diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-06-04 19:38:26 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-06-04 20:45:01 +0200 |
commit | df3fbd5957f12927a459a2686f4eee55f66ec2f4 (patch) | |
tree | c9387e7a394e7e91adcaf72aa799f4a48f03e88b /gcc/d/d-codegen.cc | |
parent | 6f8c9691495ad5a307db98dc19c3296ee4e6de64 (diff) | |
download | gcc-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.cc | 36 |
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); } |