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); } } 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/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/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/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'}}