Commit 4f05d85a by Jason Merrill Committed by Jason Merrill

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
parent 9c7b2b0b
2019-12-17 Jason Merrill <jason@redhat.com> 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. PR c++/92576 - redeclaration of variable template.
* decl.c (redeclaration_error_message): Recurse for variable * decl.c (redeclaration_error_message): Recurse for variable
templates. templates.
......
...@@ -885,16 +885,16 @@ register_constexpr_fundef (tree fun, tree body) ...@@ -885,16 +885,16 @@ register_constexpr_fundef (tree fun, tree body)
return NULL; return NULL;
} }
if (!potential_rvalue_constant_expression (massaged)) bool potential = potential_rvalue_constant_expression (massaged);
{ if (!potential && !DECL_GENERATED_P (fun))
if (!DECL_GENERATED_P (fun)) require_potential_rvalue_constant_expression (massaged);
require_potential_rvalue_constant_expression (massaged);
return NULL;
}
if (DECL_CONSTRUCTOR_P (fun) if (DECL_CONSTRUCTOR_P (fun)
&& cx_check_missing_mem_inits (DECL_CONTEXT (fun), && cx_check_missing_mem_inits (DECL_CONTEXT (fun),
massaged, !DECL_GENERATED_P (fun))) massaged, !DECL_GENERATED_P (fun)))
potential = false;
if (!potential && !DECL_GENERATED_P (fun))
return NULL; return NULL;
/* Create the constexpr function table if necessary. */ /* Create the constexpr function table if necessary. */
...@@ -917,6 +917,12 @@ register_constexpr_fundef (tree fun, tree body) ...@@ -917,6 +917,12 @@ register_constexpr_fundef (tree fun, tree body)
if (clear_ctx) if (clear_ctx)
DECL_CONTEXT (DECL_RESULT (fun)) = NULL_TREE; 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); gcc_assert (*slot == NULL);
*slot = ggc_alloc<constexpr_fundef> (); *slot = ggc_alloc<constexpr_fundef> ();
**slot = entry; **slot = entry;
...@@ -962,11 +968,15 @@ explain_invalid_constexpr_fn (tree fun) ...@@ -962,11 +968,15 @@ explain_invalid_constexpr_fn (tree fun)
{ {
/* Then if it's OK, the body. */ /* Then if it's OK, the body. */
if (!DECL_DECLARED_CONSTEXPR_P (fun) if (!DECL_DECLARED_CONSTEXPR_P (fun)
&& !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fun))) && DECL_DEFAULTED_FN (fun))
explain_implicit_non_constexpr (fun); explain_implicit_non_constexpr (fun);
else 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); require_potential_rvalue_constant_expression (body);
if (DECL_CONSTRUCTOR_P (fun)) if (DECL_CONSTRUCTOR_P (fun))
cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true); cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true);
...@@ -1919,6 +1929,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, ...@@ -1919,6 +1929,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
{ {
new_call.fundef = retrieve_constexpr_fundef (fun); new_call.fundef = retrieve_constexpr_fundef (fun);
if (new_call.fundef == NULL || new_call.fundef->body == NULL if (new_call.fundef == NULL || new_call.fundef->body == NULL
|| new_call.fundef->result == error_mark_node
|| fun == current_function_decl) || fun == current_function_decl)
{ {
if (!ctx->quiet) if (!ctx->quiet)
......
// 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" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment