Summary: | What is a bitfield's "underlying type"? | ||
---|---|---|---|
Product: | gcc | Reporter: | John Adriaan <John.Adriaan> |
Component: | c++ | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | UNCONFIRMED --- | ||
Severity: | normal | CC: | webrown.cpp |
Priority: | P3 | Keywords: | documentation |
Version: | 9.2.0 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | ||
Bug Depends on: | |||
Bug Blocks: | 114371 |
Description
John Adriaan
2020-01-09 09:07:32 UTC
I've also looked at the `unsigned : 0;` anonymous field. Frankly, it changes nothing. Maybe it should? struct S { bool b : 1; unsigned i : 1; unsigned : 0; }; // S With the above inserted into the examples given in the original post, there is no change. According to the standard, `: 0` means "align the _next_ field with the next alignment boundary." Maybe this is wrong: perhaps it should read "pad the _current_ `struct` to the next alignment boundary for _this_ field's type." The above proposal has the advantage that it doesn't change existing code. And in the unlikely scenario of my "dangling `: 0`" proposal, perhaps that's what the developer expected anyway? So I also tried the following: struct S { bool b : 1; unsigned i : 1; unsigned : 0; unsigned : 0; }; // S Alas, no change. Wow: I just realised. The following code for my proposal is problematic: struct S { bool b : 1; unsigned i : 1; unsigned : 0; char c : 8; }; // S Should `c` be aligned at one byte (its field) or four bytes (the padding field) after the beginning of `S`? According to the current implementation, it's four bytes - so again, the padding `: 0` operator seems to be the overriding by its own type, not that of the following field. Also note that removing the `: 0` field pulls `c` back to a (padded) position six bits _after_ `i` Note the behavior is probably dependent on the ABI. Mixing different underlying types for the same bit group makes this interesting. Does it change anything if you make b and i itself volatile (rather than just s)? @RichardBiener, I used the different types to prove my point: if they're all `unsigned`, it still happens. And the ABI merely defines whether `-fstrict-volatile-bitfields` is the default or not (for ARM, it is): I explicitly enabled it in all cases to eliminate this. Also, I did indeed try changing the example to make the bitfields themselves `volatile` rather than the variable itself (good pick!): no change. @RichardBiener, By "it still happens", I meant that accesses to `s.i` still occur as described. Changing `s.b` to be of type `unsigned` changes its accesses to match those of `s.i` - in other words, the type mismatch is not a factor. |