aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/cp-gimplify.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/cp-gimplify.cc')
-rw-r--r--gcc/cp/cp-gimplify.cc31
1 files changed, 28 insertions, 3 deletions
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 83ba128..92cd309 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -952,6 +952,28 @@ cp_genericize_target_expr (tree *stmt_p)
gcc_assert (!DECL_INITIAL (slot));
}
+/* Similar to if (target_expr_needs_replace) replace_decl, but TP is the
+ TARGET_EXPR_INITIAL, and this also updates *_SLOT. We need this extra
+ replacement when cp_folding TARGET_EXPR to preserve the invariant that
+ AGGR_INIT_EXPR_SLOT agrees with the enclosing TARGET_EXPR_SLOT. */
+
+bool
+maybe_replace_decl (tree *tp, tree decl, tree replacement)
+{
+ if (!*tp || !VOID_TYPE_P (TREE_TYPE (*tp)))
+ return false;
+ tree t = *tp;
+ while (TREE_CODE (t) == COMPOUND_EXPR)
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == AGGR_INIT_EXPR)
+ replace_decl (&AGGR_INIT_EXPR_SLOT (t), decl, replacement);
+ else if (TREE_CODE (t) == VEC_INIT_EXPR)
+ replace_decl (&VEC_INIT_EXPR_SLOT (t), decl, replacement);
+ else
+ replace_decl (tp, decl, replacement);
+ return true;
+}
+
/* Genericization context. */
struct cp_genericize_data
@@ -1116,15 +1138,18 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
cp_genericize_target_expr (stmt_p);
/* Folding might replace e.g. a COND_EXPR with a TARGET_EXPR; in
- that case, use it in place of this one. */
+ that case, strip it in favor of this one. */
if (tree &init = TARGET_EXPR_INITIAL (stmt))
{
cp_walk_tree (&init, cp_fold_r, data, NULL);
+ cp_walk_tree (&TARGET_EXPR_CLEANUP (stmt), cp_fold_r, data, NULL);
*walk_subtrees = 0;
if (TREE_CODE (init) == TARGET_EXPR)
{
- TARGET_EXPR_ELIDING_P (init) = TARGET_EXPR_ELIDING_P (stmt);
- *stmt_p = init;
+ tree sub = TARGET_EXPR_INITIAL (init);
+ maybe_replace_decl (&sub, TARGET_EXPR_SLOT (init),
+ TARGET_EXPR_SLOT (stmt));
+ init = sub;
}
}
break;