Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -19557,9 +19557,9 @@ if (Enum->isDependentType()) { for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - EnumConstantDecl *ECD = - cast_or_null(Elements[i]); - if (!ECD) continue; + EnumConstantDecl *ECD = cast_or_null(Elements[i]); + if (!ECD) + continue; ECD->setType(EnumType); } @@ -19568,9 +19568,6 @@ 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(); @@ -19581,9 +19578,9 @@ unsigned NumPositiveBits = 0; for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - EnumConstantDecl *ECD = - cast_or_null(Elements[i]); - if (!ECD) continue; // Already issued a diagnostic. + EnumConstantDecl *ECD = cast_or_null(Elements[i]); + if (!ECD) + continue; // Already issued a diagnostic. const llvm::APSInt &InitVal = ECD->getInitVal(); @@ -19594,8 +19591,8 @@ unsigned ActiveBits = InitVal.getActiveBits(); NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u}); } else { - NumNegativeBits = std::max(NumNegativeBits, - (unsigned)InitVal.getMinSignedBits()); + NumNegativeBits = + std::max(NumNegativeBits, (unsigned)InitVal.getMinSignedBits()); } } @@ -19637,8 +19634,7 @@ BestPromotionType = BestType; BestWidth = Context.getIntWidth(BestType); - } - else if (NumNegativeBits) { + } else if (NumNegativeBits) { // If there is a negative value, figure out the smallest integer type (of // int/long/longlong) that fits. // If it's packed, check also if it fits a char or a short. @@ -19681,23 +19677,36 @@ } else if (NumPositiveBits <= IntWidth) { BestType = Context.UnsignedIntTy; BestWidth = IntWidth; - BestPromotionType - = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) - ? Context.UnsignedIntTy : Context.IntTy; + BestPromotionType = + (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedIntTy + : Context.IntTy; } else if (NumPositiveBits <= (BestWidth = Context.getTargetInfo().getLongWidth())) { BestType = Context.UnsignedLongTy; - BestPromotionType - = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) - ? Context.UnsignedLongTy : Context.LongTy; - } else { + BestPromotionType = + (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedLongTy + : Context.LongTy; + } else if (NumPositiveBits <= Context.getTargetInfo().getLongLongWidth()) { BestWidth = Context.getTargetInfo().getLongLongWidth(); - assert(NumPositiveBits <= BestWidth && - "How could an initializer get larger than ULL?"); BestType = Context.UnsignedLongLongTy; - BestPromotionType - = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) - ? Context.UnsignedLongLongTy : Context.LongLongTy; + BestPromotionType = + (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedLongLongTy + : Context.LongLongTy; + } else { + BestWidth = 128; + assert(NumPositiveBits <= BestWidth && + "How could an initializer get larger than 128-bit?"); + assert(Context.getTargetInfo().hasInt128Type() && + "How could an initializer get larger than ULL " + "in target without 128-bit interger type support?"); + BestType = Context.UnsignedInt128Ty; + BestPromotionType = + (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) + ? Context.UnsignedInt128Ty + : Context.Int128Ty; } } @@ -19705,7 +19714,8 @@ // the type of the enum if needed. for (auto *D : Elements) { auto *ECD = cast_or_null(D); - if (!ECD) continue; // Already issued a diagnostic. + if (!ECD) + continue; // Already issued a diagnostic. // Standard C says the enumerators have int type, but we allow, as an // extension, the enumerators to be larger than int size. If each @@ -19721,8 +19731,7 @@ QualType NewTy; unsigned NewWidth; bool NewSign; - if (!getLangOpts().CPlusPlus && - !Enum->isFixed() && + if (!getLangOpts().CPlusPlus && !Enum->isFixed() && isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { NewTy = Context.IntTy; NewWidth = IntWidth; @@ -19761,21 +19770,22 @@ ECD->setType(NewTy); } - Enum->completeDefinition(BestType, BestPromotionType, - NumPositiveBits, NumNegativeBits); + Enum->completeDefinition(BestType, BestPromotionType, NumPositiveBits, + NumNegativeBits); CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType); if (Enum->isClosedFlag()) { for (Decl *D : Elements) { EnumConstantDecl *ECD = cast_or_null(D); - if (!ECD) continue; // Already issued a diagnostic. + if (!ECD) + continue; // Already issued a diagnostic. llvm::APSInt InitVal = ECD->getInitVal(); if (InitVal != 0 && !InitVal.isPowerOf2() && !IsValueInFlagEnum(Enum, InitVal, true)) Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range) - << ECD << Enum; + << ECD << Enum; } } Index: clang/test/Sema/enum.c =================================================================== --- clang/test/Sema/enum.c +++ clang/test/Sema/enum.c @@ -1,4 +1,9 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple %s -fsyntax-only -verify -pedantic +enum b { + b0 = (__uint128_t)-1, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} + b1 = (__uint128_t)0x123456789abcdef0ULL << 64|0x0fedcba987654321ULL, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} +}; + enum e {A, B = 42LL << 32, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} C = -4, D = 12456 };