From f67d7f9416be37c34c4188866fb3d10c1dbc7a2a Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 3 Jul 2021 00:13:29 +0200 Subject: [PATCH] d: RHS value lost when a target_expr modifies LHS in a cond_expr To prevent the RHS of an assignment modifying the LHS before the assignment proper, a target_expr is forced so that function calls that return with slot optimization modify the temporary instead. This did not work for conditional expressions however, to give one example. So now the RHS is always forced to a temporary. PR d/101282 gcc/d/ChangeLog: * d-codegen.cc (build_assign): Force target_expr on RHS for non-POD assignment expressions. gcc/testsuite/ChangeLog: * gdc.dg/torture/pr101282.d: New test. (cherry picked from commit c77230856eac2d28eb7bf10985846885c3c8727b) --- gcc/d/d-codegen.cc | 7 +++++++ gcc/testsuite/gdc.dg/torture/pr101282.d | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 gcc/testsuite/gdc.dg/torture/pr101282.d diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index 9a9447371aa0..ce7c17baaaf0 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -1344,6 +1344,13 @@ build_assign (tree_code code, tree lhs, tree rhs) d_mark_addressable (lhs); CALL_EXPR_RETURN_SLOT_OPT (rhs) = true; } + /* If modifying an LHS whose type is marked TREE_ADDRESSABLE. */ + else if (code == MODIFY_EXPR && TREE_ADDRESSABLE (TREE_TYPE (lhs)) + && TREE_SIDE_EFFECTS (rhs) && TREE_CODE (rhs) != TARGET_EXPR) + { + /* LHS may be referenced by the RHS expression, so force a temporary. */ + rhs = force_target_expr (rhs); + } /* The LHS assignment replaces the temporary in TARGET_EXPR_SLOT. */ if (TREE_CODE (rhs) == TARGET_EXPR) diff --git a/gcc/testsuite/gdc.dg/torture/pr101282.d b/gcc/testsuite/gdc.dg/torture/pr101282.d new file mode 100644 index 000000000000..b75d5fc678f1 --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/pr101282.d @@ -0,0 +1,23 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101282 +// { dg-do run } + +void main() +{ + struct S101282 + { + int impl; + S101282 opUnary(string op : "-")() + { + return S101282(-impl); + } + int opCmp(int i) + { + return (impl < i) ? -1 : (impl > i) ? 1 : 0; + } + } + auto a = S101282(120); + a = -a; + assert(a.impl == -120); + a = a >= 0 ? a : -a; + assert(a.impl == 120); +} -- 2.47.2