From e4ec4f0f95f44b131c256127d26c67258104be5a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 13 Aug 2026 12:22:21 -0700 Subject: [PATCH] libghostty: fix enum underlying type detection Use fixed int enum types for C++11, C23, Clang's fixed-enum extension, and GCC 13 or newer. Previously only finalized C23 mode selected an explicit underlying type, leaving C++ and common older C modes with implementation-defined enum types. --- include/ghostty/vt/types.h | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/include/ghostty/vt/types.h b/include/ghostty/vt/types.h index 672faa67c..bd3d37d65 100644 --- a/include/ghostty/vt/types.h +++ b/include/ghostty/vt/types.h @@ -39,18 +39,21 @@ * The Zig side backs all C enums with c_int, so the C declarations * must use int as their underlying type to maintain ABI compatibility. * - * C23 (detected via __STDC_VERSION__ >= 202311L) supports explicit - * enum underlying types with `enum : int { ... }`. For pre-C23 - * compilers, which are free to choose any type that can represent - * all values (C11 §6.7.2.2), we add an INT_MAX sentinel as the last - * entry to force the compiler to use int. + * C++11 and C23 support explicit enum underlying types with + * `enum : int { ... }`. Clang and GCC 13+ also support this syntax as + * an extension in older C language modes, so use it when available. + * + * Other pre-C23 C compilers are free to choose any type that can + * represent all values (C11 §6.7.2.2). For those compilers, we add an + * INT_MAX sentinel as the last entry so the compatible type must be + * able to represent INT_MAX. The exact compatible type and its + * signedness remain implementation-defined in this fallback. * * INT_MAX is used rather than a fixed constant like 0xFFFFFFFF - * because enum constants must have type int (which is signed). - * Values above INT_MAX overflow signed int and are a constraint - * violation in standard C; compilers that accept them interpret them - * as negative values via two's complement, which can collide with - * legitimate negative enum values. + * because enum constants must have type int in pre-C23 C. Values above + * INT_MAX are a constraint violation there; compilers that accept them + * may interpret them as negative values via two's complement, which can + * collide with legitimate negative enum values. * * Usage: * @code @@ -61,7 +64,18 @@ * } Foo; * @endcode */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#if defined(__cplusplus) && \ + (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)) +#define GHOSTTY_ENUM_TYPED : int +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define GHOSTTY_ENUM_TYPED : int +#elif defined(__clang__) + #if __has_extension(c_fixed_enum) + #define GHOSTTY_ENUM_TYPED : int + #else + #define GHOSTTY_ENUM_TYPED + #endif +#elif defined(__GNUC__) && __GNUC__ >= 13 #define GHOSTTY_ENUM_TYPED : int #else #define GHOSTTY_ENUM_TYPED