diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-03-04 09:51:31 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-03-04 09:51:31 +0100 |
commit | 9d5730dee4f42e94004b38f8f4862c0b1f4d964c (patch) | |
tree | ba7604a225622a2bfc6140a8f3fd0abdd837af8e | |
parent | 739e7ebb3d378ece25d64b39baae47c584253498 (diff) | |
download | gcc-9d5730dee4f42e94004b38f8f4862c0b1f4d964c.zip gcc-9d5730dee4f42e94004b38f8f4862c0b1f4d964c.tar.gz gcc-9d5730dee4f42e94004b38f8f4862c0b1f4d964c.tar.bz2 |
c++: Don't defer local statics initialized with constant expressions [PR108702]
The stmtexpr19.C testcase used to be rejected as it has a static
variable in statement expression in constexpr context, but as that
static variable is initialized by constant expression, when P2647R1
was implemented we agreed to make it valid.
Now, as reported, the testcase compiles fine, but doesn't actually link
because the static variable isn't defined anywhere, and with -flto ICEs
because of this problem. This is because we never
varpool_node::finalize_decl those vars, the constant expression in which
the DECL_EXPR is present for the static VAR_DECL is folded (constant
evaluated) into just the address of the VAR_DECL.
Now, similar testcase included below (do we want to include it in the
testsuite too?) works fine, because in
cp_finish_decl -> make_rtl_for_nonlocal_decl
we have since PR70353 fix:
/* We defer emission of local statics until the corresponding
DECL_EXPR is expanded. But with constexpr its function might never
be expanded, so go ahead and tell cgraph about the variable now. */
defer_p = ((DECL_FUNCTION_SCOPE_P (decl)
&& !var_in_maybe_constexpr_fn (decl))
|| DECL_VIRTUAL_P (decl));
and so don't defer them in constexpr/consteval functions. The following
patch calls rest_of_decl_compilation which make_rtl_for_nonlocal_decl didn't
call when encountering DECL_EXPRs of such vars during constant evaluation
if they weren't finalized yet.
2023-03-04 Jakub Jelinek <jakub@redhat.com>
PR c++/108702
* constexpr.cc: Include toplev.h.
(cxx_eval_constant_expression) <case DECL_EXPR>: When seeing a local
static initialized by constant expression outside of a constexpr
function which has been deferred by make_rtl_for_nonlocal_decl,
call rest_of_decl_compilation on it.
* g++.dg/ext/stmtexpr19.C: Use dg-do link rather than dg-do compile.
-rw-r--r-- | gcc/cp/constexpr.cc | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/stmtexpr19.C | 2 |
2 files changed, 20 insertions, 1 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index acf9847..364695b 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "fold-const.h" #include "intl.h" +#include "toplev.h" static bool verify_constant (tree, bool, bool *, bool *); #define VERIFY_CONSTANT(X) \ @@ -7127,6 +7128,24 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, break; } + /* make_rtl_for_nonlocal_decl could have deferred emission of + a local static var, but if it appears in a statement expression + which is constant expression evaluated to e.g. just the address + of the variable, its DECL_EXPR will never be seen during + gimple lowering's record_vars_into as the statement expression + will not be in the IL at all. */ + if (VAR_P (r) + && TREE_STATIC (r) + && !DECL_REALLY_EXTERN (r) + && DECL_FUNCTION_SCOPE_P (r) + && !var_in_maybe_constexpr_fn (r) + && decl_constant_var_p (r)) + { + varpool_node *node = varpool_node::get (r); + if (node == NULL || !node->definition) + rest_of_decl_compilation (r, 0, at_eof); + } + if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r))) { diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr19.C b/gcc/testsuite/g++.dg/ext/stmtexpr19.C index be395b6..5355c15 100644 --- a/gcc/testsuite/g++.dg/ext/stmtexpr19.C +++ b/gcc/testsuite/g++.dg/ext/stmtexpr19.C @@ -1,6 +1,6 @@ // PR c++/81073 // { dg-options "" } -// { dg-do compile { target c++11 } } +// { dg-do link { target c++11 } } struct test { const int *addr; }; |