]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
d: Fix error with -Warray-bounds and -O2 [PR117002]
authorIain Buclaw <ibuclaw@gdcproject.org>
Sat, 29 Mar 2025 22:16:25 +0000 (23:16 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Mon, 31 Mar 2025 17:15:33 +0000 (19:15 +0200)
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.

gcc/d/decl.cc
gcc/d/expr.cc
gcc/d/types.cc
gcc/testsuite/gdc.dg/torture/pr117002.d [new file with mode: 0644]

index 9fcfc5681f8ce4e48514e718031ffd66414e0aa5..250d148e56f4a2d04b9abebc5b5f629f1bd0210b 100644 (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;
index 0415763b60d1ad94216918ea4812da09f6f6ae1e..46e65145791102e99e209717dac3778f834101c3 100644 (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));
          }
index 98074f1fb6877184e3dc7726ba52d0d038efb5df..ea62bc9d05e19cee0c22702943a46cc23acfb868 100644 (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))
diff --git a/gcc/testsuite/gdc.dg/torture/pr117002.d b/gcc/testsuite/gdc.dg/torture/pr117002.d
new file mode 100644 (file)
index 0000000..5b8c19e
--- /dev/null
@@ -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[];
+}