diff options
author | Jason Merrill <jason@redhat.com> | 2019-12-17 16:46:40 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-12-17 16:46:40 -0500 |
commit | 4f05d85a22351720d860afb788cc5cdaffca92ca (patch) | |
tree | f09533c4151488583374ed223b5d904118a1fc44 | |
parent | 9c7b2b0ba8687f92f7beab2e3615a1107c7063db (diff) | |
download | gcc-4f05d85a22351720d860afb788cc5cdaffca92ca.zip gcc-4f05d85a22351720d860afb788cc5cdaffca92ca.tar.gz gcc-4f05d85a22351720d860afb788cc5cdaffca92ca.tar.bz2 |
PR c++/79592 - missing explanation of invalid constexpr.
We changed months back to use the pre-generic form for constexpr evaluation,
but explain_invalid_constexpr_fn was still using DECL_SAVED_TREE. This
mostly works, but misses some issues due to folding. So with this patch we
save the pre-generic form of constexpr functions even when we know they
can't produce a constant result.
* constexpr.c (register_constexpr_fundef): Do store the body of a
template instantiation that is not potentially constant.
(explain_invalid_constexpr_fn): Look it up.
(cxx_eval_call_expression): Check fundef->result.
From-SVN: r279473
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C | 12 |
3 files changed, 39 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e5824d5..91837d3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2019-12-17 Jason Merrill <jason@redhat.com> + PR c++/79592 - missing explanation of invalid constexpr. + * constexpr.c (register_constexpr_fundef): Do store the body of a + template instantiation that is not potentially constant. + (explain_invalid_constexpr_fn): Look it up. + (cxx_eval_call_expression): Check fundef->result. + +2019-12-17 Jason Merrill <jason@redhat.com> + PR c++/92576 - redeclaration of variable template. * decl.c (redeclaration_error_message): Recurse for variable templates. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f3f03e7..87d78d2 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -885,16 +885,16 @@ register_constexpr_fundef (tree fun, tree body) return NULL; } - if (!potential_rvalue_constant_expression (massaged)) - { - if (!DECL_GENERATED_P (fun)) - require_potential_rvalue_constant_expression (massaged); - return NULL; - } + bool potential = potential_rvalue_constant_expression (massaged); + if (!potential && !DECL_GENERATED_P (fun)) + require_potential_rvalue_constant_expression (massaged); if (DECL_CONSTRUCTOR_P (fun) && cx_check_missing_mem_inits (DECL_CONTEXT (fun), massaged, !DECL_GENERATED_P (fun))) + potential = false; + + if (!potential && !DECL_GENERATED_P (fun)) return NULL; /* Create the constexpr function table if necessary. */ @@ -917,6 +917,12 @@ register_constexpr_fundef (tree fun, tree body) if (clear_ctx) DECL_CONTEXT (DECL_RESULT (fun)) = NULL_TREE; + if (!potential) + /* For a template instantiation, we want to remember the pre-generic body + for explain_invalid_constexpr_fn, but do tell cxx_eval_call_expression + that it doesn't need to bother trying to expand the function. */ + entry.result = error_mark_node; + gcc_assert (*slot == NULL); *slot = ggc_alloc<constexpr_fundef> (); **slot = entry; @@ -962,11 +968,15 @@ explain_invalid_constexpr_fn (tree fun) { /* Then if it's OK, the body. */ if (!DECL_DECLARED_CONSTEXPR_P (fun) - && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fun))) + && DECL_DEFAULTED_FN (fun)) explain_implicit_non_constexpr (fun); else { - body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun)); + if (constexpr_fundef *fd = retrieve_constexpr_fundef (fun)) + body = fd->body; + else + body = DECL_SAVED_TREE (fun); + body = massage_constexpr_body (fun, body); require_potential_rvalue_constant_expression (body); if (DECL_CONSTRUCTOR_P (fun)) cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true); @@ -1919,6 +1929,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, { new_call.fundef = retrieve_constexpr_fundef (fun); if (new_call.fundef == NULL || new_call.fundef->body == NULL + || new_call.fundef->result == error_mark_node || fun == current_function_decl) { if (!ctx->quiet) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C new file mode 100644 index 0000000..b94cf30 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C @@ -0,0 +1,12 @@ +// PR c++/79592 +// { dg-do compile { target c++11 } } + +struct pthread_mutex { + void *m_ptr; +}; + +struct M { + pthread_mutex m = { ((void *) 1LL) }; // { dg-error "reinterpret_cast" } +}; + +constexpr M m; // { dg-error "M::M" } |