Hi,

This patch fixes an error raised by the middle-end when compiling with
the options `-Warray-bounds -O2'.

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.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32, committed
to mainline and backported to releases/gcc-14 and releases/gcc-13.

Regards,
Iain.

---
        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.
---
 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(-)
 create mode 100644 gcc/testsuite/gdc.dg/torture/pr117002.d

diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 9fcfc5681f8..250d148e56f 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -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;
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 0415763b60d..46e65145791 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -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));
          }
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 98074f1fb68..ea62bc9d05e 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 00000000000..5b8c19e5b12
--- /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[];
+}
-- 
2.43.0

Reply via email to