Hi,

This patch fixes an ICE in the D2 compiler in convert_move.

This was caused by a forward reference of a nested struct changing the
TYPE_MODE of its enclosing struct type to be incorrectly inferred as an
integer mode.  Fixed by setting TREE_ADDRESSABLE early, and moving the
mode setting and propagation to finish_aggregate_mode and
finish_aggregate_type respectively, rather than at the end of the
visitor method for TypeStruct.

Bootstrapped and regtested on x86_64-linux-gnu, committed to mainline,
and backported to gcc-13, gcc-14, gcc-15, and gcc-16 release branches.

Regards,
Iain

---
        PR d/125089

gcc/d/ChangeLog:

        * types.cc (finish_aggregate_mode): Explicitly set TYPE_MODE of
        non-POD types here.
        (finish_aggregate_type): Propagate TREE_ADDRESSABLE to all variants.
        (TypeVisitor::visit (TypeStruct *)): Set TREE_ADDRESSABLE before
        visiting struct members.

gcc/testsuite/ChangeLog:

        * gdc.dg/pr125089.d: New test.
---
 gcc/d/types.cc                  | 26 +++++++++++++-------------
 gcc/testsuite/gdc.dg/pr125089.d | 20 ++++++++++++++++++++
 2 files changed, 33 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/pr125089.d

diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index b5658b6e8f4..d79a8972b5c 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -593,7 +593,12 @@ finish_aggregate_mode (tree type)
        return;
     }
 
-  compute_record_mode (type);
+  /* Force mode of non-trivially copyable structs to be BLKmode, preventing it
+     from being returned in a register.  */
+  if (TREE_ADDRESSABLE (type))
+    SET_TYPE_MODE (type, BLKmode);
+  else
+    compute_record_mode (type);
 
   /* Propagate computed mode to all variants of this aggregate type.  */
   for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
@@ -715,6 +720,7 @@ finish_aggregate_type (unsigned structsize, unsigned 
alignsize, tree type)
       TYPE_PACKED (t) = TYPE_PACKED (type);
       SET_TYPE_ALIGN (t, TYPE_ALIGN (type));
       TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (type);
+      TREE_ADDRESSABLE (t) = TREE_ADDRESSABLE (type);
     }
 
   /* Complete any other forward-referenced fields of this aggregate type.  */
@@ -1236,6 +1242,12 @@ public:
     TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t);
     TYPE_CXX_ODR_P (t->ctype) = 1;
 
+    /* For structs with a user defined postblit, copy constructor, or a
+       destructor, also set TREE_ADDRESSABLE on the type and all variants.
+       This will make the struct be passed around by reference.  */
+    if (!dmd::isPOD (t->sym))
+      TREE_ADDRESSABLE (t->ctype) = 1;
+
     if (t->sym->members)
       {
        /* Must set up the overall size and alignment before determining
@@ -1257,18 +1269,6 @@ public:
        build_type_decl (t->ctype, t->sym);
        apply_user_attributes (t->sym, t->ctype);
       }
-
-    /* For structs with a user defined postblit, copy constructor, or a
-       destructor, also set TREE_ADDRESSABLE on the type and all variants.
-       This will make the struct be passed around by reference.  */
-    if (!dmd::isPOD (t->sym))
-      {
-       for (tree tv = t->ctype; tv != NULL_TREE; tv = TYPE_NEXT_VARIANT (tv))
-         {
-           TREE_ADDRESSABLE (tv) = 1;
-           SET_TYPE_MODE (tv, BLKmode);
-         }
-      }
   }
 
   /* Build a class type.  Whereas structs are value types, classes are
diff --git a/gcc/testsuite/gdc.dg/pr125089.d b/gcc/testsuite/gdc.dg/pr125089.d
new file mode 100644
index 00000000000..6936cf6e949
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr125089.d
@@ -0,0 +1,20 @@
+// { dg-do compile }
+struct R125089
+{
+    S125089.T st;
+}
+
+struct S125089
+{
+    struct T
+    {
+        void* v;
+        ~this() {}
+    }
+
+    T t;
+    this(R125089 r)
+    {
+        this.t = r.st;
+    }
+}
-- 
2.43.0

Reply via email to