c++: Fix ICE with inline variable in template [PR97975]
In this test, we have static inline const int c = b; in a class template, and we call store_init_value as usual. There, the value is IMPLICIT_CONV_EXPR<const float>(b) which is is_nondependent_static_init_expression but isn't is_nondependent_constant_expression (they only differ in STRICT). We call fold_non_dependent_expr, but that just returns the expression because it only instantiates is_nondependent_constant_expression expressions. Since we're not checking the initializer of a constexpr variable, we go on to call maybe_constant_init, whereupon we crash because it tries to evaluate all is_nondependent_static_init_expression expressions, which our value is, but it still contains a template code. I think the fix is to call fold_non_dependent_init instead of maybe_constant_init, and only call fold_non_dependent_expr on the "this is a constexpr variable" path so as to avoid instantiating twice in a row. Outside a template this should also avoid evaluating the value twice. gcc/cp/ChangeLog: PR c++/97975 * constexpr.c (fold_non_dependent_init): Add a tree parameter. Use it. * cp-tree.h (fold_non_dependent_init): Add a tree parameter with a default value. * typeck2.c (store_init_value): Call fold_non_dependent_expr only when checking the initializer for constexpr variables. Call fold_non_dependent_init instead of maybe_constant_init. gcc/testsuite/ChangeLog: PR c++/97975 * g++.dg/cpp1z/inline-var8.C: New test.
This commit is contained in:
parent
4192ffd74c
commit
69bf1c7d5e
@ -7271,7 +7271,8 @@ maybe_fold_non_dependent_expr (tree expr,
|
||||
tree
|
||||
fold_non_dependent_init (tree t,
|
||||
tsubst_flags_t complain /*=tf_warning_or_error*/,
|
||||
bool manifestly_const_eval /*=false*/)
|
||||
bool manifestly_const_eval /*=false*/,
|
||||
tree object /* = NULL_TREE */)
|
||||
{
|
||||
if (t == NULL_TREE)
|
||||
return NULL_TREE;
|
||||
@ -7279,7 +7280,7 @@ fold_non_dependent_init (tree t,
|
||||
if (processing_template_decl)
|
||||
{
|
||||
t = fold_non_dependent_expr_template (t, complain,
|
||||
manifestly_const_eval, NULL_TREE);
|
||||
manifestly_const_eval, object);
|
||||
/* maybe_constant_init does this stripping, so do it here too. */
|
||||
if (TREE_CODE (t) == TARGET_EXPR)
|
||||
{
|
||||
@ -7290,7 +7291,7 @@ fold_non_dependent_init (tree t,
|
||||
return t;
|
||||
}
|
||||
|
||||
return maybe_constant_init (t, NULL_TREE, manifestly_const_eval);
|
||||
return maybe_constant_init (t, object, manifestly_const_eval);
|
||||
}
|
||||
|
||||
/* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
|
||||
|
@ -8014,7 +8014,7 @@ extern tree maybe_fold_non_dependent_expr (tree,
|
||||
tsubst_flags_t = tf_warning_or_error);
|
||||
extern tree fold_non_dependent_init (tree,
|
||||
tsubst_flags_t = tf_warning_or_error,
|
||||
bool = false);
|
||||
bool = false, tree = NULL_TREE);
|
||||
extern tree fold_simple (tree);
|
||||
extern bool reduced_constant_expression_p (tree);
|
||||
extern bool is_instantiation_of_constexpr (tree);
|
||||
|
@ -744,11 +744,13 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
|
||||
{
|
||||
bool const_init;
|
||||
tree oldval = value;
|
||||
value = fold_non_dependent_expr (value, tf_warning_or_error, true, decl);
|
||||
if (DECL_DECLARED_CONSTEXPR_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);
|
||||
/* Diagnose a non-constant initializer for constexpr variable or
|
||||
non-inline in-class-initialized static data member. */
|
||||
if (!require_constant_expression (value))
|
||||
@ -762,7 +764,8 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
|
||||
value = cxx_constant_init (value, decl);
|
||||
}
|
||||
else
|
||||
value = maybe_constant_init (value, decl, true);
|
||||
value = fold_non_dependent_init (value, tf_warning_or_error,
|
||||
/*manifestly_const_eval=*/true, decl);
|
||||
if (TREE_CODE (value) == CONSTRUCTOR && cp_has_mutable_p (type))
|
||||
/* Poison this CONSTRUCTOR so it can't be copied to another
|
||||
constexpr variable. */
|
||||
|
17
gcc/testsuite/g++.dg/cpp1z/inline-var8.C
Normal file
17
gcc/testsuite/g++.dg/cpp1z/inline-var8.C
Normal file
@ -0,0 +1,17 @@
|
||||
// PR c++/97975
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
template <class>
|
||||
class A
|
||||
{
|
||||
static const float b;
|
||||
static inline const int c = b;
|
||||
};
|
||||
|
||||
A<int> a;
|
||||
|
||||
struct B
|
||||
{
|
||||
static const float b;
|
||||
static inline const int c = b;
|
||||
};
|
Loading…
Reference in New Issue
Block a user