From 4f05d85a22351720d860afb788cc5cdaffca92ca Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 17 Dec 2019 16:46:40 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 8 ++++++ gcc/cp/constexpr.c | 27 +++++++++++++------ gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C | 12 +++++++++ 3 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e5824d57cc0..91837d36d6e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-12-17 Jason Merrill + + 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 PR c++/92576 - redeclaration of variable template. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f3f03e7d621..87d78d26728 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 (); **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 00000000000..b94cf3099f4 --- /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" } -- 2.30.2