c++: Don't cache constexpr functions which are passed pointers to heap or static...
authorJakub Jelinek <jakub@redhat.com>
Thu, 8 Apr 2021 15:15:39 +0000 (17:15 +0200)
committerJakub Jelinek <jakub@redhat.com>
Thu, 8 Apr 2021 15:19:12 +0000 (17:19 +0200)
commit559d2f1e0eafd96c19dc5324db1a466286c0e7fc
treeca7eba8859cf502d26615e6a956cfb86443a0732
parentca4641a3b536c9301a6dcb6cb2e26bd4717b47d9
c++: Don't cache constexpr functions which are passed pointers to heap or static vars being constructed [PR99859]

When cxx_bind_parameters_in_call is called e.g. on a method on an automatic
variable, we evaluate the argument and because ADDR_EXPR of an automatic
decl is not TREE_CONSTANT, we set *non_constant_args and don't cache it.
But when it is called on an object located on the heap (allocated using
C++20 constexpr new) where we represent it as TREE_STATIC artificial
var, or when it is called on a static var that is currently being
constructed, such ADDR_EXPRs are TREE_CONSTANT and we happily cache
such calls, but they can in those cases have side-effects in the heap
or static var objects and so caching them means such side-effects will
happen only once and not as many times as that method or function is called.
Furthermore, as Patrick mentioned in the PR, the argument doesn't need to be
just ADDR_EXPR of the heap or static var or its components, but it could be
a CONSTRUCTOR that has the ADDR_EXPR embedded anywhere.
And the incorrectly cached function doesn't need to modify the pointed vars
or their components, but some caller could be changing them in between the
call that was cached and the call that used the cached result.

The following patch fixes it by setting *non_constant_args also when
the argument contains somewhere such an ADDR_EXPR, either of a heap
artificial var or component thereof, or of a static var currently being
constructed (where for that it uses the same check as
cxx_eval_store_expression, ctx->global->values.get (...); addresses of
other static variables would be rejected by cxx_eval_store_expression
and therefore it is ok to cache such calls).

2021-04-08  Jakub Jelinek  <jakub@redhat.com>

PR c++/99859
* constexpr.c (addr_of_non_const_var): New function.
(cxx_bind_parameters_in_call): Set *non_constant_args to true
even if cp_walk_tree on arg with addr_of_non_const_var callback
returns true.

* g++.dg/cpp1y/constexpr-99859-1.C: New test.
* g++.dg/cpp1y/constexpr-99859-2.C: New test.
* g++.dg/cpp2a/constexpr-new18.C: New test.
* g++.dg/cpp2a/constexpr-new19.C: New test.
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp1y/constexpr-99859-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-99859-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/constexpr-new18.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/constexpr-new19.C [new file with mode: 0644]