https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102024
Bug ID: 102024 Summary: zero width bitfields and ABIs Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: jakub at gcc dot gnu.org Target Milestone: --- My r12-2975-g32c3a75390623a0470df52af13f78baddd562981 change removed removal of zero width unnamed bitfields from the C++ FE, the C FE has never been removing those (the removal was certainly premature, as the newly added traits need to see the zero width unnamed bitfields). This unfortunately can affect ABI on several targets. >From quick grep I think this can't affect alpha, arc, avr, bfin, bpf, c6x, cr16, cris, csky, epiphany, fr30, frv, ft32, gcn, h8300, lm32, m32c, m32r, m68k, mcore, microblaze, mmix, mn10300, moxie, msp430, nds32, nios2, nvptx, or1k, pa, pdp11, pru, rl78, rx, stormy16, tilegx, tilepro, v850, vax, visium, xtensa are all safe, they either don't mention TYPE_FIELDS in their backends or use it either in va_list or in structure layout code only (structure layout happens before the zero width bitfields are removed by the FE). TYPE_MODE should be ok too, it is just passing of arguments by value and returning by value that could be problematic on aarch64, arm, i386, ia64, iq2000, mips, riscv, rs6000, s390, sh and sparc I think sh is ok, it ignores integer_zerop (DECL_SIZE (field)). riscv apparently has old (< GCC 10) and new (>= GCC 10) ABI and the old one didn't ignore them and made C and C++ ABI incompatible, while the new one does ignore them. So, my patch probably broke the "ABI for flattened struct with zero-length bit-fields changed in GCC 10" warning (why isn't it guarded with -Wpsabi?), perhaps we should mark the C++ zero width bitfields with some attribute or flag so that backends could emit correct -Wpsabi warnings? x86_64 seems to be affected: struct S { float a; int : 0; float b; }; __attribute__((noipa)) struct S foo (struct S x) { return x; } void bar (void) { struct S s = { 0.0f, 0.0f }; foo (s); } With GCC 10 and C we emit: xorl %edi, %edi jmp foo With C++ we emit: pxor %xmm0, %xmm0 jmp _Z3foo1S with current trunk xorl %edi, %edi jmp _Z3foo1S