@@ -7779,6 +7779,7 @@ extern bool array_of_runtime_bound_p (tree);
extern bool vla_type_p (tree);
extern tree build_array_copy (tree);
extern tree build_vec_init_expr (tree, tree, tsubst_flags_t);
+extern tree expand_vec_init_expr (tree, tree, tsubst_flags_t);
extern void diagnose_non_constexpr_vec_init (tree);
extern tree hash_tree_cons (tree, tree, tree);
extern tree hash_tree_chain (tree, tree);
@@ -3020,8 +3020,7 @@ reduced_constant_expression_p (tree t)
if (TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
/* An initialized vector would have a VECTOR_CST. */
return false;
- else if (cxx_dialect >= cxx20
- && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+ else if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
{
/* There must be a valid constant initializer at every array
index. */
@@ -4955,8 +4954,36 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t,
{
tree atype = TREE_TYPE (t);
tree init = VEC_INIT_EXPR_INIT (t);
- tree r = cxx_eval_vec_init_1 (ctx, atype, init,
- VEC_INIT_EXPR_VALUE_INIT (t),
+ bool value_init = VEC_INIT_EXPR_VALUE_INIT (t);
+ if (!init || !BRACE_ENCLOSED_INITIALIZER_P (init))
+ ;
+ else if (CONSTRUCTOR_NELTS (init) == 0)
+ {
+ /* Handle {} as value-init. */
+ init = NULL_TREE;
+ value_init = true;
+ }
+ else
+ {
+ /* This is a more complicated case, like needing to loop over trailing
+ elements; call build_vec_init and evaluate the result. */
+ tsubst_flags_t complain = ctx->quiet ? tf_none : tf_warning_or_error;
+ constexpr_ctx new_ctx = *ctx;
+ if (!ctx->object)
+ {
+ /* We want to have an initialization target for an VEC_INIT_EXPR.
+ If we don't already have one in CTX, use the VEC_INIT_EXPR_SLOT. */
+ new_ctx.object = VEC_INIT_EXPR_SLOT (t);
+ tree ctor = new_ctx.ctor = build_constructor (atype, NULL);
+ CONSTRUCTOR_NO_CLEARING (ctor) = true;
+ ctx->global->values.put (new_ctx.object, ctor);
+ ctx = &new_ctx;
+ }
+ init = expand_vec_init_expr (ctx->object, t, complain);
+ return cxx_eval_constant_expression (ctx, init, lval, non_constant_p,
+ overflow_p);
+ }
+ tree r = cxx_eval_vec_init_1 (ctx, atype, init, value_init,
lval, non_constant_p, overflow_p);
if (*non_constant_p)
return t;
@@ -462,21 +462,14 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
case VEC_INIT_EXPR:
{
- location_t loc = input_location;
- tree init = VEC_INIT_EXPR_INIT (*expr_p);
- int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
- gcc_assert (EXPR_HAS_LOCATION (*expr_p));
- input_location = EXPR_LOCATION (*expr_p);
- *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
- init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
- from_array,
- tf_warning_or_error);
+ *expr_p = expand_vec_init_expr (NULL_TREE, *expr_p,
+ tf_warning_or_error);
+
hash_set<tree> pset;
cp_walk_tree (expr_p, cp_fold_r, &pset, NULL);
cp_genericize_tree (expr_p, false);
copy_if_shared (expr_p);
ret = GS_OK;
- input_location = loc;
}
break;
@@ -4337,12 +4337,19 @@ build_vec_init (tree base, tree maxindex, tree init,
&& from_array != 2)
init = TARGET_EXPR_INITIAL (init);
+ if (init && TREE_CODE (init) == VEC_INIT_EXPR)
+ {
+ gcc_checking_assert (false);
+ init = VEC_INIT_EXPR_INIT (init);
+ }
+
bool direct_init = false;
if (from_array && init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CONSTRUCTOR_NELTS (init) == 1)
{
tree elt = CONSTRUCTOR_ELT (init, 0)->value;
- if (TREE_CODE (TREE_TYPE (elt)) == ARRAY_TYPE)
+ if (TREE_CODE (TREE_TYPE (elt)) == ARRAY_TYPE
+ && TREE_CODE (elt) != VEC_INIT_EXPR)
{
direct_init = DIRECT_LIST_INIT_P (init);
init = elt;
@@ -4516,6 +4523,8 @@ build_vec_init (tree base, tree maxindex, tree init,
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
if (digested)
one_init = build2 (INIT_EXPR, type, baseref, elt);
+ else if (TREE_CODE (elt) == VEC_INIT_EXPR)
+ one_init = expand_vec_init_expr (baseref, elt, complain);
else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
one_init = build_aggr_init (baseref, elt, 0, complain);
else
@@ -756,13 +756,11 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
else if (init == void_type_node)
return build_value_init (inner_type, complain);
- gcc_assert (init == NULL_TREE
- || (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (init))));
-
releasing_vec argvec;
- if (init)
+ if (init && !BRACE_ENCLOSED_INITIALIZER_P (init))
{
+ gcc_assert (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (init)));
tree init_type = strip_array_types (TREE_TYPE (init));
tree dummy = build_dummy_object (init_type);
if (!lvalue_p (init))
@@ -788,25 +786,28 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
tree
build_vec_init_expr (tree type, tree init, tsubst_flags_t complain)
{
- tree slot;
- bool value_init = false;
- tree elt_init;
- if (init && TREE_CODE (init) == CONSTRUCTOR)
+ if (init && TREE_CODE (init) == VEC_INIT_EXPR)
{
- gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
- /* We built any needed constructor calls in digest_init. */
- elt_init = init;
+ gcc_checking_assert (false);
+ return init;
}
+
+ tree elt_init;
+ if (init && TREE_CODE (init) == CONSTRUCTOR
+ && !BRACE_ENCLOSED_INITIALIZER_P (init))
+ /* We built any needed constructor calls in digest_init. */
+ elt_init = init;
else
elt_init = build_vec_init_elt (type, init, complain);
+ bool value_init = false;
if (init == void_type_node)
{
value_init = true;
init = NULL_TREE;
}
- slot = build_local_temp (type);
+ tree slot = build_local_temp (type);
init = build2 (VEC_INIT_EXPR, type, slot, init);
TREE_SIDE_EFFECTS (init) = true;
SET_EXPR_LOCATION (init, input_location);
@@ -819,6 +820,23 @@ build_vec_init_expr (tree type, tree init, tsubst_flags_t complain)
return init;
}
+/* Call build_vec_init to expand VEC_INIT into TARGET (for which NULL_TREE
+ means VEC_INIT_EXPR_SLOT). */
+
+tree
+expand_vec_init_expr (tree target, tree vec_init, tsubst_flags_t complain)
+{
+ iloc_sentinel ils = EXPR_LOCATION (vec_init);
+
+ if (!target)
+ target = VEC_INIT_EXPR_SLOT (vec_init);
+ tree init = VEC_INIT_EXPR_INIT (vec_init);
+ int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
+ return build_vec_init (target, NULL_TREE, init,
+ VEC_INIT_EXPR_VALUE_INIT (vec_init),
+ from_array, complain);
+}
+
/* Give a helpful diagnostic for a non-constexpr VEC_INIT_EXPR in a context
that requires a constant expression. */
@@ -1317,6 +1317,7 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain)
#define PICFLAG_NOT_ALL_CONSTANT 2
#define PICFLAG_NOT_ALL_SIMPLE 4
#define PICFLAG_SIDE_EFFECTS 8
+#define PICFLAG_VEC_INIT 16
/* Given an initializer INIT, return the flag (PICFLAG_*) which better
describe it. */
@@ -1460,10 +1461,19 @@ process_init_constructor_array (tree type, tree init, int nested, int flags,
if (next)
{
- picflags |= picflag_from_initializer (next);
- if (len > i+1
+ if (next != error_mark_node
+ && ! seen_error () // Improves error-recovery on anew5.C.
&& (initializer_constant_valid_p (next, TREE_TYPE (next))
- == null_pointer_node))
+ != null_pointer_node))
+ {
+ /* Use VEC_INIT_EXPR for non-constant initialization of
+ trailing elements with no explicit initializers. */
+ picflags |= PICFLAG_VEC_INIT;
+ break;
+ }
+
+ picflags |= picflag_from_initializer (next);
+ if (len > i+1)
{
tree range = build2 (RANGE_EXPR, size_type_node,
build_int_cst (size_type_node, i),
@@ -1858,6 +1868,13 @@ process_init_constructor (tree type, tree init, int nested, int flags,
if (!(picflags & PICFLAG_NOT_ALL_SIMPLE))
TREE_STATIC (init) = 1;
}
+ if (picflags & PICFLAG_VEC_INIT)
+ {
+ /* Defer default-initialization of array elements with no corresponding
+ initializer-clause until later so we can use a loop. */
+ TREE_TYPE (init) = init_list_type_node;
+ init = build_vec_init_expr (type, init, complain);
+ }
return init;
}
new file mode 100644
@@ -0,0 +1,16 @@
+// PR c++/92385
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump-times "item::item" 1 "gimple" } }
+
+struct item {
+ int i;
+ item();
+};
+
+struct item_array {
+ item a[10];
+ item_array();
+};
+
+item_array::item_array() : a{} {}