https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99859

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org,
                   |                            |mpolacek at gcc dot gnu.org,
                   |                            |ppalka at gcc dot gnu.org

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, on the #c3 testcase, if I put a breakpoint before and after
fold_nondependent_expr in finish_static_assert and temporarily in between those
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<Foo>::~intrusive_ptr (&D.2255);
Foo::dec (NON_LVALUE_EXPR <((struct intrusive_ptr *) this)->ptr>);
intrusive_ptr<Foo>::~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 when
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 return
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?

Reply via email to