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);