https://gcc.gnu.org/g:c19dda2bc6af928414788509d9be7675b93dcb03
commit r15-11134-gc19dda2bc6af928414788509d9be7675b93dcb03 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 2dde6c91d0f0df9ebef57955b92a6dfd30bea480) 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 2757fe793f2a..60e42cf15e18 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. */ @@ -1234,6 +1240,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 @@ -1255,18 +1267,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; + } +}
