forked from OSchip/llvm-project
Allow the warning 'case value not in enumerated type' to be silenced with
the following pattern. If 'case' expression refers to a static const variable of the correct enum type, then we count this as a sufficient declaration of intent by the user, so we silence the warning. llvm-svn: 196546
This commit is contained in:
parent
ae9451218f
commit
58683755ed
|
@ -659,6 +659,29 @@ static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) {
|
|||
Val.setIsSigned(IsSigned);
|
||||
}
|
||||
|
||||
/// 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 ASTContext &Ctx,
|
||||
const EnumDecl *ED,
|
||||
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();
|
||||
if (!VarType.isConstQualified())
|
||||
return true;
|
||||
QualType EnumType = Ctx.getTypeDeclType(ED);
|
||||
if (Ctx.hasSameUnqualifiedType(EnumType, VarType))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
StmtResult
|
||||
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
|
||||
Stmt *BodyStmt) {
|
||||
|
@ -1008,9 +1031,12 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
|
|||
CI != CaseVals.end(); CI++) {
|
||||
while (EI != EIend && EI->first < CI->first)
|
||||
EI++;
|
||||
if (EI == EIend || EI->first > CI->first)
|
||||
Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
|
||||
<< CondTypeBeforePromotion;
|
||||
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();
|
||||
|
@ -1020,8 +1046,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
|
|||
EI++;
|
||||
|
||||
if (EI == EIend || EI->first != RI->first) {
|
||||
Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum)
|
||||
<< CondTypeBeforePromotion;
|
||||
Expr *CaseExpr = RI->second->getLHS();
|
||||
if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr))
|
||||
Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
|
||||
<< CondTypeBeforePromotion;
|
||||
}
|
||||
|
||||
llvm::APSInt Hi =
|
||||
|
@ -1029,9 +1057,12 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
|
|||
AdjustAPSInt(Hi, CondWidth, CondIsSigned);
|
||||
while (EI != EIend && EI->first < Hi)
|
||||
EI++;
|
||||
if (EI == EIend || EI->first != Hi)
|
||||
Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum)
|
||||
<< CondTypeBeforePromotion;
|
||||
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
|
||||
|
|
|
@ -349,3 +349,29 @@ void test19(int i) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the warning 'case value not in enumerated type' to be silenced with
|
||||
// the following pattern.
|
||||
//
|
||||
// If 'case' expression refers to a static const variable of the correct enum
|
||||
// type, then we count this as a sufficient declaration of intent by the user,
|
||||
// so we silence the warning.
|
||||
enum ExtendedEnum1 {
|
||||
EE1_a,
|
||||
EE1_b
|
||||
};
|
||||
|
||||
enum ExtendedEnum1_unrelated { EE1_misc };
|
||||
|
||||
static const enum ExtendedEnum1 EE1_c = 100;
|
||||
static const enum ExtendedEnum1_unrelated EE1_d = 101;
|
||||
|
||||
void switch_on_ExtendedEnum1(enum ExtendedEnum1 e) {
|
||||
switch(e) {
|
||||
case EE1_a: break;
|
||||
case EE1_b: break;
|
||||
case EE1_c: break; // no-warning
|
||||
case EE1_d: break; // expected-warning {{case value not in enumerated type 'enum ExtendedEnum1'}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue