Skip to content

Commit 3b7ba24

Browse files
authored
[C23] No longer assert on huge enumerator values (#81760)
C23 added the wb and uwb suffixes to generate a bit-precise integer value. These values can be larger than what is representable in intmax_t or uintmax_t. We were asserting that an enumerator constant could not have a value larger than unsigned long long but that's now a possibility. This patch turns the assertion into a "value too large" diagnostic. Note, we do not yet implement WG14 N3029 and so the behavior of this patch will cause the enumerator to be cast to unsigned long long, but this behavior may change in the future. GCC selects __uint128_t as the underlying type for such an enumeration and we may want to match that behavior in the future. This patch has several FIXME comments related to this and the release notes call out the possibility of a change in behavior in the future. Fixes #69352
1 parent 9923d29 commit 3b7ba24

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ Improvements to Clang's diagnostics
201201
- Added diagnostics for C11 keywords being incompatible with language standards
202202
before C11, under a new warning group: ``-Wpre-c11-compat``.
203203

204+
- Now diagnoses an enumeration constant whose value is larger than can be
205+
represented by ``unsigned long long``, which can happen with a large constant
206+
using the ``wb`` or ``uwb`` suffix. The maximal underlying type is currently
207+
``unsigned long long``, but this behavior may change in the future when Clang
208+
implements
209+
`WG14 N3029 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3029.htm>`_.
210+
Fixes `#69352 <https://github.com/llvm/llvm-project/issues/69352>`_.
211+
204212
Improvements to Clang's time-trace
205213
----------------------------------
206214

clang/lib/Sema/SemaDecl.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20317,8 +20317,13 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2031720317
? Context.UnsignedLongTy : Context.LongTy;
2031820318
} else {
2031920319
BestWidth = Context.getTargetInfo().getLongLongWidth();
20320-
assert(NumPositiveBits <= BestWidth &&
20321-
"How could an initializer get larger than ULL?");
20320+
if (NumPositiveBits > BestWidth) {
20321+
// This can happen with bit-precise integer types, but those are not
20322+
// allowed as the type for an enumerator per C23 6.7.2.2p4 and p12.
20323+
// FIXME: GCC uses __int128_t and __uint128_t for cases that fit within
20324+
// a 128-bit integer, we should consider doing the same.
20325+
Diag(Enum->getLocation(), diag::ext_enum_too_large);
20326+
}
2032220327
BestType = Context.UnsignedLongLongTy;
2032320328
BestPromotionType
2032420329
= (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus)

clang/test/Sema/enum.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify -pedantic
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fsyntax-only -std=c23 -verify -pedantic
23
enum e {A,
34
B = 42LL << 32, // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
45
C = -4, D = 12456 };
@@ -167,3 +168,27 @@ enum struct GH42372_1 { // expected-error {{expected identifier or '{'}}
167168
enum class GH42372_2 {
168169
One
169170
};
171+
172+
#if __STDC_VERSION__ >= 202311L
173+
// FIXME: GCC picks __uint128_t as the underlying type for the enumeration
174+
// value and Clang picks unsigned long long.
175+
// FIXME: Clang does not yet implement WG14 N3029, so the warning about
176+
// restricting enumerator values to 'int' is not correct.
177+
enum GH59352 { // expected-warning {{enumeration values exceed range of largest integer}}
178+
BigVal = 66666666666666666666wb // expected-warning {{ISO C restricts enumerator values to range of 'int' (66666666666666666666 is too large)}}
179+
};
180+
_Static_assert(BigVal == 66666666666666666666wb); /* expected-error {{static assertion failed due to requirement 'BigVal == 66666666666666666666wb'}}
181+
expected-note {{expression evaluates to '11326434445538011818 == 66666666666666666666'}}
182+
*/
183+
_Static_assert(
184+
_Generic(BigVal, // expected-error {{static assertion failed}}
185+
_BitInt(67) : 0,
186+
__INTMAX_TYPE__ : 0,
187+
__UINTMAX_TYPE__ : 0,
188+
long long : 0,
189+
unsigned long long : 0,
190+
__int128_t : 0,
191+
__uint128_t : 1
192+
)
193+
);
194+
#endif // __STDC_VERSION__ >= 202311L

0 commit comments

Comments
 (0)