diff options
-rw-r--r-- | gcc/cp/constexpr.c | 35 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 13 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/init.c | 11 | ||||
-rw-r--r-- | gcc/cp/tree.c | 44 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/array61.C | 16 |
7 files changed, 112 insertions, 31 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 72be45c..4a4b347 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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; diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 27e78ee..e4f2442 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -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; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 10ca809..0a3697f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 2cab4b4..2a7dfe2b 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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 diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 6199801..8bd1964 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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. */ diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 84cef54..3d4d35e 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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; } diff --git a/gcc/testsuite/g++.dg/init/array61.C b/gcc/testsuite/g++.dg/init/array61.C new file mode 100644 index 0000000..eaf535c --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array61.C @@ -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{} {} |