c++: be stricter about constinit [CWG2543]

DR 2543 clarifies that constinit variables should follow the language, and
diagnose non-constant initializers (according to [expr.const]) even if they
can actually initialize the variables statically.

	DR 2543

gcc/cp/ChangeLog:

	* constexpr.cc (cxx_eval_outermost_constant_expr): Preserve
	TARGET_EXPR flags.
	(potential_constant_expression_1): Check TARGET_EXPR_ELIDING_P.
	* typeck2.cc (store_init_value): Diagnose constinit sooner.

gcc/testsuite/ChangeLog:

	* g++.dg/DRs/dr2543.C: New test.
This commit is contained in:
Jason Merrill 2023-02-06 15:08:17 -08:00
parent 688fdde2f1
commit 8d46516a61
3 changed files with 48 additions and 24 deletions

View file

@ -8448,6 +8448,17 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
}
}
if (TREE_CODE (t) == TARGET_EXPR
&& TREE_CODE (r) == TARGET_EXPR)
{
/* Preserve this flag for potential_constant_expression, and the others
for good measure. */
TARGET_EXPR_ELIDING_P (r) = TARGET_EXPR_ELIDING_P (t);
TARGET_EXPR_IMPLICIT_P (r) = TARGET_EXPR_IMPLICIT_P (t);
TARGET_EXPR_LIST_INIT_P (r) = TARGET_EXPR_LIST_INIT_P (t);
TARGET_EXPR_DIRECT_INIT_P (r) = TARGET_EXPR_DIRECT_INIT_P (t);
}
/* Remember the original location if that wouldn't need a wrapper. */
if (location_t loc = EXPR_LOCATION (t))
protected_set_expr_location (r, loc);
@ -9774,6 +9785,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case TARGET_EXPR:
if (!TARGET_EXPR_DIRECT_INIT_P (t)
&& !TARGET_EXPR_ELIDING_P (t)
&& !literal_type_p (TREE_TYPE (t)))
{
if (flags & tf_error)

View file

@ -843,23 +843,45 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
bool const_init;
tree oldval = value;
if (DECL_DECLARED_CONSTEXPR_P (decl)
|| DECL_DECLARED_CONSTINIT_P (decl)
|| (DECL_IN_AGGR_P (decl)
&& DECL_INITIALIZED_IN_CLASS_P (decl)))
{
value = fold_non_dependent_expr (value, tf_warning_or_error,
/*manifestly_const_eval=*/true,
decl);
if (value == error_mark_node)
;
/* Diagnose a non-constant initializer for constexpr variable or
non-inline in-class-initialized static data member. */
if (!require_constant_expression (value))
value = error_mark_node;
else if (processing_template_decl)
/* In a template we might not have done the necessary
transformations to make value actually constant,
e.g. extend_ref_init_temps. */
value = maybe_constant_init (value, decl, true);
else if (!is_constant_expression (value))
{
/* Maybe we want to give this message for constexpr variables as
well, but that will mean a lot of testsuite adjustment. */
if (DECL_DECLARED_CONSTINIT_P (decl))
error_at (location_of (decl),
"%<constinit%> variable %qD does not have a "
"constant initializer", decl);
require_constant_expression (value);
value = error_mark_node;
}
else
value = cxx_constant_init (value, decl);
{
value = maybe_constant_init (value, decl, true);
/* In a template we might not have done the necessary
transformations to make value actually constant,
e.g. extend_ref_init_temps. */
if (!processing_template_decl
&& !TREE_CONSTANT (value))
{
if (DECL_DECLARED_CONSTINIT_P (decl))
error_at (location_of (decl),
"%<constinit%> variable %qD does not have a "
"constant initializer", decl);
value = cxx_constant_init (value, decl);
}
}
}
else
value = fold_non_dependent_init (value, tf_warning_or_error,
@ -875,22 +897,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
if (!TYPE_REF_P (type))
TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
if (!const_init)
{
/* [dcl.constinit]/2 "If a variable declared with the constinit
specifier has dynamic initialization, the program is
ill-formed." */
if (DECL_DECLARED_CONSTINIT_P (decl))
{
error_at (location_of (decl),
"%<constinit%> variable %qD does not have a constant "
"initializer", decl);
if (require_constant_expression (value))
cxx_constant_init (value, decl);
value = error_mark_node;
}
else
value = oldval;
}
value = oldval;
}
/* Don't fold initializers of automatic variables in constexpr functions,
that might fold away something that needs to be diagnosed at constexpr

View file

@ -0,0 +1,5 @@
// CWG 2543
// { dg-do compile { target c++20 } }
float f;
constinit int * pi = (int*) &f; // { dg-error "constant" } reinterpret_cast, not constant-initialized