aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c84
1 files changed, 49 insertions, 35 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 2a7dfe2b..7c7b810 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -4292,7 +4292,9 @@ finish_length_check (tree atype, tree iterator, tree obase, unsigned n)
tree
build_vec_init (tree base, tree maxindex, tree init,
bool explicit_value_init_p,
- int from_array, tsubst_flags_t complain)
+ int from_array,
+ tsubst_flags_t complain,
+ vec<tree, va_gc>** flags /* = nullptr */)
{
tree rval;
tree base2 = NULL_TREE;
@@ -4310,7 +4312,6 @@ build_vec_init (tree base, tree maxindex, tree init,
tree stmt_expr;
tree compound_stmt;
int destroy_temps;
- tree try_block = NULL_TREE;
HOST_WIDE_INT num_initialized_elts = 0;
bool is_global;
tree obase = base;
@@ -4447,7 +4448,9 @@ build_vec_init (tree base, tree maxindex, tree init,
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
rval = get_temp_regvar (ptype, base);
base = get_temp_regvar (ptype, rval);
- iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
+ tree iterator_targ = get_target_expr (maxindex);
+ add_stmt (iterator_targ);
+ iterator = TARGET_EXPR_SLOT (iterator_targ);
/* If initializing one array from another, initialize element by
element. We rely upon the below calls to do the argument
@@ -4470,7 +4473,37 @@ build_vec_init (tree base, tree maxindex, tree init,
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
&& from_array != 2)
{
- try_block = begin_try_block ();
+ tree e;
+ tree m = cp_build_binary_op (input_location,
+ MINUS_EXPR, maxindex, iterator,
+ complain);
+
+ /* Flatten multi-dimensional array since build_vec_delete only
+ expects one-dimensional array. */
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ m = cp_build_binary_op (input_location,
+ MULT_EXPR, m,
+ /* Avoid mixing signed and unsigned. */
+ convert (TREE_TYPE (m),
+ array_type_nelts_total (type)),
+ complain);
+
+ e = build_vec_delete_1 (input_location, rval, m,
+ inner_elt_type, sfk_complete_destructor,
+ /*use_global_delete=*/0, complain);
+ if (e == error_mark_node)
+ errors = true;
+ TARGET_EXPR_CLEANUP (iterator_targ) = e;
+ CLEANUP_EH_ONLY (iterator_targ) = true;
+
+ /* Since we push this cleanup before doing any initialization, cleanups
+ for any temporaries in the initialization are naturally within our
+ cleanup region, so we don't want wrap_temporary_cleanups to do
+ anything for arrays. But if the array is a subobject, we need to
+ tell split_nonconstant_init how to turn off this cleanup in favor of
+ the cleanup for the complete object. */
+ if (flags)
+ vec_safe_push (*flags, build_tree_list (iterator, maxindex));
}
/* Should we try to create a constant initializer? */
@@ -4520,11 +4553,10 @@ build_vec_init (tree base, tree maxindex, tree init,
num_initialized_elts++;
- 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);
+ one_init = expand_vec_init_expr (baseref, elt, complain, flags);
else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
one_init = build_aggr_init (baseref, elt, 0, complain);
else
@@ -4560,7 +4592,6 @@ build_vec_init (tree base, tree maxindex, tree init,
if (one_init)
finish_expr_stmt (one_init);
- current_stmt_tree ()->stmts_are_full_exprs_p = 0;
one_init = cp_build_unary_op (PREINCREMENT_EXPR, base, false,
complain);
@@ -4782,6 +4813,17 @@ build_vec_init (tree base, tree maxindex, tree init,
}
}
+ /* [class.temporary]: "There are three contexts in which temporaries are
+ destroyed at a different point than the end of the full-
+ expression. The first context is when a default constructor is called
+ to initialize an element of an array with no corresponding
+ initializer. The second context is when a copy constructor is called
+ to copy an element of an array while the entire array is copied. In
+ either case, if the constructor has one or more default arguments, the
+ destruction of every temporary created in a default argument is
+ sequenced before the construction of the next array element, if any."
+
+ So, for this loop, statements are full-expressions. */
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
if (elt_init && !errors)
elt_init = build2 (COMPOUND_EXPR, void_type_node, elt_init, decr);
@@ -4799,34 +4841,6 @@ build_vec_init (tree base, tree maxindex, tree init,
finish_for_stmt (for_stmt);
}
- /* Make sure to cleanup any partially constructed elements. */
- if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
- && from_array != 2)
- {
- tree e;
- tree m = cp_build_binary_op (input_location,
- MINUS_EXPR, maxindex, iterator,
- complain);
-
- /* Flatten multi-dimensional array since build_vec_delete only
- expects one-dimensional array. */
- if (TREE_CODE (type) == ARRAY_TYPE)
- m = cp_build_binary_op (input_location,
- MULT_EXPR, m,
- /* Avoid mixing signed and unsigned. */
- convert (TREE_TYPE (m),
- array_type_nelts_total (type)),
- complain);
-
- finish_cleanup_try_block (try_block);
- e = build_vec_delete_1 (input_location, rval, m,
- inner_elt_type, sfk_complete_destructor,
- /*use_global_delete=*/0, complain);
- if (e == error_mark_node)
- errors = true;
- finish_cleanup (e, try_block);
- }
-
/* The value of the array initialization is the array itself, RVAL
is a pointer to the first element. */
finish_stmt_expr_expr (rval, stmt_expr);