diff options
author | Hans Wennborg <hans@hanshq.net> | 2015-01-20 19:27:49 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2015-01-20 19:27:49 +0000 |
commit | e2b4aa19430a7f0eb9a166b701e40c3dc4cdd53b (patch) | |
tree | 54b2a65851678bbf78c27a2403d70fd55553effe | |
parent | 2e151343a8de90fc29d2081c02fcb50b48fd23bd (diff) |
Revert "r222906 - Create a new 'flag_enum' attribute."
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_36@226593 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/Attr.td | 23 | ||||
-rw-r--r-- | include/clang/Basic/AttrDocs.td | 10 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | include/clang/Sema/AttributeList.h | 1 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 86 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 147 | ||||
-rw-r--r-- | test/Sema/attr-flag-enum.c | 73 | ||||
-rw-r--r-- | test/SemaCXX/attr-flag-enum-reject.cpp | 4 | ||||
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 7 |
12 files changed, 80 insertions, 286 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 8437461114..3ed7f8d6b1 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -224,14 +224,12 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag, string CustomDiag = customDiag; } -class LangOpt<string name, bit negated = 0> { +class LangOpt<string name> { string Name = name; - bit Negated = negated; } def MicrosoftExt : LangOpt<"MicrosoftExt">; def Borland : LangOpt<"Borland">; def CUDA : LangOpt<"CUDA">; -def COnly : LangOpt<"CPlusPlus", 1>; // Defines targets for target-specific attributes. The list of strings should // specify architectures for which the target applies, based off the ArchType @@ -709,25 +707,6 @@ def MinSize : InheritableAttr { let Documentation = [Undocumented]; } -def FlagEnum : InheritableAttr { - let Spellings = [GNU<"flag_enum">]; - let Subjects = SubjectList<[Enum]>; - let Documentation = [FlagEnumDocs]; - let LangOpts = [COnly]; - let AdditionalMembers = [{ -private: - llvm::APInt FlagBits; -public: - llvm::APInt &getFlagBits() { - return FlagBits; - } - - const llvm::APInt &getFlagBits() const { - return FlagBits; - } -}]; -} - def Flatten : InheritableAttr { let Spellings = [GCC<"flatten">]; let Subjects = SubjectList<[Function], ErrorDiag>; diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 918abb6072..530c6e7d10 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -1196,16 +1196,6 @@ behavior of the program is undefined. }]; } -def FlagEnumDocs : Documentation { - let Category = DocCatType; - let Content = [{ -This attribute can be added to an enumerator to signal to the compiler that it -is intended to be used as a flag type. This will cause the compiler to assume -that the range of the type includes all of the values that you can get by -manipulating bits of the enumerator when issuing warnings. - }]; -} - def MSInheritanceDocs : Documentation { let Category = DocCatType; let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance"; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 75d40b17a6..5edd3ddbc8 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -190,7 +190,6 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; def DanglingField : DiagGroup<"dangling-field">; def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; -def FlagEnum : DiagGroup<"flag-enum">; def InfiniteRecursion : DiagGroup<"infinite-recursion">; def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 8966c55d09..d2ee3f8b69 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2236,7 +2236,7 @@ def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" "functions, methods and blocks|functions, methods, and classes|" - "functions, methods, and parameters|classes|enums|variables|methods|" + "functions, methods, and parameters|classes|variables|methods|" "variables, functions and labels|fields and global variables|structs|" "variables and typedefs|thread-local variables|" "variables and fields|variables, data members and tag types|" @@ -4059,9 +4059,6 @@ def ext_enum_too_large : ExtWarn< def ext_enumerator_increment_too_large : ExtWarn< "incremented enumerator value %0 is not representable in the " "largest integer type">, InGroup<EnumTooLarge>; -def warn_flag_enum_constant_out_of_range : Warning< - "enumeration value %0 is out of range of flags in enumeration type %1">, - InGroup<FlagEnum>; def warn_illegal_constant_array_size : Extension< "size of static array must be an integer constant expression">; diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index dc85f5d208..5e543a5fa5 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -822,7 +822,6 @@ enum AttributeDeclKind { ExpectedFunctionMethodOrClass, ExpectedFunctionMethodOrParameter, ExpectedClass, - ExpectedEnum, ExpectedVariable, ExpectedMethod, ExpectedVariableFunctionOrLabel, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 74efa60c93..bba7c36834 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7971,12 +7971,6 @@ public: Expr *SrcExpr, AssignmentAction Action, bool *Complained = nullptr); - /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag - /// enum. If AllowMask is true, then we also allow the complement of a valid - /// value, to be used as a mask. - bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, - bool AllowMask) const; - /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant /// integer not in the range of enum values. void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 007470344f..a2e5b98d48 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -13519,49 +13519,6 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements, } } -bool -Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, - bool AllowMask) const { - FlagEnumAttr *FEAttr = ED->getAttr<FlagEnumAttr>(); - assert(FEAttr && "looking for value in non-flag enum"); - - llvm::APInt FlagMask = ~FEAttr->getFlagBits(); - unsigned Width = FlagMask.getBitWidth(); - - // We will try a zero-extended value for the regular check first. - llvm::APInt ExtVal = Val.zextOrSelf(Width); - - // A value is in a flag enum if either its bits are a subset of the enum's - // flag bits (the first condition) or we are allowing masks and the same is - // true of its complement (the second condition). When masks are allowed, we - // allow the common idiom of ~(enum1 | enum2) to be a valid enum value. - // - // While it's true that any value could be used as a mask, the assumption is - // that a mask will have all of the insignificant bits set. Anything else is - // likely a logic error. - if (!(FlagMask & ExtVal)) - return true; - - if (AllowMask) { - // Try a one-extended value instead. This can happen if the enum is wider - // than the constant used, in C with extensions to allow for wider enums. - // The mask will still have the correct behaviour, so we give the user the - // benefit of the doubt. - // - // FIXME: This heuristic can cause weird results if the enum was extended - // to a larger type and is signed, because then bit-masks of smaller types - // that get extended will fall out of range (e.g. ~0x1u). We currently don't - // detect that case and will get a false positive for it. In most cases, - // though, it can be fixed by making it a signed type (e.g. ~0x1), so it may - // be fine just to accept this as a warning. - ExtVal |= llvm::APInt::getHighBitsSet(Width, Width - Val.getBitWidth()); - if (!(FlagMask & ~ExtVal)) - return true; - } - - return false; -} - void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, SourceLocation RBraceLoc, Decl *EnumDeclX, ArrayRef<Decl *> Elements, @@ -13647,8 +13604,10 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, BestPromotionType = Context.getPromotedIntegerType(BestType); else BestPromotionType = BestType; - - BestWidth = Context.getIntWidth(BestType); + // We don't need to set BestWidth, because BestType is going to be the type + // of the enumerators, but we do anyway because otherwise some compilers + // warn that it might be used uninitialized. + BestWidth = CharWidth; } else if (NumNegativeBits) { // If there is a negative value, figure out the smallest integer type (of @@ -13713,15 +13672,10 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } } - FlagEnumAttr *FEAttr = Enum->getAttr<FlagEnumAttr>(); - if (FEAttr) - FEAttr->getFlagBits() = llvm::APInt(BestWidth, 0); - // Loop over all of the enumerator constants, changing their types to match - // the type of the enum if needed. If we have a flag type, we also prepare the - // FlagBits cache. - for (auto *D : Elements) { - auto *ECD = cast_or_null<EnumConstantDecl>(D); + // the type of the enum if needed. + 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. // Standard C says the enumerators have int type, but we allow, as an @@ -13751,7 +13705,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // enum-specifier, each enumerator has the type of its // enumeration. ECD->setType(EnumType); - goto flagbits; + continue; } else { NewTy = BestType; NewWidth = BestWidth; @@ -13778,32 +13732,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(EnumType); else ECD->setType(NewTy); - -flagbits: - // Check to see if we have a constant with exactly one bit set. Note that x - // & (x - 1) will be nonzero if and only if x has more than one bit set. - if (FEAttr) { - llvm::APInt ExtVal = InitVal.zextOrSelf(BestWidth); - if (ExtVal != 0 && !(ExtVal & (ExtVal - 1))) { - FEAttr->getFlagBits() |= ExtVal; - } - } } - if (FEAttr) { - for (Decl *D : Elements) { - EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(D); - if (!ECD) continue; // Already issued a diagnostic. - - llvm::APSInt InitVal = ECD->getInitVal(); - if (InitVal != 0 && !IsValueInFlagEnum(Enum, InitVal, true)) - Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range) - << ECD << Enum; - } - } - - - Enum->completeDefinition(BestType, BestPromotionType, NumPositiveBits, NumNegativeBits); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 17a849ea7a..dcab25e7fe 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4395,9 +4395,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_OptimizeNone: handleOptimizeNoneAttr(S, D, Attr); break; - case AttributeList::AT_FlagEnum: - handleSimpleAttribute<FlagEnumAttr>(S, D, Attr); - break; case AttributeList::AT_Flatten: handleSimpleAttribute<FlattenAttr>(S, D, Attr); break; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 22ed930820..0d1da4540e 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -687,39 +687,26 @@ static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val, } } -typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy; - /// Returns true if we should emit a diagnostic about this case expression not /// being a part of the enum used in the switch controlling expression. -static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, +static bool ShouldDiagnoseSwitchCaseNotInEnum(const ASTContext &Ctx, const EnumDecl *ED, - const Expr *CaseExpr, - EnumValsTy::iterator &EI, - EnumValsTy::iterator &EIEnd, - const llvm::APSInt &Val) { - bool FlagType = ED->hasAttr<FlagEnumAttr>(); - - if (const DeclRefExpr *DRE = - dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) { + const Expr *CaseExpr) { + // Don't warn if the 'case' expression refers to a static const variable of + // the enum type. + CaseExpr = CaseExpr->IgnoreParenImpCasts(); + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseExpr)) { if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { + if (!VD->hasGlobalStorage()) + return true; QualType VarType = VD->getType(); - QualType EnumType = S.Context.getTypeDeclType(ED); - if (VD->hasGlobalStorage() && VarType.isConstQualified() && - S.Context.hasSameUnqualifiedType(EnumType, VarType)) + if (!VarType.isConstQualified()) + return true; + QualType EnumType = Ctx.getTypeDeclType(ED); + if (Ctx.hasSameUnqualifiedType(EnumType, VarType)) return false; } } - - if (FlagType) { - return !S.IsValueInFlagEnum(ED, Val, false); - } else { - while (EI != EIEnd && EI->first < Val) - EI++; - - if (EI != EIEnd && EI->first == Val) - return false; - } - return true; } @@ -1059,6 +1046,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If switch has default case, then ignore it. if (!CaseListIsErroneous && !HasConstantCond && ET) { const EnumDecl *ED = ET->getDecl(); + typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> + EnumValsTy; EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, @@ -1069,48 +1058,57 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, EnumVals.push_back(std::make_pair(Val, EDI)); } std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); - auto EI = EnumVals.begin(), EIEnd = + EnumValsTy::iterator EIend = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); // See which case values aren't in enum. + EnumValsTy::const_iterator EI = EnumVals.begin(); for (CaseValsTy::const_iterator CI = CaseVals.begin(); - CI != CaseVals.end(); CI++) { - Expr *CaseExpr = CI->second->getLHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, - CI->first)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; + CI != CaseVals.end(); CI++) { + while (EI != EIend && EI->first < CI->first) + EI++; + if (EI == EIend || EI->first > CI->first) { + Expr *CaseExpr = CI->second->getLHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; + } } - // See which of case ranges aren't in enum EI = EnumVals.begin(); for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); - RI != CaseRanges.end(); RI++) { - Expr *CaseExpr = RI->second->getLHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, - RI->first)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; + RI != CaseRanges.end() && EI != EIend; RI++) { + while (EI != EIend && EI->first < RI->first) + EI++; + + if (EI == EIend || EI->first != RI->first) { + Expr *CaseExpr = RI->second->getLHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; + } llvm::APSInt Hi = RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); - - CaseExpr = RI->second->getRHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, - Hi)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; + while (EI != EIend && EI->first < Hi) + EI++; + if (EI == EIend || EI->first != Hi) { + Expr *CaseExpr = RI->second->getRHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; + } } // Check which enum vals aren't in switch - auto CI = CaseVals.begin(); - auto RI = CaseRanges.begin(); + CaseValsTy::const_iterator CI = CaseVals.begin(); + CaseRangesTy::const_iterator RI = CaseRanges.begin(); bool hasCasesNotInSwitch = false; SmallVector<DeclarationName,8> UnhandledNames; - for (EI = EnumVals.begin(); EI != EIEnd; EI++){ + for (EI = EnumVals.begin(); EI != EIend; EI++){ // Drop unneeded case values while (CI != CaseVals.end() && CI->first < EI->first) CI++; @@ -1197,37 +1195,30 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context); AdjustAPSInt(RhsVal, DstWidth, DstIsSigned); const EnumDecl *ED = ET->getDecl(); - - if (ED->hasAttr<FlagEnumAttr>()) { - if (!IsValueInFlagEnum(ED, RhsVal, true)) - Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) + typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> + EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, + // allowing easier comparison with rhs constant. + for (auto *EDI : ED->enumerators()) { + llvm::APSInt Val = EDI->getInitVal(); + AdjustAPSInt(Val, DstWidth, DstIsSigned); + EnumVals.push_back(std::make_pair(Val, EDI)); + } + if (EnumVals.empty()) + return; + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = + std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + + // See which values aren't in the enum. + EnumValsTy::const_iterator EI = EnumVals.begin(); + while (EI != EIend && EI->first < RhsVal) + EI++; + if (EI == EIend || EI->first != RhsVal) { + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) << DstType.getUnqualifiedType(); - } else { - typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> - EnumValsTy; - EnumValsTy EnumVals; - - // Gather all enum values, set their type and sort them, - // allowing easier comparison with rhs constant. - for (auto *EDI : ED->enumerators()) { - llvm::APSInt Val = EDI->getInitVal(); - AdjustAPSInt(Val, DstWidth, DstIsSigned); - EnumVals.push_back(std::make_pair(Val, EDI)); - } - if (EnumVals.empty()) - return; - std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); - EnumValsTy::iterator EIend = - std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); - - // See which values aren't in the enum. - EnumValsTy::const_iterator EI = EnumVals.begin(); - while (EI != EIend && EI->first < RhsVal) - EI++; - if (EI == EIend || EI->first != RhsVal) { - Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) - << DstType.getUnqualifiedType(); - } } } } diff --git a/test/Sema/attr-flag-enum.c b/test/Sema/attr-flag-enum.c deleted file mode 100644 index a53c1dc8e7..0000000000 --- a/test/Sema/attr-flag-enum.c +++ /dev/null @@ -1,73 +0,0 @@ -// RUN: %clang_cc1 -verify -fsyntax-only -std=c11 -Wassign-enum %s - -enum __attribute__((flag_enum)) flag { - ea = 0x1, - eb = 0x2, - ec = 0x8, -}; - -enum __attribute__((flag_enum)) flag2 { - ga = 0x1, - gb = 0x4, - - gc = 0x5, // no-warning - gd = 0x7, // expected-warning {{enumeration value 'gd' is out of range}} - ge = ~0x2, // expected-warning {{enumeration value 'ge' is out of range}} - gf = ~0x4, // no-warning - gg = ~0x1, // no-warning - gh = ~0x5, // no-warning - gi = ~0x11, // expected-warning {{enumeration value 'gi' is out of range}} -}; - -enum __attribute__((flag_enum)) flag3 { - fa = 0x1, - fb = ~0x1u, // no-warning -}; - -// What happens here is that ~0x2 is negative, and so the enum must be signed. -// But ~0x1u is unsigned and has the high bit set, so the enum must be 64-bit. -// The result is that ~0x1u does not have high bits set, and so it is considered -// to be an invalid value. See Sema::IsValueInFlagEnum in SemaDecl.cpp for more -// discussion. -enum __attribute__((flag_enum)) flag4 { - ha = 0x1, - hb = 0x2, - - hc = ~0x1u, // expected-warning {{enumeration value 'hc' is out of range}} - hd = ~0x2, // no-warning -}; - -void f(void) { - enum flag e = 0; // no-warning - e = 0x1; // no-warning - e = 0x3; // no-warning - e = 0xa; // no-warning - e = 0x4; // expected-warning {{integer constant not in range of enumerated type}} - e = 0xf; // expected-warning {{integer constant not in range of enumerated type}} - e = ~0; // no-warning - e = ~0x1; // no-warning - e = ~0x2; // no-warning - e = ~0x3; // no-warning - e = ~0x4; // expected-warning {{integer constant not in range of enumerated type}} - - switch (e) { - case 0: break; // no-warning - case 0x1: break; // no-warning - case 0x3: break; // no-warning - case 0xa: break; // no-warning - case 0x4: break; // expected-warning {{case value not in enumerated type}} - case 0xf: break; // expected-warning {{case value not in enumerated type}} - case ~0: break; // expected-warning {{case value not in enumerated type}} - case ~0x1: break; // expected-warning {{case value not in enumerated type}} - case ~0x2: break; // expected-warning {{case value not in enumerated type}} - case ~0x3: break; // expected-warning {{case value not in enumerated type}} - case ~0x4: break; // expected-warning {{case value not in enumerated type}} - default: break; - } - - enum flag2 f = ~0x1; // no-warning - f = ~0x1u; // no-warning - - enum flag4 h = ~0x1; // no-warning - h = ~0x1u; // expected-warning {{integer constant not in range of enumerated type}} -} diff --git a/test/SemaCXX/attr-flag-enum-reject.cpp b/test/SemaCXX/attr-flag-enum-reject.cpp deleted file mode 100644 index f28d60c0c2..0000000000 --- a/test/SemaCXX/attr-flag-enum-reject.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// RUN: %clang_cc1 -verify -fsyntax-only -x c++ -Wassign-enum %s - -enum __attribute__((flag_enum)) flag { // expected-warning {{ignored}} -}; diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index a73be2e081..5dd3f7e4af 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -2185,8 +2185,7 @@ static std::string CalculateDiagnostic(const Record &S) { Namespace = 1U << 11, Field = 1U << 12, CXXMethod = 1U << 13, - ObjCProtocol = 1U << 14, - Enum = 1U << 15 + ObjCProtocol = 1U << 14 }; uint32_t SubMask = 0; @@ -2220,7 +2219,6 @@ static std::string CalculateDiagnostic(const Record &S) { .Case("Namespace", Namespace) .Case("Field", Field) .Case("CXXMethod", CXXMethod) - .Case("Enum", Enum) .Default(0); if (!V) { // Something wasn't in our mapping, so be helpful and let the developer @@ -2239,7 +2237,6 @@ static std::string CalculateDiagnostic(const Record &S) { case Var: return "ExpectedVariable"; case Param: return "ExpectedParameter"; case Class: return "ExpectedClass"; - case Enum: return "ExpectedEnum"; case CXXMethod: // FIXME: Currently, this maps to ExpectedMethod based on existing code, // but should map to something a bit more accurate at some point. @@ -2393,8 +2390,6 @@ static std::string GenerateLangOptRequirements(const Record &R, std::string FnName = "check", Test; for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { std::string Part = (*I)->getValueAsString("Name"); - if ((*I)->getValueAsBit("Negated")) - Test += "!"; Test += "S.LangOpts." + Part; if (I + 1 != E) Test += " || "; |