diff options
Diffstat (limited to 'gcc/cp/typeck2.cc')
-rw-r--r-- | gcc/cp/typeck2.cc | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index d5236d1..2644472 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -649,7 +649,7 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, else { build_init: - code = build2 (INIT_EXPR, inner_type, sub, value); + code = cp_build_init_expr (sub, value); } code = build_stmt (input_location, EXPR_STMT, code); add_stmt (code); @@ -764,7 +764,7 @@ split_nonconstant_init (tree dest, tree init) } else if (init) { - tree ie = build2 (INIT_EXPR, void_type_node, dest, init); + tree ie = cp_build_init_expr (dest, init); code = add_stmt_to_compound (ie, code); } } @@ -773,7 +773,7 @@ split_nonconstant_init (tree dest, tree init) code = build_vec_init (dest, NULL_TREE, init, /*value-init*/false, /*from array*/1, tf_warning_or_error); else - code = build2 (INIT_EXPR, TREE_TYPE (dest), dest, init); + code = cp_build_init_expr (dest, init); return code; } @@ -1464,6 +1464,7 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain) && CP_AGGREGATE_TYPE_P (type)) init = reshape_init (type, init, complain); init = digest_init_flags (type, init, flags, complain); + set_target_expr_eliding (init); /* We may have temporary materialization in a NSDMI, if the initializer has something like A{} in it. Digesting the {} could have introduced @@ -1542,6 +1543,7 @@ massage_init_elt (tree type, tree init, int nested, int flags, tree t = fold_non_dependent_init (init, complain); if (TREE_CONSTANT (t)) init = t; + set_target_expr_eliding (init); } return init; } @@ -1771,6 +1773,13 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, { gcc_assert (ce->value); next = massage_init_elt (fldtype, next, nested, flags, complain); + /* We can't actually elide the temporary when initializing a + potentially-overlapping field from a function that returns by + value. */ + if (ce->index + && TREE_CODE (next) == TARGET_EXPR + && unsafe_copy_elision_p (ce->index, next)) + TARGET_EXPR_ELIDING_P (next) = false; ++idx; } } @@ -1804,6 +1813,9 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, a class, just build one up; if it's an array, recurse. */ next = build_constructor (init_list_type_node, NULL); next = massage_init_elt (fldtype, next, nested, flags, complain); + if (TREE_CODE (next) == TARGET_EXPR + && unsafe_copy_elision_p (field, next)) + TARGET_EXPR_ELIDING_P (next) = false; /* Warn when some struct elements are implicitly initialized. */ if ((complain & tf_warning) @@ -2727,3 +2739,41 @@ require_complete_eh_spec_types (tree fntype, tree decl) } } } + +/* Record that any TARGET_EXPR in T are going to be elided in + cp_gimplify_init_expr (or sooner). */ + +void +set_target_expr_eliding (tree t) +{ + if (!t) + return; + switch (TREE_CODE (t)) + { + case TARGET_EXPR: + TARGET_EXPR_ELIDING_P (t) = true; + break; + case COMPOUND_EXPR: + set_target_expr_eliding (TREE_OPERAND (t, 1)); + break; + case COND_EXPR: + set_target_expr_eliding (TREE_OPERAND (t, 1)); + set_target_expr_eliding (TREE_OPERAND (t, 2)); + break; + + default: + break; + } +} + +/* Call the above in the process of building an INIT_EXPR. */ + +tree +cp_build_init_expr (location_t loc, tree target, tree init) +{ + set_target_expr_eliding (init); + tree ie = build2_loc (loc, INIT_EXPR, TREE_TYPE (target), + target, init); + TREE_SIDE_EFFECTS (ie) = true; + return ie; +} |