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