zhouyizhou updated this revision to Diff 508350. zhouyizhou added a comment.
Add 128-bit integer support to enum element like GCC extension do. Also test coverage around _BitInt which can be arbitrarily large depending on the target. Also leave room for improvements to C2X because C2x made changes in this area to how we calculate what type to represent the enumerations in. Signed-off-by: Zhouyi Zhou <zhouzho...@gmail.com> CHANGES SINCE LAST ACTION https://reviews.llvm.org/D144157/new/ https://reviews.llvm.org/D144157 Files: clang/lib/Sema/SemaDecl.cpp clang/test/AST/Interp/enums-targets.cpp clang/test/CXX/drs/dr3xx.cpp clang/test/CodeGen/enum2.c clang/test/Sema/enum.c
Index: clang/test/Sema/enum.c =================================================================== --- clang/test/Sema/enum.c +++ clang/test/Sema/enum.c @@ -14,7 +14,7 @@ }; // minll maxull -enum x // expected-warning {{enumeration values exceed range of largest integer}} +enum x { 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'}} Index: clang/test/CodeGen/enum2.c =================================================================== --- clang/test/CodeGen/enum2.c +++ clang/test/CodeGen/enum2.c @@ -1,15 +1,43 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown %s -debug-info-kind=limited -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -debug-info-kind=limited -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c2x -triple x86_64-linux-gnu %s -debug-info-kind=limited -emit-llvm -o - | FileCheck %s int v; enum e { MAX }; +__uint128_t v1; +enum b { + b0 = (__uint128_t)0x123456789abcdef0ULL << 64|0x0fedcba987654321ULL, +}; + +#if __STDC_VERSION__ >= 202000L +_BitInt(256) v2; +enum c { + c0 = 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1wb + // TODO: check c0's debug inform under c2x +}; +#endif + void foo (void) { v = MAX; + // CHECK: store i32 0, ptr @v, align 4 + v1 = b0; + // CHECK: store i128 24197857203266734864629346612071973665, ptr @v1, align 16 +#if __STDC_VERSION__ >= 202000L + v2 = c0; + // TODO: check how v2's value is changed by the _BitInt enum under c2x +#endif } + // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, // CHECK-SAME: baseType: ![[LONG:[0-9]+]] // CHECK-SAME: elements: ![[ELTS:[0-9]+]] // CHECK: ![[LONG]] = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) // CHECK: ![[ELTS]] = !{![[MAX:[0-9]+]]} // CHECK: ![[MAX]] = !DIEnumerator(name: "MAX", value: 0) +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, +// CHECK-SAME: baseType: ![[BTYPE:[0-9]+]] +// CHECK-SAME: elements: ![[ELTS:[0-9]+]] +// CHECK: ![[BTYPE]] = !DIBasicType(name: "unsigned __int128", size: 128, encoding: DW_ATE_unsigned) +// CHECK: ![[ELTS]] = !{![[E:[0-9]+]]} +// CHECK: ![[E]] = !DIEnumerator(name: "b0", value: 24197857203266734864629346612071973665, isUnsigned: true) Index: clang/test/CXX/drs/dr3xx.cpp =================================================================== --- clang/test/CXX/drs/dr3xx.cpp +++ clang/test/CXX/drs/dr3xx.cpp @@ -1079,8 +1079,8 @@ namespace dr377 { // dr377: yes enum E { // expected-error {{enumeration values exceed range of largest integer}} - a = -__LONG_LONG_MAX__ - 1, // expected-error 0-1{{extension}} - b = 2 * (unsigned long long)__LONG_LONG_MAX__ // expected-error 0-2{{extension}} + a = -((__int128_t)__LONG_LONG_MAX__ << 64|__LONG_LONG_MAX__) - 1, // expected-error 0-2{{extension}} + b = 2 * ((__uint128_t)__LONG_LONG_MAX__ << 64|__LONG_LONG_MAX__) // expected-error 0-2{{extension}} }; } Index: clang/test/AST/Interp/enums-targets.cpp =================================================================== --- clang/test/AST/Interp/enums-targets.cpp +++ clang/test/AST/Interp/enums-targets.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple i686-pc-linux -fexperimental-new-constant-interpreter -verify %s // RUN: %clang_cc1 -triple i686-pc-linux -verify %s -// RUN: %clang_cc1 -triple x86_64-pc-linux -fexperimental-new-constant-interpreter -verify=warn %s -// RUN: %clang_cc1 -triple x86_64-pc-linux -verify=warn %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -verify %s // RUN: %clang_cc1 -triple x86_64-windows-msvc -fexperimental-new-constant-interpreter -verify %s // RUN: %clang_cc1 -triple x86_64-windows-msvc -verify %s // RUN: %clang_cc1 -triple hexagon -fexperimental-new-constant-interpreter -verify %s @@ -11,7 +11,7 @@ /// This test is split out from the rest since the output is target dependent. -enum E { // warn-warning {{enumeration values exceed range of largest integer}} +enum E { E1 = -__LONG_MAX__ -1L, E2 = __LONG_MAX__ *2UL+1UL }; Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -19151,12 +19151,19 @@ EltTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast) .get(); - } else if (getLangOpts().CPlusPlus) { + } else if (getLangOpts().CPlusPlus || getLangOpts().C2x) { // C++11 [dcl.enum]p5: // If the underlying type is not fixed, the type of each enumerator // is the type of its initializing value: // - If an initializer is specified for an enumerator, the // initializing value has the same type as the expression. + + // C2x 6.7.2.2p2: + // For all the integer constant expressions which make up the values + // of the enumeration constant, there shall be an + // implementation-defined signed or unsigned integer type (excluding + // the bit-precise integer types) capable of representing all of the + // values. EltTy = Val->getType(); } else { // C99 6.7.2.2p2: @@ -19660,10 +19667,20 @@ BestType = Context.LongTy; } else { BestWidth = Context.getTargetInfo().getLongLongWidth(); - - if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) - Diag(Enum->getLocation(), diag::ext_enum_too_large); - BestType = Context.LongLongTy; + if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) { + BestType = Context.LongLongTy; + } else { + BestWidth = 128; + // TODO: C2x 6.7.2.2p2: + // For all the integer constant expressions which make up the values + // of the enumeration constant, there shall be an + // implementation-defined signed or unsigned integer type (excluding + // the bit-precise integer types) capable of representing all of the + // values. + if (NumNegativeBits > 128 || NumPositiveBits >= 128) + Diag(Enum->getLocation(), diag::ext_enum_too_large); + BestType = Context.Int128Ty; + } } } BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType); @@ -19691,14 +19708,27 @@ BestPromotionType = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) ? Context.UnsignedLongTy : Context.LongTy; - } else { - BestWidth = Context.getTargetInfo().getLongLongWidth(); - assert(NumPositiveBits <= BestWidth && - "How could an initializer get larger than ULL?"); + } else if (NumPositiveBits <= + (BestWidth = Context.getTargetInfo().getLongLongWidth())) { BestType = Context.UnsignedLongLongTy; - BestPromotionType - = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) - ? Context.UnsignedLongLongTy : Context.LongLongTy; + BestPromotionType = + (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedLongLongTy + : Context.LongLongTy; + } else { + BestWidth = 128; + BestType = Context.UnsignedInt128Ty; + BestPromotionType = + (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedInt128Ty + : Context.Int128Ty; + // TODO: C2x 6.7.2.2p2: + // For all the integer constant expressions which make up the values + // of the enumeration constant, there shall be an implementation-defined + // signed or unsigned integer type (excluding the bit-precise integer + // types) capable of representing all of the values. + if (NumPositiveBits > 128) + Diag(Enum->getLocation(), diag::ext_enum_too_large); } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits