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

Reply via email to