https://gcc.gnu.org/g:bfc9520eab16379aa47121d336bfd4d38c6d040a
commit r13-9480-gbfc9520eab16379aa47121d336bfd4d38c6d040a Author: Iain Buclaw <ibuc...@gdcproject.org> Date: Sat Mar 29 23:16:25 2025 +0100 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. (cherry picked from commit 9fadadbbbc2b5352e5e70e0e1a9be9b447176913) Diff: --- gcc/d/decl.cc | 6 ++++++ gcc/d/expr.cc | 2 ++ gcc/d/types.cc | 3 ++- gcc/testsuite/gdc.dg/torture/pr117002.d | 28 ++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index deba3335a6a8..945f075cd44e 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -2382,6 +2382,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; diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 5d91349bf5b5..6ed9554af1bf 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -2261,6 +2261,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)); } diff --git a/gcc/d/types.cc b/gcc/d/types.cc index 32b322c87190..0a8679756b0a 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -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)) diff --git a/gcc/testsuite/gdc.dg/torture/pr117002.d b/gcc/testsuite/gdc.dg/torture/pr117002.d new file mode 100644 index 000000000000..5b8c19e5b12f --- /dev/null +++ b/gcc/testsuite/gdc.dg/torture/pr117002.d @@ -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[]; +}