aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/d-codegen.cc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2021-06-04 19:38:26 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2021-06-04 20:45:01 +0200
commitdf3fbd5957f12927a459a2686f4eee55f66ec2f4 (patch)
treec9387e7a394e7e91adcaf72aa799f4a48f03e88b /gcc/d/d-codegen.cc
parent6f8c9691495ad5a307db98dc19c3296ee4e6de64 (diff)
downloadgcc-df3fbd5957f12927a459a2686f4eee55f66ec2f4.zip
gcc-df3fbd5957f12927a459a2686f4eee55f66ec2f4.tar.gz
gcc-df3fbd5957f12927a459a2686f4eee55f66ec2f4.tar.bz2
d: Fix ICE in gimplify_var_or_parm_decl, at gimplify.c:2755 (PR100882)
Constructor calls for temporaries were reusing the TARGET_EXPR_SLOT of a TARGET_EXPR for an assignment, which later got passed to `build_assign', which stripped away the outer TARGET_EXPR, leaving a reference to a lone temporary with no declaration. This stripping away of the TARGET_EXPR also discarded any cleanups that may have been assigned to the expression as well. So now the reuse of TARGET_EXPR_SLOT has been removed, and `build_assign' now constructs assignments inside the TARGET_EXPR_INITIAL slot. This has also been extended to `return_expr', to deal with possibility of a TARGET_EXPR being returned. gcc/d/ChangeLog: PR d/100882 * d-codegen.cc (build_assign): Construct initializations inside TARGET_EXPR_INITIAL. (compound_expr): Remove intermediate expressions that have no side-effects. (return_expr): Construct returns inside TARGET_EXPR_INITIAL. * expr.cc (ExprVisitor::visit (CallExp *)): Remove useless assignment to TARGET_EXPR_SLOT. gcc/testsuite/ChangeLog: PR d/100882 * gdc.dg/pr100882a.d: New test. * gdc.dg/pr100882b.d: New test. * gdc.dg/pr100882c.d: New test. * gdc.dg/torture/pr100882.d: New test.
Diffstat (limited to 'gcc/d/d-codegen.cc')
-rw-r--r--gcc/d/d-codegen.cc36
1 files changed, 30 insertions, 6 deletions
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 5fa1acd..9a94473 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -1330,6 +1330,7 @@ component_ref (tree object, tree field)
tree
build_assign (tree_code code, tree lhs, tree rhs)
{
+ tree result;
tree init = stabilize_expr (&lhs);
init = compound_expr (init, stabilize_expr (&rhs));
@@ -1348,22 +1349,27 @@ build_assign (tree_code code, tree lhs, tree rhs)
if (TREE_CODE (rhs) == TARGET_EXPR)
{
/* If CODE is not INIT_EXPR, can't initialize LHS directly,
- since that would cause the LHS to be constructed twice.
- So we force the TARGET_EXPR to be expanded without a target. */
+ since that would cause the LHS to be constructed twice. */
if (code != INIT_EXPR)
{
init = compound_expr (init, rhs);
- rhs = TARGET_EXPR_SLOT (rhs);
+ result = build_assign (code, lhs, TARGET_EXPR_SLOT (rhs));
}
else
{
d_mark_addressable (lhs);
- rhs = TARGET_EXPR_INITIAL (rhs);
+ TARGET_EXPR_INITIAL (rhs) = build_assign (code, lhs,
+ TARGET_EXPR_INITIAL (rhs));
+ result = rhs;
}
}
+ else
+ {
+ /* Simple assignment. */
+ result = fold_build2_loc (input_location, code,
+ TREE_TYPE (lhs), lhs, rhs);
+ }
- tree result = fold_build2_loc (input_location, code,
- TREE_TYPE (lhs), lhs, rhs);
return compound_expr (init, result);
}
@@ -1485,6 +1491,11 @@ compound_expr (tree arg0, tree arg1)
if (arg0 == NULL_TREE || !TREE_SIDE_EFFECTS (arg0))
return arg1;
+ /* Remove intermediate expressions that have no side-effects. */
+ while (TREE_CODE (arg0) == COMPOUND_EXPR
+ && !TREE_SIDE_EFFECTS (TREE_OPERAND (arg0, 1)))
+ arg0 = TREE_OPERAND (arg0, 0);
+
if (TREE_CODE (arg1) == TARGET_EXPR)
{
/* If the rhs is a TARGET_EXPR, then build the compound expression
@@ -1505,6 +1516,19 @@ compound_expr (tree arg0, tree arg1)
tree
return_expr (tree ret)
{
+ /* Same as build_assign, the DECL_RESULT assignment replaces the temporary
+ in TARGET_EXPR_SLOT. */
+ if (ret != NULL_TREE && TREE_CODE (ret) == TARGET_EXPR)
+ {
+ tree exp = TARGET_EXPR_INITIAL (ret);
+ tree init = stabilize_expr (&exp);
+
+ exp = fold_build1_loc (input_location, RETURN_EXPR, void_type_node, exp);
+ TARGET_EXPR_INITIAL (ret) = compound_expr (init, exp);
+
+ return ret;
+ }
+
return fold_build1_loc (input_location, RETURN_EXPR,
void_type_node, ret);
}