Description
Seen at #78112 (review), this compiles surprisingly in C23:
struct C {
signed long long i : 8;
};
constexpr struct C c = { 255 };
My reading of N3096:
§6.7.1p6:
If an object or subobject declared with storage-class specifier
constexpr
has [...] integer [..] type, any explicit initializer value for it shall be [.,.] an integer constant expression
§6.6p4:
Each constant expression shall evaluate to a constant that is in the range of representable values for its type.
§6.7.2.1p12:
A bit-field is interpreted as having a signed or unsigned integer type consisting of the specified number of bits.
... So the member i
has a signed type with 8 bits, which 255 is not representable in, and Clang should reject the initializer.
Two other places I can think of where the type of something is observed is typeof
(which explicitly bans bit-fields), and _Generic
. Clang currently allows:
struct C {
signed long long i : 8;
} c;
static_assert(_Generic(c.i, long long: 1));
which according to §6.7.2.1p12, it shouldn't? The bit-field type with width 8 should not be compatible with a 64 bit wide type. Unless the lvalue conversion done converts the bit-field type to long long, but that doesn't seem to be allowed by §6.3.2.1
See also:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88731
DR#315
DR#481