diff mbox series

[committed] d: RHS value lost when a target_expr modifies LHS in a cond_expr (PR101282)

Message ID 20210702224641.3508084-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: RHS value lost when a target_expr modifies LHS in a cond_expr (PR101282) | expand

Commit Message

Iain Buclaw July 2, 2021, 10:46 p.m. UTC
Hi,

This patch forces a target_expr on the RHS of an assignment when it is
a non-POD type.

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.

Bootstrapped and regression tested on x86_64-linux-gnu/-m64/-m32/-mx32.
Committed to mainline, and backported to the gcc-11 release branch.

Regards,
Iain
---
gcc/d/ChangeLog:

	PR d/101282
	* d-codegen.cc (build_assign): Force target_expr on RHS for non-POD
	assignment expressions.

gcc/testsuite/ChangeLog:

	PR d/101282
	* gdc.dg/torture/pr101282.d: New test.
---
 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 mbox series

Patch

diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 9a9447371aa..ce7c17baaaf 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 00000000000..b75d5fc678f
--- /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);
+}