https://github.com/Lu4nScr1pt1ng created https://github.com/llvm/llvm-project/pull/208230
When an enumerator has no explicit value and the previous enumerator has a _BitInt type whose maximum is reached, incrementing should widen to a suitably sized standard integer type (C23 6.7.3.3p12 excludes bit-precise types from the widening). Clang instead kept the _BitInt type and let the value wrap around, with a misleading "not representable in the largest integer type" warning. The problem is in getNextLargerIntegralType: it compared candidate types against the storage size of the previous type. A _BitInt(33) is stored in 64 bits, so no standard type looked larger and the widening never happened. Comparing against the value width (getIntWidth) fixes it: the enumerator now gets the next standard type that can hold the value, and the behavior matches GCC (verified against GCC 15.2). For standard integer types getIntWidth equals getTypeSize, so this changes behavior only for bit-precise types. The new tests in enum.c check the widened type and the value from inside the enum definition, like the reproducer in the issue; they fail without this change. Incrementing the max of a _BitInt(64) still warns, since no standard type can hold that value, and that case is covered too. Fixes #208163 >From 78d5741c987f5708bdab73ecb4b95db42ddef199 Mon Sep 17 00:00:00 2001 From: Lu4nScr1pt1ng <[email protected]> Date: Wed, 8 Jul 2026 11:18:15 -0300 Subject: [PATCH] [clang][Sema] Widen enumerators that overflow a _BitInt type (C23) getNextLargerIntegralType compared the candidate types against the storage size of the previous enumerator's type. A _BitInt(33) is stored in 64 bits, so no standard type looked larger and the widening never happened: the next enumerator kept the _BitInt type and its value wrapped around, with a bogus "not representable in the largest integer type" warning on top. Compare against the value width instead, so the enumerator widens to the next standard integer type that can hold the value, matching GCC. C23 6.7.3.3p12 excludes bit-precise types when picking that type. Fixes #208163 --- clang/docs/ReleaseNotes.md | 3 +++ clang/lib/Sema/SemaDecl.cpp | 6 +++++- clang/test/Sema/enum.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 5de8e546b7812..6f2bfb8a1bb0e 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -305,6 +305,9 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the the corresponding decimal floating-point types, `_Decimal32`, `_Decimal64`, and `_Decimal128`. (#GH116962) - Fixed a bug with deducing qualified inferred types with `auto`. `auto` can now be combined with `restrict` or `_Atomic` to form a properly-qualified type. (#GH207466) +- Fixed a bug where an enumerator following a `_BitInt`-typed enumerator kept + the bit-precise type and wrapped around on overflow instead of taking a + suitably sized standard integer type. (#GH208163) ### Objective-C Language Changes diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2fc4fac6d5351..b84dfb4c8d712 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20454,7 +20454,11 @@ static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { Context.UnsignedLongLongTy }; - unsigned BitWidth = Context.getTypeSize(T); + // Compare value widths, not storage sizes: a _BitInt(33) is stored in 64 + // bits but a 64-bit standard type can still represent its incremented + // value. C23 6.7.3.3p12 does not allow the widened type to be a + // bit-precise type either. + unsigned BitWidth = Context.getIntWidth(T); QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes : UnsignedIntegralTypes; for (unsigned I = 0; I != NumTypes; ++I) diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c index f0da5f097fa80..7fb5d61b25896 100644 --- a/clang/test/Sema/enum.c +++ b/clang/test/Sema/enum.c @@ -243,4 +243,33 @@ void fooinc23() { } +// GH208163: when incrementing a _BitInt enumerator overflows, the next +// enumerator should get a standard integer type, not the _BitInt type. +// C23 6.7.3.3p12 excludes bit-precise types when picking the larger type. +void fooinc23bitint() { + enum E5 { + V8 = 4294967295wb, // max of signed _BitInt(33) + V9, + V8InsideIsBitInt = _Generic(V8, _BitInt(33) : 1, default : 0), + V9InsideIsLong = _Generic(V9, long : 1, default : 0) + }; + + enum E6 { + V10 = 8589934591uwb, // max of unsigned _BitInt(33) + V11, + V11InsideIsULong = _Generic(V11, unsigned long : 1, default : 0) + }; + + enum E7 { + V12 = 9223372036854775807wb, // max of signed _BitInt(64) + V13 // expected-warning {{incremented enumerator value 9223372036854775808 is not representable in the largest integer type}} + }; + + _Static_assert(V8InsideIsBitInt == 1); + _Static_assert(V9InsideIsLong == 1); + _Static_assert(V9 == 4294967296wb); + _Static_assert(V11InsideIsULong == 1); + _Static_assert(V11 == 8589934592uwb); +} + #endif // __STDC_VERSION__ >= 202311L _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
