r196546 - Allow the warning 'case value not in enumerated type' to be silenced with

Dmitri Gribenko gribozavr at gmail.com
Thu Dec 5 14:52:08 PST 2013


Author: gribozavr
Date: Thu Dec  5 16:52:07 2013
New Revision: 196546

URL: http://llvm.org/viewvc/llvm-project?rev=196546&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/Sema/switch.c

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=196546&r1=196545&r2=196546&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Dec  5 16:52:07 2013
@@ -659,6 +659,29 @@ static void AdjustAPSInt(llvm::APSInt &V
   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(SourceLocati
            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(SourceLocati
           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(SourceLocati
         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

Modified: cfe/trunk/test/Sema/switch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/switch.c?rev=196546&r1=196545&r2=196546&view=diff
==============================================================================
--- cfe/trunk/test/Sema/switch.c (original)
+++ cfe/trunk/test/Sema/switch.c Thu Dec  5 16:52:07 2013
@@ -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'}}
+  }
+}
+





More information about the cfe-commits mailing list