Menu

#508 Anonymous-union initializers: six fixes for bug #3393

open
nobody
None
5
5 days ago
5 days ago
No

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.

Limitations

These six do not make anonymous-union initialization correct in general. Three
things are known to remain:

  1. 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.

  2. 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.

  3. 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.

Verification

  • The affected tests — 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.
  • Full suite, nine ports — 287,635 test executions, 0 failures — against device libraries rebuilt with the same compiler.
  • Every prefix of the series builds, and each patch carries its fix and the test for it in the same commit, so no test appears before the patch that makes it pass.
  • The three tests also run directly under gcc and clang, and under s390x gcc via qemu, so their expected values are not derived from SDCC's own behavior.
6 Attachments

Related

Patches: #509

Discussion


Log in to post a comment.