]> gcc.gnu.org Git - gcc.git/commitdiff
d: Fix no NRVO when returning an array of a non-POD struct
authorIain Buclaw <ibuclaw@gdcproject.org>
Mon, 24 Aug 2020 22:39:17 +0000 (00:39 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Sun, 30 Aug 2020 14:23:54 +0000 (16:23 +0200)
TREE_ADDRESSABLE was not propagated from the RECORD_TYPE to the ARRAY_TYPE, so
NRVO code generation was not being triggered.

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.

(cherry picked from commit 312ad889e99ff9458c01518325775e75ab57f272)

gcc/d/d-codegen.cc
gcc/d/types.cc
gcc/testsuite/gdc.dg/pr96157a.d [new file with mode: 0644]
gcc/testsuite/gdc.dg/pr96157b.d [new file with mode: 0644]

index b5af2aca0a9a3ecc84174a293968679554f94b72..f57caf226d40aa2b63867d9c14b9a725f59b5f31 100644 (file)
@@ -1910,10 +1910,10 @@ 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 ();
+             Type *t = arg->type->toBasetype ()->baseElemOf ();
              gcc_assert (t->ty == Tstruct);
              StructDeclaration *sd = ((TypeStruct *) t)->sym;
 
index 59a90b492438d301b02abd2cff7a9654a749a650..d6607a30b7ba74b23e07e313d1d44d7f81c30f17 100644 (file)
@@ -142,8 +142,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 (file)
index 0000000..11df19e
--- /dev/null
@@ -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 (file)
index 0000000..40a7e0b
--- /dev/null
@@ -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);
+    }
+}
This page took 0.071278 seconds and 5 git commands to generate.