d: Fix error with -Warray-bounds and -O2 [PR117002]

The record layout of class types in D don't get any tail padding, so it
is possible for the `classInstanceSize' to not be a multiple of the
`classInstanceAlignment'.

Rather than setting the instance alignment on the underlying
RECORD_TYPE, instead give the type an alignment of 1, which will mark it
as TYPE_PACKED.  The value of `classInstanceAlignment' is instead
applied to the DECL_ALIGN of both the static `init' symbol, and the
stack allocated variable used when generating `new' for a `scope' class.

	PR d/117002

gcc/d/ChangeLog:

	* decl.cc (aggregate_initializer_decl): Set explicit decl alignment of
	class instance.
	* expr.cc (ExprVisitor::visit (NewExp *)): Likewise.
	* types.cc (TypeVisitor::visit (TypeClass *)): Mark the record type of
	classes as packed.

gcc/testsuite/ChangeLog:

	* gdc.dg/torture/pr117002.d: New test.
This commit is contained in:
Iain Buclaw 2025-03-29 23:16:25 +01:00
parent b9adf3a4c8
commit 9fadadbbbc
4 changed files with 38 additions and 1 deletions

View file

@ -2393,6 +2393,12 @@ aggregate_initializer_decl (AggregateDeclaration *decl)
SET_DECL_ALIGN (sinit, sd->alignment.get () * BITS_PER_UNIT);
DECL_USER_ALIGN (sinit) = true;
}
else if (sd == NULL)
{
/* Alignment of class is determined its biggest field alignment. */
SET_DECL_ALIGN (sinit, decl->alignsize * BITS_PER_UNIT);
DECL_USER_ALIGN (sinit) = true;
}
decl->sinit = sinit;
return sinit;

View file

@ -2243,6 +2243,8 @@ public:
storage class, then the instance is allocated on the stack
rather than the heap or using the class specific allocator. */
tree var = build_local_temp (TREE_TYPE (type));
SET_DECL_ALIGN (var, cd->alignsize * BITS_PER_UNIT);
DECL_USER_ALIGN (var) = 1;
new_call = build_nop (type, build_address (var));
setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
}

View file

@ -1278,7 +1278,8 @@ public:
build_type_decl (basetype, t->sym);
set_visibility_for_decl (basetype, t->sym);
apply_user_attributes (t->sym, basetype);
finish_aggregate_type (t->sym->structsize, t->sym->alignsize, basetype);
/* The underlying record type of classes are packed. */
finish_aggregate_type (t->sym->structsize, 1, basetype);
/* Classes only live in memory, so always set the TREE_ADDRESSABLE bit. */
for (tree tv = basetype; tv != NULL_TREE; tv = TYPE_NEXT_VARIANT (tv))

View file

@ -0,0 +1,28 @@
// { dg-do compile }
// { dg-additional-options "-Warray-bounds" }
extern(C++) class C117002
{
ubyte[4] not_multiple_of_8;
}
int pr117002a(void *p)
{
auto init = __traits(initSymbol, C117002);
if (init.ptr + init.length <= p)
return 1;
return 0;
}
void pr117002b(void *p)
{
auto init = __traits(initSymbol, C117002);
p[0 .. init.length] = init[];
}
void pr117002c()
{
scope var = new C117002;
void *p = cast(void*)var;
auto init = __traits(initSymbol, C117002);
p[0 .. __traits(classInstanceSize, C117002)] = init[];
}