Hi,

This patch fixes a logic bug in the adjustment of nested fields in
anonymous aggregates in the D front-end, closing PR d/92309.

Bootstrapped and tested on x86_64-linux-gnu, and committed to trunk.

Regards
Iain.

---
gcc/d/ChangeLog:

        PR d/92309
        * types.cc (fixup_anonymous_offset): Don't set DECL_FIELD_OFFSET on
        anonymous fields.

gcc/testsuite/ChangeLog:

        PR d/92309
        * gdc.dg/pr92309.d: New test.

---
 gcc/d/types.cc                 | 10 +++++++---
 gcc/testsuite/gdc.dg/pr92309.d | 25 +++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/pr92309.d

diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 736f128422c..866da965b40 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -234,16 +234,20 @@ insert_aggregate_field (tree type, tree field, size_t 
offset)
 static void
 fixup_anonymous_offset (tree fields, tree offset)
 {
+  /* No adjustment in field offset required.  */
+  if (integer_zerop (offset))
+    return;
+
   while (fields != NULL_TREE)
     {
-      /* Traverse all nested anonymous aggregates to update their offset.
-        Set the anonymous decl offset to its first member.  */
+      /* Traverse all nested anonymous aggregates to update the offset of their
+        fields.  Note that the anonymous field itself is not adjusted, as it
+        already has an offset relative to its outer aggregate.  */
       tree ftype = TREE_TYPE (fields);
       if (TYPE_NAME (ftype) && IDENTIFIER_ANON_P (TYPE_IDENTIFIER (ftype)))
        {
          tree vfields = TYPE_FIELDS (ftype);
          fixup_anonymous_offset (vfields, offset);
-         DECL_FIELD_OFFSET (fields) = DECL_FIELD_OFFSET (vfields);
        }
       else
        {
diff --git a/gcc/testsuite/gdc.dg/pr92309.d b/gcc/testsuite/gdc.dg/pr92309.d
new file mode 100644
index 00000000000..01ebc40d336
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr92309.d
@@ -0,0 +1,25 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92309
+// { dg-do run { target hw } }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+
+union U
+{
+    struct
+    {
+        size_t a;
+        size_t b;
+        union
+        {
+            size_t c;
+            size_t d;
+        }
+    }
+}
+
+void main()
+{
+    U u;
+    assert(u.a == 0);
+    u.d = 1;
+    assert(u.a == 0);
+}
-- 
2.20.1

Reply via email to