Six patches against trunk r16743. Each extends the mechanism r16733 introduced rather than replacing it, and each carries a test case that fails without it.
0001 compare bit extents, not byte offsets, so the bitfield exemption goes
0002 an alternative that is a struct larger than the first (both paths)
0003 zero the part of a union no initializer reaches, for automatic storage
0004 a union whose first member is an unnamed bitfield
0005 an initializer after a designated one, without undoing the designated
0006 a union object in its own right, designator naming a promoted member
0001 addresses the case the r16733 commit message records as remaining, and deletes the #if 0 in bug-3393.c that compiled that alternative out. Byte offsets cannot distinguish a union alternative from bitfields sharing a storage unit, because both share an offset, which is why the watermark has to exempt bitfields. Bit extents distinguish them: consecutive bitfields start where the previous one ended, an alternative starts where the union does. The exemption is then unnecessary.
These six do not make anonymous-union initialization correct in general. Three
things are known to remain:
A designated initializer into a nested anonymous union is still wrong at file scope, on the targets that emit an initialized global as a data image. 0003 fixes the automatic-storage half; printIvalStruct() is unfixed. bug-3393-designated.c carries the case with the failing checks under #if 0, following the convention bug-3393.c already uses, so it is recorded in the suite rather than left to be rediscovered. Details and a reproducer are in the comment on #3393.
That one cannot be fixed within the current structure. The union's extent is not recoverable from the flattened member list. A fix means letting the initializer walk see the nesting, which reaches printIvalStruct(), createIvalStruct(), reorderIlistFull() and the pic14 and pic16 copies. That is not attempted here.
Brace elision into a nested aggregate at block scope is unimplemented (C11 6.7.9p20) — struct out {char a; struct in in; char z;} with struct out v = {1, 2, 3, 4}; fails to compile at block scope while the same declaration at file scope is accepted and correct. Pre-existing, unrelated to these patches, and not addressed.
bug-3393.c, bug-2840.c and bug-3393-designated.c — pass on eight ports: ucz80, mcs51-small, stm8, hc08, s08, ds390, f8 and pdk14.