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[];
+}

Reply via email to