C23 adds a feature from C++11 that allows the storage type for an enum definition to be specifies with the syntax:
enum my_enum : uint8_t {
...
};
This has been supported by C compilers for quite a while, and is used in places like macOS's system headers. For example, in MacOSX.sdk/usr/include/sys/mount.h, there is the following definition:
OS_ENUM(graftdmg_type, uint32_t,
GRAFTDMG_CRYPTEX_BOOT = 1,
GRAFTDMG_CRYPTEX_PREBOOT = 2,
GRAFTDMG_CRYPTEX_DOWNLEVEL = 3,
// Reserved: CRYPTEX1_AUTH_ENV_GENERIC = 4,
// Reserved: CRYPTEX1_AUTH_ENV_GENERIC_SUPPLEMENTAL = 5,
GRAFTDMG_CRYPTEX_PDI_NONCE = 6,
GRAFTDMG_CRYPTEX_EFFECTIVE_AP = 7,
GRAFTDMG_CRYPTEX_MOBILE_ASSET = 8,
// Update this when a new type is added
GRAFTDMG_CRYPTEX_MAX = 8);
which expands to
typedef enum : uint32_t {
GRAFTDMG_CRYPTEX_BOOT = 1,
GRAFTDMG_CRYPTEX_PREBOOT = 2,
GRAFTDMG_CRYPTEX_DOWNLEVEL = 3,
GRAFTDMG_CRYPTEX_PDI_NONCE = 6,
GRAFTDMG_CRYPTEX_EFFECTIVE_AP = 7,
GRAFTDMG_CRYPTEX_MOBILE_ASSET = 8,
GRAFTDMG_CRYPTEX_MAX = 8
} graftdmg_type_t
For reference, definition of OS_ENUM is guarded by come __has_extension checks, and I guess at least one must be true when c2hs is parsing the file:
#if __has_feature(objc_fixed_enum) || __has_extension(cxx_fixed_enum) || \
__has_extension(cxx_strong_enums)
#define OS_ENUM(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } _name##_t
#define OS_CLOSED_ENUM(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } __OS_ENUM_ATTR_CLOSED _name##_t
#define OS_OPTIONS(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } __OS_ENUM_ATTR __OS_OPTIONS_ATTR _name##_t
#define OS_CLOSED_OPTIONS(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } __OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR _name##_t
#else
/*!
* There is unfortunately no good way in plain C to have both fixed-type enums
* and enforcement for clang's enum_extensibility extensions. The primary goal
* of these macros is to allow you to define an enum and specify its width in a
* single statement, and for plain C that is accomplished by defining an
* anonymous enum and then separately typedef'ing the requested type name to the
* requested underlying integer type. So the type emitted actually has no
* relationship at all to the enum, and therefore while the compiler could
* enforce enum extensibility if you used the enum type, it cannot do so if you
* use the "_t" type resulting from this expression.
*
* But we still define a named enum type and decorate it appropriately for you,
* so if you really want the enum extensibility enforcement, you can use the
* enum type yourself, i.e. when compiling with a C compiler:
*
* OS_CLOSED_ENUM(my_type, uint64_t,
* FOO,
* BAR,
* BAZ,
* );
*
* my_type_t mt = 98; // legal
* enum my_type emt = 98; // illegal
*
* But be aware that the underlying enum type's width is subject only to the C
* language's guarantees -- namely that it will be compatible with int, char,
* and unsigned char. It is not safe to rely on the size of this type.
*
* When compiling in ObjC or C++, both of the above assignments are illegal.
*/
#define __OS_ENUM_C_FALLBACK(_name, _type, ...) \
typedef _type _name##_t; enum _name { __VA_ARGS__ }
#define OS_ENUM(_name, _type, ...) \
typedef _type _name##_t; enum { __VA_ARGS__ }
#define OS_CLOSED_ENUM(_name, _type, ...) \
__OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
__OS_ENUM_ATTR_CLOSED
#define OS_OPTIONS(_name, _type, ...) \
__OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
__OS_ENUM_ATTR __OS_OPTIONS_ATTR
#define OS_CLOSED_OPTIONS(_name, _type, ...) \
__OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
__OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR
#endif // __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
Clangs docs on its support:
https://clang.llvm.org/docs/LanguageExtensions.html#enumerations-with-a-fixed-underlying-type
https://clang.llvm.org/docs/LanguageExtensions.html#c-11-strongly-typed-enumerations
C23 adds a feature from C++11 that allows the storage type for an
enumdefinition to be specifies with the syntax:This has been supported by C compilers for quite a while, and is used in places like macOS's system headers. For example, in
MacOSX.sdk/usr/include/sys/mount.h, there is the following definition:which expands to
For reference, definition of
OS_ENUMis guarded by come__has_extensionchecks, and I guess at least one must be true when c2hs is parsing the file:Clangs docs on its support:
https://clang.llvm.org/docs/LanguageExtensions.html#enumerations-with-a-fixed-underlying-type
https://clang.llvm.org/docs/LanguageExtensions.html#c-11-strongly-typed-enumerations