https://gcc.gnu.org/g:362839a1cfff37f01267789e71c4e9e757588785

commit r13-10293-g362839a1cfff37f01267789e71c4e9e757588785
Author: Iain Buclaw <[email protected]>
Date:   Tue May 5 22:00:28 2026 +0200

    d: internal compiler error: in convert_move, at expr.cc:227
    
    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.
    
            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.
    
    (cherry picked from commit c19dda2bc6af928414788509d9be7675b93dcb03)

Diff:
---
 gcc/d/types.cc                  | 26 +++++++++++++-------------
 gcc/testsuite/gdc.dg/pr125089.d | 20 ++++++++++++++++++++
 2 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 27fbe715c89b..f6406e0268e0 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.  */
@@ -1232,6 +1238,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 (!t->sym->isPOD ())
+      TREE_ADDRESSABLE (t->ctype) = 1;
+
     if (t->sym->members)
       {
        /* Must set up the overall size and alignment before determining
@@ -1253,18 +1265,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 (!t->sym->isPOD ())
-      {
-       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 000000000000..6936cf6e9492
--- /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;
+    }
+}

Reply via email to