N2969: bit-precise bit-fields

Submitter: Philipp Klaus Krause
Submission Date: 2022-04-10

Summary:

Bit-fields of bit-precise integer types. This is an update of N2945.

This mandates support for bit-fields of bit-precise integer types.

Justification:

C currently mandates support for bool, int, signed int and unsigned int as types for bit-fields. Support for further types is implementation-defined. However, other bit-fields are useful and having them supported in the standard would be good. Particularly useful would be types larger than int (since these add functionality that is currently not mandated by the standard).

Some such types (e.g. unsigned long, unsigned long long) are supported by many implementations, including IAR, GCC and clang. They are widely used.

Debian code search shows that in particular, unsigned long and unsigned long long are very widely used, in different programs (including e.g. GCC and Linux)

N2774 proposed support for unsigned long and unsigned long long. When N2774 was discussed, WG14 wanted bit-fields of unsigned bit-precise integer types instead. Since the standard requires that implementations support bit-precise types up to the width of long long, this should also cover most current use-cases of bit-fields of type unsigned long and unsigned long long.

Bit-precise integer types allow programmers to explicitly state their intent on how many bits are needed; but since they are addressable, they need padding bits when their width is not a multiple of CHAR_WIDTH. Some implementations might use more padding for alignment. Where there is a need to save memory, this is a problem. Using bit-fields of bit-precise integer types is a solution/p>

Bit-precise integer types are not promoted to int, as other types smaller than int are; thus bit-fields of bit-precise unsigned integer types are not affected by issues that affect some other bit-fields (e.g. GCC and clang disagreeing on the type of a bit-field of type unsigned long).

Bit-precise bit-fields (both signed and unsigned) are supported by SDCC, clang and ICX. At least in SDCC, just like in this proposal, bit-fields of bit-precise type convert to the corresponding bit-precise type, e.g. signed _BitInt(7) : 3 is a bit-field that can hold the values -4, -3, -2, -1, 0, 1, 2, 3, and converts to signed _BitInt(7).

Do we want bit-precise bit-fields?

Proposed changes (vs N2732 with N2763 applied):
In 6.3.1.1p2, replace
"If the original type is not a bit-precise integer type (6.2.5) and if an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int;"
by
"The value from a bit-field of a bit-precise integer type is converted to the corresponding bit-precise type. If the original type is not a bit-precise integer type (6.2.5) and if an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; [footnote]" [footnote]: E.g. unsigned _BitInt(7) : 2 is a bit-field that can hold the values -2, -1, 0, 1, and converts to unsigned _BitInt(7).
In 6.7.2.1p5, replace
"A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type."
by
"A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, a bit-precise integer type, or some other implementation-defined type.".
In J.3.9, replace
"Allowable bit-field types other than _Bool, signed int, and unsigned int"
by
"Allowable bit-field types other than _Bool, signed int, unsigned int, and bit-precise integer types".
In J.5.8 replace
"A bit-field may be declared with a type other than _Bool, unsigned int, or signed int"
by
"A bit-field may be declared with a type other than _Bool, unsigned int, signed int, or a bit-precise integer type".

If not, do we want unsigned bit-precise bit-fields only?

Proposed changes (vs N2732 with N2763 applied):
In 6.3.1.1p2, replace
"If the original type is not a bit-precise integer type (6.2.5) and if an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int;"
by
"The value from a bit-field of a bit-precise integer type is converted to the corresponding bit-precise type. If the original type is not a bit-precise integer type (6.2.5) and if an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int;"
In 6.7.2.1p5, replace
"A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type."
by
"A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, a bit-precise unsigned integer type, or some other implementation-defined type.".
In J.3.9, replace
"Allowable bit-field types other than _Bool, signed int, and unsigned int"
by
"Allowable bit-field types other than _Bool, signed int, unsigned int, and bit-precise unsigned integer types".
In J.5.8 replace
"A bit-field may be declared with a type other than _Bool, unsigned int, or signed int"
by
"A bit-field may be declared with a type other than _Bool, unsigned int, signed int, or a bit-precise unsigned integer type".