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

--- Comment #9 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #6)
> The argument is a pointer.
> Now, I bet a pointer to an automatic variable will be seen as non-constant
> and so in that case we might be ok.
> If the argument is a pointer to some global constexpr variable, dunno.

FWIW I think this is PR80039.  I think we might have to worry about this case
only when evaluating the constructor of the global constexpr variable.

> Why does it work for:
> constexpr int foo(int* x) { return ++*x; }
> struct S { constexpr S() : a(0) { foo(&a); foo(&a); } int a; };
> constexpr S s;
> static_assert (s.a == 2);
> though?  The argument to foo after constexpr processing it is &s.a which is
> TREE_CONSTANT too, yet we don't cache the calls.

Hmm, seems because ctx->strict is not set when the initialization of s gets
evaluated in this case.   But it breaks if we instead do "constexpr S s = S();"

> And, on this testcase the argument is a heap pointer which during constexpr
> evaluation we pretend it is constant.
> So maybe cxx_bind_parameters_in_call should set *non_constant_args also when
> arg is ADDR_EXPR of something with heap_*identifier* VAR_DECL as base?

I think we'd also have to look inside TREE_CONSTANT CONSTRUCTORs to see if
they're storing a pointer to such a variable, so that we also suppress caching
for cases like:

constexpr int foo(auto x) { return ++*x.p; }
struct S {
  int a = 0;

  constexpr S() {
    struct R { int* p; };
    foo(R{&a});
    foo(R{&a});
  }
};
constexpr S s = S();
static_assert (s.a == 2);

Reply via email to