https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103839

            Bug ID: 103839
           Summary: __builtin_clear_padding doesn't zero alignment holes
                    of unions with fields that overlap padding
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ibuclaw at gdcproject dot org
  Target Milestone: ---

Consider:

---
// { dg-additional-options "-ftrivial-auto-var-init=zero" }
union U
{
  struct { char a; int b; } c;
  int d;
};

int main()
{
  U u[2] = {{1, 2}, {3, 4}};
}
---

Because of `int d`, the three byte padding that would be required to fill the
gap between the two struct fields is ignored.

So after gimple lowering, we are left with:
---
  u[0].c.a = 1;
  u[0].c.b = 2;
  u[1].c.a = 3;
  u[1].c.b = 4;
  GIMPLE_NOP
---

Instead of the expected:
---
  u[0].c.a = 1;
  u[0].c.b = 2;
  u[1].c.a = 3;
  u[1].c.b = 4;
  MEM <char[3]> [(union U[2] *)&a + 1B] = {};
  MEM <char[3]> [(union U[2] *)&a + 9B] = {};
---

And inspecting the data in gdb, we visibly have garbage in the object.
---
(gdb) p u
$1 = {{c = {a = 1 '\001', b = 2}, d = 1025}, {c = {a = 3 '\003', b = 4}, d =
4355}}
---

I can work around this by setting DECL_PADDING_P on all fields in unions except
the first.  However I suspect this is a mistake, and the proper thing to do
would be to only consider the first field when clear padding a union.

Reply via email to