From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 8538E3858028; Wed, 7 Apr 2021 11:39:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8538E3858028 From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/99859] constexpr evaluation with member function is incorrect Date: Wed, 07 Apr 2021 11:39:32 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 11.0 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: cc Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 Apr 2021 11:39:32 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D99859 Jakub Jelinek changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at gcc dot gnu.org, | |mpolacek at gcc dot gnu.or= g, | |ppalka at gcc dot gnu.org --- Comment #4 from Jakub Jelinek --- So, on the #c3 testcase, if I put a breakpoint before and after fold_nondependent_expr in finish_static_assert and temporarily in between t= hose two breakpoints put a breakpoint on cxx_eval_call_expression and cxx_eval_increment_expression, it is clear that while cxx_eval_call_expression is called on ... intrusive_ptr::~intrusive_ptr (&D.2255); Foo::dec (NON_LVALUE_EXPR <((struct intrusive_ptr *) this)->ptr>); intrusive_ptr::~intrusive_ptr (&a); Foo::dec (NON_LVALUE_EXPR <((struct intrusive_ptr *) this)->ptr>); where during the first Foo::dec call evaluation cxx_eval_increment_expression is called on --((struct Foo *) this)->count_ during the second Foo::dec call we use cached result (1) and don't evaluate= the body at all. But the body of the constexpr method has side-effects on the class it is called on (and the result is incorrect too), on the testcase wh= en not evaluating at compile time but runtime the first Foo::dec shall predecrement count_ from 2 to 1 (thus return 1) and the second one should predecrement count_ from 1 to 0 (thus return 0). For the constexpr new I had to add the /* If the call allocated some heap object that hasn't been deallocated during the call, or if it deallocated some heap object it has not allocated, the call isn't really stateless for the constexpr evaluation and should not be cached. It is fine if the call allocates something and deallocates it too. */ setting of cacheable to false in some cases, but this PR let's me wonder if= it is ever ok to cache constexpr results and what the standard actually says (= if constexpr/consteval functions can have side-effects besides computing a ret= urn value (I believe they can't just change some unrelated constexpr variable, right?) and ditto for constexpr/consteval methods. So, e.g. shall we remember during the constexpr evaluation if the currently evaluated constexpr function has side-effects to something other than its automatic variables or return value and if so, make it effectively non-cacheable?=