diff mbox series

[committed] d: Fix no NRVO when returning an array of a non-POD struct

Message ID 20200826081436.451013-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Fix no NRVO when returning an array of a non-POD struct | expand

Commit Message

Iain Buclaw Aug. 26, 2020, 8:14 a.m. UTC
Hi,

This patch fixes another NRVO bug in the D front-end where arrays of
non-POD types were not being returns by reference.

TREE_ADDRESSABLE was not propagated from the RECORD_TYPE to the ARRAY_TYPE, so
NRVO code generation was not being triggered.

Regstrapped on x86_64-linux-gnu/-m32/-mx32, committed to mainline.

Regards
Iain

---
gcc/d/ChangeLog:

	PR d/96157
	* d-codegen.cc (d_build_call): Handle TREE_ADDRESSABLE static arrays.
	* types.cc (make_array_type): Propagate TREE_ADDRESSABLE from base
	type to static array.

gcc/testsuite/ChangeLog:

	PR d/96157
	* gdc.dg/pr96157a.d: New test.
	* gdc.dg/pr96157b.d: New test.
---
 gcc/d/d-codegen.cc              |  4 +--
 gcc/d/types.cc                  |  7 +++--
 gcc/testsuite/gdc.dg/pr96157a.d | 24 +++++++++++++++++
 gcc/testsuite/gdc.dg/pr96157b.d | 46 +++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/pr96157a.d
 create mode 100644 gcc/testsuite/gdc.dg/pr96157b.d
diff mbox series

Patch

diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 73a6a340ccf..6a7ecc50645 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -1987,11 +1987,11 @@  d_build_call (TypeFunction *tf, tree callable, tree object,
 	      targ = build2 (COMPOUND_EXPR, TREE_TYPE (t), targ, t);
 	    }
 
-	  /* Parameter is a struct passed by invisible reference.  */
+	  /* Parameter is a struct or array passed by invisible reference.  */
 	  if (TREE_ADDRESSABLE (TREE_TYPE (targ)))
 	    {
 	      Type *t = arg->type->toBasetype ();
-	      StructDeclaration *sd = t->isTypeStruct ()->sym;
+	      StructDeclaration *sd = t->baseElemOf ()->isTypeStruct ()->sym;
 
 	      /* Nested structs also have ADDRESSABLE set, but if the type has
 		 neither a copy constructor nor a destructor available, then we
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 0d05e4d82b3..994d0b9195b 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -186,8 +186,11 @@  make_array_type (Type *type, unsigned HOST_WIDE_INT size)
       return t;
     }
 
-  return build_array_type (build_ctype (type),
-			   build_index_type (size_int (size - 1)));
+  tree t = build_array_type (build_ctype (type),
+			     build_index_type (size_int (size - 1)));
+  /* Propagate TREE_ADDRESSABLE to the static array type.  */
+  TREE_ADDRESSABLE (t) = TREE_ADDRESSABLE (TREE_TYPE (t));
+  return t;
 }
 
 /* Builds a record type whose name is NAME.  NFIELDS is the number of fields,
diff --git a/gcc/testsuite/gdc.dg/pr96157a.d b/gcc/testsuite/gdc.dg/pr96157a.d
new file mode 100644
index 00000000000..11df19ea700
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr96157a.d
@@ -0,0 +1,24 @@ 
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96157
+// { dg-do run { target native } }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+
+struct S
+{
+    @disable this(this); // triggers nrvo
+    int v;
+}
+
+__gshared void* p;
+
+S[1000] foo() nothrow
+{
+    typeof(return) d;
+    p = &d;
+    return d;
+}
+
+void main()
+{
+    auto d = foo();
+    assert(p == &d);
+}
diff --git a/gcc/testsuite/gdc.dg/pr96157b.d b/gcc/testsuite/gdc.dg/pr96157b.d
new file mode 100644
index 00000000000..40a7e0ba787
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr96157b.d
@@ -0,0 +1,46 @@ 
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96157
+// { dg-options "-fno-moduleinfo -fno-rtti" }
+// { dg-do compile }
+
+int[] testYearsBC;
+
+struct FilterResult
+{
+    int[] input;
+    bool primed;
+
+    this(int[] r)
+    {
+        this.input = r;
+    }
+
+    int front()
+    {
+        return input[0];
+    }
+};
+
+FilterResult filter(int[] range)
+{
+    return FilterResult(range);
+}
+
+int[] chain(int[] rs)
+{
+    return rs;
+}
+
+struct SysTime
+{
+    this(int);
+}
+
+void test()
+{
+    while (1)
+    {
+        FilterResult val = filter(chain(testYearsBC));
+        int year = val.front();
+        SysTime(0);
+    }
+}