[clang] [Clang] Fix oversized bit-field layout on big-endian targets (PR #225494)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 24 12:48:45 PDT 2026
================
@@ -15917,12 +15917,15 @@ struct PaddingCalculator {
const uint64_t DeclaredSizeInBits = Field->getBitWidthValue();
- // Handle over-sized bitfields:
- // unsigned char a : 12;
- // In this case, DeclaredSizeInBits is 12, but the actually occupied bit
- // size is 8, while the remaining 4 bits are padding.
+ // Oversized bit-fields (declared width larger than the field type) keep
+ // only the type's width as the value container. The extra declared bits
+ // are padding and follow that container (Itanium C++ ABI 2.4).
+ // getIntWidth may be narrower still (bool, _BitInt); those occupied bits
+ // are the low-order bits of the value container.
----------------
xiongzile wrote:
I guess my naming caused the confusion.
What I meant is that, for `bool`, `getIntWidth()` returns 1 while `getTypeSize()` is 8 bits on this target. This is why I introduced `ValueFieldBits`.
For example, consider an oversized bit-field:
```cpp
bool x : 16;
```
On a big-endian target, the single occupied bit is at offset 7 within the first 8-bit type-sized portion, while the additional 8 bits are trailing padding:
```text
PPPPPPPV PPPPPPPP
^
occupied bit
```
So the occupied range starts at `StartBitOffset + 7`, not at `StartBitOffset`.
That's why I used:
```cpp
const uint64_t Start =
StartBitOffset + ValueFieldBits - OccupiedSizeInBits;
```
rather than simply:
```cpp
const uint64_t Start = StartBitOffset;
```
https://github.com/llvm/llvm-project/pull/225494
More information about the cfe-commits
mailing list