https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/103917
>From eee57bcc211a8a045c0102ebb2f4410d52d657f6 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Wed, 14 Aug 2024 05:56:18 -0700 Subject: [PATCH 1/5] [clang][C23] Support N3029 Improved Normal Enumerations Basically clang already implemented 90% of the feature as an extension. This commit disables warnings for C23 and aligns types of enumerators according to the recent wording. --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaDecl.cpp | 44 +++++++++++++++------------ clang/test/C/C23/n3029.c | 59 +++++++++++++++++++++++++++++++++++++ clang/test/Sema/enum.c | 52 +++++++++++++++++++++++++------- clang/www/c_status.html | 2 +- 5 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 clang/test/C/C23/n3029.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6796a619ba97f8..376ed0facc8504 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -125,6 +125,8 @@ C2y Feature Support C23 Feature Support ^^^^^^^^^^^^^^^^^^^ +- Clang now supports `N3029 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm>`_ Improved Normal Enumerations. + Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 641b180527da55..03f14487d0b80e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19474,11 +19474,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // representable as an int. // Complain if the value is not representable in an int. - if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) - Diag(IdLoc, diag::ext_enum_value_not_int) - << toString(EnumVal, 10) << Val->getSourceRange() - << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); - else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { + if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) { + if (!getLangOpts().C23) + Diag(IdLoc, diag::ext_enum_value_not_int) + << toString(EnumVal, 10) << Val->getSourceRange() + << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); + } else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).get(); } @@ -19553,12 +19554,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // If we're not in C++, diagnose the overflow of enumerator values, // which in C99 means that the enumerator value is not representable in - // an int (C99 6.7.2.2p2). However, we support GCC's extension that - // permits enumerator values that are representable in some larger - // integral type. - if (!getLangOpts().CPlusPlus && !T.isNull()) + // an int (C99 6.7.2.2p2). However C23 permits enumerator values that + // are representable in some larger integral type and we allow it in + // older language modes as an extension. + if (!getLangOpts().CPlusPlus && !getLangOpts().C23 && !T.isNull()) Diag(IdLoc, diag::warn_enum_value_overflow); - } else if (!getLangOpts().CPlusPlus && + } else if (!getLangOpts().CPlusPlus && !getLangOpts().C23 && !EltTy->isDependentType() && !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { // Enforce C99 6.7.2.2p2 even when we compute the next value. @@ -19882,9 +19883,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, return; } - // TODO: If the result value doesn't fit in an int, it must be a long or long - // long value. ISO C does not support this, but GCC does as an extension, - // emit a warning. unsigned IntWidth = Context.getTargetInfo().getIntWidth(); unsigned CharWidth = Context.getTargetInfo().getCharWidth(); unsigned ShortWidth = Context.getTargetInfo().getShortWidth(); @@ -19893,13 +19891,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, // reverse the list. unsigned NumNegativeBits = 0; unsigned NumPositiveBits = 0; + bool MembersRepresentableByInt = true; for (unsigned i = 0, e = Elements.size(); i != e; ++i) { EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]); if (!ECD) continue; // Already issued a diagnostic. - const llvm::APSInt &InitVal = ECD->getInitVal(); + llvm::APSInt InitVal = ECD->getInitVal(); // Keep track of the size of positive and negative values. if (InitVal.isUnsigned() || InitVal.isNonNegative()) { @@ -19911,6 +19910,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, NumNegativeBits = std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits()); } + MembersRepresentableByInt &= + isRepresentableIntegerValue(Context, InitVal, Context.IntTy); } // If we have an empty set of enumerators we still need one bit. @@ -19932,7 +19933,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, // int, long long int, or unsigned long long int. // C99 6.4.4.3p2: // An identifier declared as an enumeration constant has type int. - // The C99 rule is modified by a gcc extension + // The C99 rule is modified by C23. QualType BestPromotionType; bool Packed = Enum->hasAttr<PackedAttr>(); @@ -20026,7 +20027,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, auto *ECD = cast_or_null<EnumConstantDecl>(D); if (!ECD) continue; // Already issued a diagnostic. - // Standard C says the enumerators have int type, but we allow, as an + // C99 says the enumerators have int type, but we allow, as an // extension, the enumerators to be larger than int size. If each // enumerator value fits in an int, type it as an int, otherwise type it the // same as the enumerator decl itself. This means that in "enum { X = 1U }" @@ -20040,9 +20041,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, QualType NewTy; unsigned NewWidth; bool NewSign; - if (!getLangOpts().CPlusPlus && - !Enum->isFixed() && - isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { + if (!getLangOpts().CPlusPlus && !Enum->isFixed() && + MembersRepresentableByInt) { + // C23 6.7.3.3.3p15: + // The enumeration member type for an enumerated type without fixed + // underlying type upon completion is: + // - int if all the values of the enumeration are representable as an + // int; or, + // - the enumerated type NewTy = Context.IntTy; NewWidth = IntWidth; NewSign = true; diff --git a/clang/test/C/C23/n3029.c b/clang/test/C/C23/n3029.c new file mode 100644 index 00000000000000..d0dccb02501133 --- /dev/null +++ b/clang/test/C/C23/n3029.c @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -verify -fsyntax-only --embed-dir=%S/Inputs -std=c23 %s -pedantic + +#include <limits.h> + +#define GET_TYPE_INT(x) _Generic(x, \ + char: 1,\ + unsigned char: 2,\ + signed char: 3,\ + short: 4,\ + unsigned short: 5,\ + int: 6,\ + unsigned int: 7,\ + long: 8,\ + unsigned long: 9,\ + long long: 10,\ + unsigned long long: 11,\ + default: 0xFF\ + )\ + +enum x { +a = INT_MAX, +b = ULLONG_MAX, +a_type = GET_TYPE_INT(a), +b_type = GET_TYPE_INT(b) +}; + +static_assert(GET_TYPE_INT(a) == GET_TYPE_INT(b)); + +extern enum x e_a; +extern __typeof(b) e_a; +extern __typeof(a) e_a; + +enum a { + a0 = 0xFFFFFFFFFFFFFFFFULL +}; + +_Bool e () { + return a0; +} + +int f () { + return a0; // expected-warning {{implicit conversion from 'unsigned long' to 'int' changes value from 18446744073709551615 to -1}} +} + +unsigned long g () { + return a0; +} + +unsigned long long h () { + return a0; +} + +enum big_enum { + big_enum_a = LONG_MAX, + big_enum_b = a + 1, + big_enum_c = ULLONG_MAX +}; + +static_assert(GET_TYPE_INT(big_enum_a) == GET_TYPE_INT(big_enum_b)); diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c index b0707914c0d852..d2cd27a0c02299 100644 --- a/clang/test/Sema/enum.c +++ b/clang/test/Sema/enum.c @@ -1,23 +1,23 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify -pedantic +// RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify=expected,c99 -pedantic // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fsyntax-only -std=c23 -verify -pedantic enum e {A, - B = 42LL << 32, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} + B = 42LL << 32, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} C = -4, D = 12456 }; enum f { a = -2147483648, b = 2147483647 }; // ok. enum g { // too negative - c = -2147483649, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} + c = -2147483649, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} d = 2147483647 }; enum h { e = -2147483648, // too pos - f = 2147483648, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} - i = 0xFFFF0000 // expected-warning {{too large}} + f = 2147483648, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} + i = 0xFFFF0000 // c99-warning {{too large}} }; // minll maxull enum x // expected-warning {{enumeration values exceed range of largest integer}} -{ y = -9223372036854775807LL-1, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} -z = 9223372036854775808ULL }; // expected-warning {{ISO C restricts enumerator values to range of 'int'}} +{ y = -9223372036854775807LL-1, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} +z = 9223372036854775808ULL }; // c99-warning {{ISO C restricts enumerator values to range of 'int'}} int test(void) { return sizeof(enum e) ; @@ -172,10 +172,8 @@ enum class GH42372_2 { #if __STDC_VERSION__ >= 202311L // FIXME: GCC picks __uint128_t as the underlying type for the enumeration // value and Clang picks unsigned long long. -// FIXME: Clang does not yet implement WG14 N3029, so the warning about -// restricting enumerator values to 'int' is not correct. enum GH59352 { // expected-warning {{enumeration values exceed range of largest integer}} - BigVal = 66666666666666666666wb // expected-warning {{ISO C restricts enumerator values to range of 'int' (66666666666666666666 is too large)}} + BigVal = 66666666666666666666wb // c99-warning {{ISO C restricts enumerator values to range of 'int' (66666666666666666666 is too large)}} }; _Static_assert(BigVal == 66666666666666666666wb); /* expected-error {{static assertion failed due to requirement 'BigVal == 66666666666666666666wb'}} expected-note {{expression evaluates to '11326434445538011818 == 66666666666666666666'}} @@ -191,4 +189,38 @@ _Static_assert( __uint128_t : 1 ) ); + +#include <limits.h> + +void fooinc23() { + enum E1 { + V1 = INT_MAX + } e1; + + enum E2 { + V2 = INT_MAX, + V3 + } e2; + + enum E3 { + V4 = INT_MAX, + V5 = LONG_MIN + } e3; + + enum E4 { + V6 = 1u, + V7 = 2wb + } e4; + + _Static_assert(_Generic(V1, int : 1)); + _Static_assert(_Generic(V2, int : 0, unsigned int : 1)); + _Static_assert(_Generic(V3, int : 0, unsigned int : 1)); + _Static_assert(_Generic(V4, int : 0, signed long : 1)); + _Static_assert(_Generic(V5, int : 0, signed long : 1)); + _Static_assert(_Generic(V6, int : 1)); + _Static_assert(_Generic(V7, int : 1)); + _Static_assert(_Generic((enum E4){}, unsigned int : 1)); + +} + #endif // __STDC_VERSION__ >= 202311L diff --git a/clang/www/c_status.html b/clang/www/c_status.html index a5d04506b642bc..cc2c83d5225e98 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -1160,7 +1160,7 @@ <h2 id="c2x">C23 implementation status</h2> <tr> <td>Improved normal enumerations</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3029.htm">N3029</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 20</td> </tr> <tr> <td>Relax requirements for va_start</td> >From d766f1924d3724eb13c1b50e2018a0f3becefabb Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Thu, 15 Aug 2024 03:47:15 -0700 Subject: [PATCH 2/5] Fix test on Windows --- clang/test/C/C23/n3029.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/C/C23/n3029.c b/clang/test/C/C23/n3029.c index d0dccb02501133..b5c331ab96c4de 100644 --- a/clang/test/C/C23/n3029.c +++ b/clang/test/C/C23/n3029.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -fsyntax-only --embed-dir=%S/Inputs -std=c23 %s -pedantic +// RUN: %clang_cc1 -verify -triple x86_64-unknown-linux-gnu -fsyntax-only --embed-dir=%S/Inputs -std=c23 %s -pedantic #include <limits.h> >From 06c369998e8d2e3d1ea4b409f141928fc507503c Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Mon, 2 Sep 2024 05:02:33 -0700 Subject: [PATCH 3/5] Add -Wpre-c23-compat warning --- clang/docs/ReleaseNotes.rst | 2 +- .../include/clang/Basic/DiagnosticSemaKinds.td | 9 ++++++--- clang/lib/Sema/SemaDecl.cpp | 18 ++++++++++-------- clang/test/C/C23/n3029.c | 16 ++++++++-------- clang/test/Misc/warning-flags.c | 2 +- clang/test/Sema/enum.c | 10 +++++----- 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 376ed0facc8504..6af7769177ecbe 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -125,7 +125,7 @@ C2y Feature Support C23 Feature Support ^^^^^^^^^^^^^^^^^^^ -- Clang now supports `N3029 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm>`_ Improved Normal Enumerations. +- Clang now supports `N3029 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3029.htm>`_ Improved Normal Enumerations. Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 554dbaff2ce0d8..fa2ba4400ae052 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6185,9 +6185,12 @@ def err_misplaced_ivar : Error< def warn_ivars_in_interface : Warning< "declaration of instance variables in the interface is deprecated">, InGroup<DiagGroup<"objc-interface-ivars">>, DefaultIgnore; -def ext_enum_value_not_int : Extension< - "ISO C restricts enumerator values to range of 'int' (%0 is too " - "%select{small|large}1)">; +def ext_c23_enum_value_not_int : Extension< + "enumerator values exceeding range of 'int' is a C23 extension (%0 is too " + "%select{small|large}1)">, InGroup<C23>; +def warn_c17_compat_enum_value_not_int : Warning< + "enumerator values exceeding range of 'int' is incompatible with C standards before C23 (%0 is too " + "%select{small|large}1)">, DefaultIgnore, InGroup<CPre23Compat>; def ext_enum_too_large : ExtWarn< "enumeration values exceed range of largest integer">, InGroup<EnumTooLarge>; def ext_enumerator_increment_too_large : ExtWarn< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 03f14487d0b80e..d7e8e536431656 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19475,10 +19475,11 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // Complain if the value is not representable in an int. if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) { - if (!getLangOpts().C23) - Diag(IdLoc, diag::ext_enum_value_not_int) - << toString(EnumVal, 10) << Val->getSourceRange() - << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); + Diag(IdLoc, (getLangOpts().C23) + ? diag::warn_c17_compat_enum_value_not_int + : diag::ext_c23_enum_value_not_int) + << toString(EnumVal, 10) << Val->getSourceRange() + << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); } else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).get(); @@ -19559,12 +19560,13 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // older language modes as an extension. if (!getLangOpts().CPlusPlus && !getLangOpts().C23 && !T.isNull()) Diag(IdLoc, diag::warn_enum_value_overflow); - } else if (!getLangOpts().CPlusPlus && !getLangOpts().C23 && - !EltTy->isDependentType() && + } else if (!getLangOpts().CPlusPlus && !EltTy->isDependentType() && !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { // Enforce C99 6.7.2.2p2 even when we compute the next value. - Diag(IdLoc, diag::ext_enum_value_not_int) - << toString(EnumVal, 10) << 1; + Diag(IdLoc, (getLangOpts().C23) + ? diag::warn_c17_compat_enum_value_not_int + : diag::ext_c23_enum_value_not_int) + << toString(EnumVal, 10) << 1; } } } diff --git a/clang/test/C/C23/n3029.c b/clang/test/C/C23/n3029.c index b5c331ab96c4de..40d23472c4bdcd 100644 --- a/clang/test/C/C23/n3029.c +++ b/clang/test/C/C23/n3029.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -triple x86_64-unknown-linux-gnu -fsyntax-only --embed-dir=%S/Inputs -std=c23 %s -pedantic +// RUN: %clang_cc1 -verify -triple x86_64-unknown-linux-gnu -fsyntax-only --embed-dir=%S/Inputs -std=c23 %s -pedantic -Wpre-c23-compat #include <limits.h> @@ -19,19 +19,19 @@ enum x { a = INT_MAX, -b = ULLONG_MAX, +b = ULLONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} a_type = GET_TYPE_INT(a), b_type = GET_TYPE_INT(b) }; -static_assert(GET_TYPE_INT(a) == GET_TYPE_INT(b)); +_Static_assert(GET_TYPE_INT(a) == GET_TYPE_INT(b), "ok"); extern enum x e_a; extern __typeof(b) e_a; extern __typeof(a) e_a; enum a { - a0 = 0xFFFFFFFFFFFFFFFFULL + a0 = 0xFFFFFFFFFFFFFFFFULL // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} }; _Bool e () { @@ -51,9 +51,9 @@ unsigned long long h () { } enum big_enum { - big_enum_a = LONG_MAX, - big_enum_b = a + 1, - big_enum_c = ULLONG_MAX + big_enum_a = LONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} + big_enum_b = a + 1, // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} + big_enum_c = ULLONG_MAX // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} }; -static_assert(GET_TYPE_INT(big_enum_a) == GET_TYPE_INT(big_enum_b)); +_Static_assert(GET_TYPE_INT(big_enum_a) == GET_TYPE_INT(big_enum_b), "ok"); diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c index cdbe1e95cba965..6bcc41888a6343 100644 --- a/clang/test/Misc/warning-flags.c +++ b/clang/test/Misc/warning-flags.c @@ -88,4 +88,4 @@ CHECK-NEXT: warn_weak_import The list of warnings in -Wpedantic should NEVER grow. -CHECK: Number in -Wpedantic (not covered by other -W flags): 25 +CHECK: Number in -Wpedantic (not covered by other -W flags): 24 diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c index d2cd27a0c02299..b9183d3fb2b8c8 100644 --- a/clang/test/Sema/enum.c +++ b/clang/test/Sema/enum.c @@ -1,23 +1,23 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify=expected,c99 -pedantic // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fsyntax-only -std=c23 -verify -pedantic enum e {A, - B = 42LL << 32, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} + B = 42LL << 32, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} C = -4, D = 12456 }; enum f { a = -2147483648, b = 2147483647 }; // ok. enum g { // too negative - c = -2147483649, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} + c = -2147483649, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} d = 2147483647 }; enum h { e = -2147483648, // too pos - f = 2147483648, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} + f = 2147483648, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} i = 0xFFFF0000 // c99-warning {{too large}} }; // minll maxull enum x // expected-warning {{enumeration values exceed range of largest integer}} -{ y = -9223372036854775807LL-1, // c99-warning {{ISO C restricts enumerator values to range of 'int'}} -z = 9223372036854775808ULL }; // c99-warning {{ISO C restricts enumerator values to range of 'int'}} +{ y = -9223372036854775807LL-1, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} +z = 9223372036854775808ULL }; // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} int test(void) { return sizeof(enum e) ; >From 19e7922ab683652a1928fa36ff2d6ea854188c9a Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Wed, 4 Sep 2024 09:27:20 -0700 Subject: [PATCH 4/5] Adjustments + cr feedback --- .../clang/Basic/DiagnosticSemaKinds.td | 7 +++--- clang/lib/Sema/SemaDecl.cpp | 8 +++++-- clang/test/C/C23/n3029.c | 10 ++++----- clang/test/Misc/warning-flags.c | 3 +-- clang/test/Sema/enum.c | 22 +++++++++++++------ 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1dece377f6823..2423aa750435f1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1039,7 +1039,8 @@ def err_opencl_invalid_param : Error< "declaring function parameter of type %0 is not allowed%select{; did you forget * ?|}1">; def err_opencl_invalid_return : Error< "declaring function return value of type %0 is not allowed %select{; did you forget * ?|}1">; -def warn_enum_value_overflow : Warning<"overflow in enumeration value">; +def ext_c23_enum_value_int_overflow : Extension<"incremented enumerator value that is exceeding range of 'int' is a C23 extension">, InGroup<C23>; +def warn_c17_compat_enum_value_int_overflow : Warning<"incremented enumerator value that is exceeding range of 'int' is incompatible with C standards before C23">, InGroup<CPre23Compat>; def warn_pragma_options_align_reset_failed : Warning< "#pragma options align=reset failed: %0">, InGroup<IgnoredPragmas>; @@ -6195,10 +6196,10 @@ def warn_ivars_in_interface : Warning< "declaration of instance variables in the interface is deprecated">, InGroup<DiagGroup<"objc-interface-ivars">>, DefaultIgnore; def ext_c23_enum_value_not_int : Extension< - "enumerator values exceeding range of 'int' is a C23 extension (%0 is too " + "enumerator values exceeding range of 'int' are a C23 extension (%0 is too " "%select{small|large}1)">, InGroup<C23>; def warn_c17_compat_enum_value_not_int : Warning< - "enumerator values exceeding range of 'int' is incompatible with C standards before C23 (%0 is too " + "enumerator values exceeding range of 'int' are incompatible with C standards before C23 (%0 is too " "%select{small|large}1)">, DefaultIgnore, InGroup<CPre23Compat>; def ext_enum_too_large : ExtWarn< "enumeration values exceed range of largest integer">, InGroup<EnumTooLarge>; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 58a66617d326b4..96ab02a70c1b5b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19558,8 +19558,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // an int (C99 6.7.2.2p2). However C23 permits enumerator values that // are representable in some larger integral type and we allow it in // older language modes as an extension. - if (!getLangOpts().CPlusPlus && !getLangOpts().C23 && !T.isNull()) - Diag(IdLoc, diag::warn_enum_value_overflow); + // Exclude fixed enumerators since they are diagnosed with an error for + // this case. + if (!getLangOpts().CPlusPlus && !T.isNull() && !Enum->isFixed()) + Diag(IdLoc, (getLangOpts().C23) + ? diag::warn_c17_compat_enum_value_int_overflow + : diag::ext_c23_enum_value_int_overflow); } else if (!getLangOpts().CPlusPlus && !EltTy->isDependentType() && !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { // Enforce C99 6.7.2.2p2 even when we compute the next value. diff --git a/clang/test/C/C23/n3029.c b/clang/test/C/C23/n3029.c index 40d23472c4bdcd..d1f8306fb7709a 100644 --- a/clang/test/C/C23/n3029.c +++ b/clang/test/C/C23/n3029.c @@ -19,7 +19,7 @@ enum x { a = INT_MAX, -b = ULLONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} +b = ULLONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} a_type = GET_TYPE_INT(a), b_type = GET_TYPE_INT(b) }; @@ -31,7 +31,7 @@ extern __typeof(b) e_a; extern __typeof(a) e_a; enum a { - a0 = 0xFFFFFFFFFFFFFFFFULL // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} + a0 = 0xFFFFFFFFFFFFFFFFULL // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} }; _Bool e () { @@ -51,9 +51,9 @@ unsigned long long h () { } enum big_enum { - big_enum_a = LONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} - big_enum_b = a + 1, // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} - big_enum_c = ULLONG_MAX // expected-warning {{enumerator values exceeding range of 'int' is incompatible with C standards before C23}} + big_enum_a = LONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} + big_enum_b = a + 1, // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} + big_enum_c = ULLONG_MAX // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} }; _Static_assert(GET_TYPE_INT(big_enum_a) == GET_TYPE_INT(big_enum_b), "ok"); diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c index efadadc000e9cb..80c01099140f79 100644 --- a/clang/test/Misc/warning-flags.c +++ b/clang/test/Misc/warning-flags.c @@ -18,7 +18,7 @@ This test serves two purposes: The list of warnings below should NEVER grow. It should gradually shrink to 0. -CHECK: Warnings without flags (63): +CHECK: Warnings without flags (62): CHECK-NEXT: ext_expected_semi_decl_list CHECK-NEXT: ext_missing_whitespace_after_macro_name @@ -46,7 +46,6 @@ CHECK-NEXT: warn_drv_amdgpu_cov6 CHECK-NEXT: warn_drv_assuming_mfloat_abi_is CHECK-NEXT: warn_drv_clang_unsupported CHECK-NEXT: warn_drv_pch_not_first_include -CHECK-NEXT: warn_enum_value_overflow CHECK-NEXT: warn_expected_qualified_after_typename CHECK-NEXT: warn_fe_backend_unsupported CHECK-NEXT: warn_fe_cc_log_diagnostics_failure diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c index b9183d3fb2b8c8..80be9d24c8d990 100644 --- a/clang/test/Sema/enum.c +++ b/clang/test/Sema/enum.c @@ -1,23 +1,23 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify=expected,c99 -pedantic // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fsyntax-only -std=c23 -verify -pedantic enum e {A, - B = 42LL << 32, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} + B = 42LL << 32, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} C = -4, D = 12456 }; enum f { a = -2147483648, b = 2147483647 }; // ok. enum g { // too negative - c = -2147483649, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} + c = -2147483649, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} d = 2147483647 }; enum h { e = -2147483648, // too pos - f = 2147483648, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} + f = 2147483648, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} i = 0xFFFF0000 // c99-warning {{too large}} }; // minll maxull enum x // expected-warning {{enumeration values exceed range of largest integer}} -{ y = -9223372036854775807LL-1, // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} -z = 9223372036854775808ULL }; // c99-warning {{enumerator values exceeding range of 'int' is a C23 extension}} +{ y = -9223372036854775807LL-1, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} +z = 9223372036854775808ULL }; // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} int test(void) { return sizeof(enum e) ; @@ -169,11 +169,19 @@ enum class GH42372_2 { One }; +enum IncOverflow { + V2 = __INT_MAX__, + V3 // c99-warning {{incremented enumerator value that is exceeding range of 'int' is a C23 extension}} +#if __STDC_VERSION__ >= 202311L + // expected-warning@-2 {{incremented enumerator value that is exceeding range of 'int' is incompatible with C standards before C23}} +#endif +}; + #if __STDC_VERSION__ >= 202311L // FIXME: GCC picks __uint128_t as the underlying type for the enumeration // value and Clang picks unsigned long long. enum GH59352 { // expected-warning {{enumeration values exceed range of largest integer}} - BigVal = 66666666666666666666wb // c99-warning {{ISO C restricts enumerator values to range of 'int' (66666666666666666666 is too large)}} + BigVal = 66666666666666666666wb }; _Static_assert(BigVal == 66666666666666666666wb); /* expected-error {{static assertion failed due to requirement 'BigVal == 66666666666666666666wb'}} expected-note {{expression evaluates to '11326434445538011818 == 66666666666666666666'}} @@ -199,7 +207,7 @@ void fooinc23() { enum E2 { V2 = INT_MAX, - V3 + V3 // expected-warning {{incremented enumerator value that is exceeding range of 'int' is incompatible with C standards before C23}} } e2; enum E3 { >From 9d4ff0f83399266dc8659bf205ba8f1f84fb22af Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Fri, 6 Sep 2024 02:28:18 -0700 Subject: [PATCH 5/5] Accomodate review feedback --- .../clang/Basic/DiagnosticSemaKinds.td | 11 ++++---- clang/lib/Sema/SemaDecl.cpp | 18 ++++++------ clang/test/C/C23/n3029.c | 28 +++++++++++-------- clang/test/Sema/enum.c | 23 +++++++-------- 4 files changed, 41 insertions(+), 39 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 757c7494102df5..9be11217775381 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1039,8 +1039,6 @@ def err_opencl_invalid_param : Error< "declaring function parameter of type %0 is not allowed%select{; did you forget * ?|}1">; def err_opencl_invalid_return : Error< "declaring function return value of type %0 is not allowed %select{; did you forget * ?|}1">; -def ext_c23_enum_value_int_overflow : Extension<"incremented enumerator value that is exceeding range of 'int' is a C23 extension">, InGroup<C23>; -def warn_c17_compat_enum_value_int_overflow : Warning<"incremented enumerator value that is exceeding range of 'int' is incompatible with C standards before C23">, InGroup<CPre23Compat>; def warn_pragma_options_align_reset_failed : Warning< "#pragma options align=reset failed: %0">, InGroup<IgnoredPragmas>; @@ -6196,11 +6194,12 @@ def warn_ivars_in_interface : Warning< "declaration of instance variables in the interface is deprecated">, InGroup<DiagGroup<"objc-interface-ivars">>, DefaultIgnore; def ext_c23_enum_value_not_int : Extension< - "enumerator values exceeding range of 'int' are a C23 extension (%0 is too " - "%select{small|large}1)">, InGroup<C23>; + "%select{|incremented }0enumerator value which exceeds the range of 'int' is " + "a C23 extension (%1 is too %select{small|large}2)">, InGroup<C23>; def warn_c17_compat_enum_value_not_int : Warning< - "enumerator values exceeding range of 'int' are incompatible with C standards before C23 (%0 is too " - "%select{small|large}1)">, DefaultIgnore, InGroup<CPre23Compat>; + "%select{|incremented }0enumerator value which exceeds the range of 'int' is " + "incompatible with C standards before C23 (%1 is too %select{small|large}2)">, + DefaultIgnore, InGroup<CPre23Compat>; def ext_enum_too_large : ExtWarn< "enumeration values exceed range of largest integer">, InGroup<EnumTooLarge>; def ext_enumerator_increment_too_large : ExtWarn< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2d4082f7150943..c5ab6072f96361 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19479,10 +19479,10 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // Complain if the value is not representable in an int. if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) { - Diag(IdLoc, (getLangOpts().C23) + Diag(IdLoc, getLangOpts().C23 ? diag::warn_c17_compat_enum_value_not_int : diag::ext_c23_enum_value_not_int) - << toString(EnumVal, 10) << Val->getSourceRange() + << 0 << toString(EnumVal, 10) << Val->getSourceRange() << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); } else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. @@ -19565,16 +19565,16 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // Exclude fixed enumerators since they are diagnosed with an error for // this case. if (!getLangOpts().CPlusPlus && !T.isNull() && !Enum->isFixed()) - Diag(IdLoc, (getLangOpts().C23) - ? diag::warn_c17_compat_enum_value_int_overflow - : diag::ext_c23_enum_value_int_overflow); + Diag(IdLoc, getLangOpts().C23 + ? diag::warn_c17_compat_enum_value_not_int + : diag::ext_c23_enum_value_not_int) + << 1 << toString(EnumVal, 10) << 1; } else if (!getLangOpts().CPlusPlus && !EltTy->isDependentType() && !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { // Enforce C99 6.7.2.2p2 even when we compute the next value. - Diag(IdLoc, (getLangOpts().C23) - ? diag::warn_c17_compat_enum_value_not_int - : diag::ext_c23_enum_value_not_int) - << toString(EnumVal, 10) << 1; + Diag(IdLoc, getLangOpts().C23 ? diag::warn_c17_compat_enum_value_not_int + : diag::ext_c23_enum_value_not_int) + << 1 << toString(EnumVal, 10) << 1; } } } diff --git a/clang/test/C/C23/n3029.c b/clang/test/C/C23/n3029.c index d1f8306fb7709a..26d6dfdcc60462 100644 --- a/clang/test/C/C23/n3029.c +++ b/clang/test/C/C23/n3029.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -verify -triple x86_64-unknown-linux-gnu -fsyntax-only --embed-dir=%S/Inputs -std=c23 %s -pedantic -Wpre-c23-compat +// RUN: %clang_cc1 -verify=expected,all -triple x86_64-unknown-linux-gnu -fsyntax-only -std=c23 %s -Wpre-c23-compat +// RUN: %clang_cc1 -verify=pedantic,all -triple x86_64-unknown-linux-gnu -fsyntax-only -std=c17 %s -pedantic #include <limits.h> @@ -19,7 +20,8 @@ enum x { a = INT_MAX, -b = ULLONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} +b = ULLONG_MAX, // expected-warning {{enumerator value which exceeds the range of 'int' is incompatible with C standards before C23}} + // pedantic-warning@-1 {{enumerator value which exceeds the range of 'int' is a C23 extension}} a_type = GET_TYPE_INT(a), b_type = GET_TYPE_INT(b) }; @@ -31,29 +33,33 @@ extern __typeof(b) e_a; extern __typeof(a) e_a; enum a { - a0 = 0xFFFFFFFFFFFFFFFFULL // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} + a0 = 0xFFFFFFFFFFFFFFFFULL // expected-warning {{enumerator value which exceeds the range of 'int' is incompatible with C standards before C23}} + // pedantic-warning@-1 {{enumerator value which exceeds the range of 'int' is a C23 extension}} }; -_Bool e () { +_Bool e (void) { return a0; } -int f () { - return a0; // expected-warning {{implicit conversion from 'unsigned long' to 'int' changes value from 18446744073709551615 to -1}} +int f (void) { + return a0; // all-warning {{implicit conversion from 'unsigned long' to 'int' changes value from 18446744073709551615 to -1}} } -unsigned long g () { +unsigned long g (void) { return a0; } -unsigned long long h () { +unsigned long long h (void) { return a0; } enum big_enum { - big_enum_a = LONG_MAX, // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} - big_enum_b = a + 1, // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} - big_enum_c = ULLONG_MAX // expected-warning {{enumerator values exceeding range of 'int' are incompatible with C standards before C23}} + big_enum_a = LONG_MAX, // expected-warning {{enumerator value which exceeds the range of 'int' is incompatible with C standards before C23}} + // pedantic-warning@-1 {{enumerator value which exceeds the range of 'int' is a C23 extension}} + big_enum_b = a + 1, // expected-warning {{enumerator value which exceeds the range of 'int' is incompatible with C standards before C23}} + // pedantic-warning@-1 {{enumerator value which exceeds the range of 'int' is a C23 extension}} + big_enum_c = ULLONG_MAX // expected-warning {{enumerator value which exceeds the range of 'int' is incompatible with C standards before C23}} + // pedantic-warning@-1 {{enumerator value which exceeds the range of 'int' is a C23 extension}} }; _Static_assert(GET_TYPE_INT(big_enum_a) == GET_TYPE_INT(big_enum_b), "ok"); diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c index 80be9d24c8d990..4f6d04ba7f9182 100644 --- a/clang/test/Sema/enum.c +++ b/clang/test/Sema/enum.c @@ -1,23 +1,23 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify=expected,c99 -pedantic -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fsyntax-only -std=c23 -verify -pedantic +// RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify=expected,pre-c23 -pedantic +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fsyntax-only -std=c23 -verify=expected -pedantic enum e {A, - B = 42LL << 32, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} + B = 42LL << 32, // pre-c23-warning {{enumerator value which exceeds the range of 'int' is a C23 extension}} C = -4, D = 12456 }; enum f { a = -2147483648, b = 2147483647 }; // ok. enum g { // too negative - c = -2147483649, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} + c = -2147483649, // pre-c23-warning {{enumerator value which exceeds the range of 'int' is a C23 extension}} d = 2147483647 }; enum h { e = -2147483648, // too pos - f = 2147483648, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} - i = 0xFFFF0000 // c99-warning {{too large}} + f = 2147483648, // pre-c23-warning {{enumerator value which exceeds the range of 'int' is a C23 extension}} + i = 0xFFFF0000 // pre-c23-warning {{too large}} }; // minll maxull enum x // expected-warning {{enumeration values exceed range of largest integer}} -{ y = -9223372036854775807LL-1, // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} -z = 9223372036854775808ULL }; // c99-warning {{enumerator values exceeding range of 'int' are a C23 extension}} +{ y = -9223372036854775807LL-1, // pre-c23-warning {{enumerator value which exceeds the range of 'int' is a C23 extension}} +z = 9223372036854775808ULL }; // pre-c23-warning {{enumerator value which exceeds the range of 'int' is a C23 extension}} int test(void) { return sizeof(enum e) ; @@ -171,10 +171,7 @@ enum class GH42372_2 { enum IncOverflow { V2 = __INT_MAX__, - V3 // c99-warning {{incremented enumerator value that is exceeding range of 'int' is a C23 extension}} -#if __STDC_VERSION__ >= 202311L - // expected-warning@-2 {{incremented enumerator value that is exceeding range of 'int' is incompatible with C standards before C23}} -#endif + V3 // pre-c23-warning {{incremented enumerator value which exceeds the range of 'int' is a C23 extension}} }; #if __STDC_VERSION__ >= 202311L @@ -207,7 +204,7 @@ void fooinc23() { enum E2 { V2 = INT_MAX, - V3 // expected-warning {{incremented enumerator value that is exceeding range of 'int' is incompatible with C standards before C23}} + V3 } e2; enum E3 { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits