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
This commit is contained in:
Jason Merrill 2019-12-17 16:46:40 -05:00 committed by Jason Merrill
parent 9c7b2b0ba8
commit 4f05d85a22
3 changed files with 39 additions and 8 deletions

View File

@ -1,3 +1,11 @@
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.

View File

@ -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)

View File

@ -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" }