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.
This commit is contained in:
Iain Buclaw
2026-05-05 22:00:28 +02:00
parent 710581c80b
commit 2dde6c91d0
2 changed files with 33 additions and 13 deletions

View File

@@ -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

View File

@@ -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;
}
}