1. Changelog
1.1. Revision 0 - January 15st, 2022
-
Initial release 🎉!
2. Introduction and Motivation
C always designates
as the type for the enumerators of its enumerations, but it’s entirely unspecified what the (underlying compatible) type for the
will end up being. These constants (and the initializers for those constants) must fit within an
, otherwise it is a constraint violation. For decades, compilers have been silently providing extensions in their default build modes for enumerations to be larger than
, even if
and friends always detects the type of such an enumerator to be
. It is problematic to only have enumerators which are
, especially since it is only guaranteed to be 16-bits wide. Portability breaks happen between normal 32-bit
environments like typical GCC and Clang x86 platforms vs. 16-bit
environments like SDCC microcontroller targets, which is not desirable.
This proposal provides for enumerations with enumerators of values greater than
and smaller than
to have enumerators that are of a different type than
, allowing the underlying type and the enumeration constants themselves to be of a different type. It does not change behavior for any enumeration constants which were within the
range already.
3. Prior Art
The design of this feature is to enable what has been existing practice on implementations for a long time now, including GCC, SDCC, Clang, and several other compilers. Compilers have allowed for values greater than
and values less than
for a long time in their default compilation modes. We capture this as part of the design discussion below, for how we structure these proposed changes to the C Standard.
4. Design
This is a very small change that only makes previously ill-formed code now well-formed. It does not provide any other guarantees from the new wording besides allowing constants larger than
to be used with enumerations. Better enumeration types and values are better left with the sister paper on Enhanced Enumerations.
More specifically:
-
values for enumerators that are outside of the range
are allowed and change the type of the enumerators from[ INT_MIN , INT_MAX ]
;int -
and, the underlying type for enumerations with such types may be larger than
.int
Particularly, this code:
enum a { a0 = 0xFFFFFFFFFFFFFFFFULL }; int main () { return _Generic ( a0 , unsigned long long : 0 , int : 1 , default : 2 ); }
Should produce a value of
on a normal implementations (but can give other values, so long as the underlying type is big enough to fit a number (264 - 1)). It shall also not produce a diagnostic on even the most strict implementations.
5. Proposed Wording
The following wording is relative to N2731.
5.1. Intent
The intent of the wording is to provide the ability to express enumerations with the underlying type present. In particular:
-
enumerations without an underlying type can have enumerators initialized with integer constant expressions whose type is
or some implementation-defined type capable of representing the constant expression’s value.int
5.2. Proposed Specification
5.2.1. Modify Section §6.4.4.3 Enumeration constants
6.4.4.3 Enumeration constants
Syntax
- enumeration-constant:
- identifier
Semantics
An identifier declared as an enumeration constant for an enumeration has type int if the value used to initialize the enumeration constant is representable in an int. Otherwise, it is an implementation-defined signed or unsigned integer type capable of holding all of the values of the enumeration, as defined in 6.7.2.2.Forward references: enumeration specifiers (6.7.2.2).
5.2.2. Modify Section §6.7.2.2 Enumeration constants
6.7.2.2 Enumeration specifiersSyntax
- enum-specifier:
- enum attribute-specifier-sequenceopt identifieropt { enumerator-list }
- enum attribute-specifier-sequenceopt identifieropt { enumerator-list , }
- enum identifier
- enumerator-list:
enumerator enumerator-list , enumerator enumerator:
- enumeration-constant attribute-specifier-sequenceopt
- enumeration-constant attribute-specifier-sequenceopt = constant-expression
Constraints
The expression that defines the value of an enumeration constant shall be an integer constant expression.that has a value representable as an int.If the values of the integer constant expressions for each enumeration constant of an enumeration are representable as an int, then the enumeration constant’s type shall be an compatible with int. Otherwise, the values of the integer constant expressions for each enumeration constant for the enumeration determine the implementation-defined compatible type for the enumeration constant. The implementation-defined compatible type shall be capable of representing all of the integer constant expressions used to intiialize the enumeration.Semantics
The identifiers in an enumerator list are declared as constants and may appear wherever such are permitted.133) An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. (The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.) The enumerators of an enumeration are also known as its members.Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type (excluding the bit-precise integer types) . The choice of type is implementation-defined134), but shall be capable of representing the values of all the members of the enumeration.The enumerated type is incomplete until immediately after the } that terminates the list of enumerator declarations, and complete thereafter.
5.2.3. Add implementation-defined enumeration behavior to Annex J
6. Acknowledgements
Thanks to:
-
Aaron Ballman for help with the initial drafting;
-
Aaron Ballman, Aaron Bachmann, Jens Gustedt & Joseph Myers for questions, suggestions and offline discussion;
-
Robert Seacord for editing suggestions; and,
-
Clive Pygott for the initial draft of this paper.
We hope this paper serves you all well.