]> granicus.if.org Git - clang/commitdiff
improve the "enumeration value 'g' not handled in switch"
authorChris Lattner <sabre@nondot.org>
Thu, 16 Sep 2010 17:09:42 +0000 (17:09 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 16 Sep 2010 17:09:42 +0000 (17:09 +0000)
warning to handle multiple enumerators with one warning.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114093 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaStmt.cpp
test/Sema/statements.c

index 1ccc89f06888023eaa54e53e42c5e958bf7c8c35..e796a4d564f9f99881c47c13a59247e866c4b724 100644 (file)
@@ -3142,8 +3142,18 @@ def err_duplicate_case : Error<"duplicate case value '%0'">;
 def warn_case_empty_range : Warning<"empty case range specified">;
 def warn_missing_case_for_condition :
   Warning<"no case matching constant switch condition '%0'">;
-def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">,
+def warn_missing_case1 : Warning<"enumeration value %0 not handled in switch">,
   InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_case2 : Warning<
+  "enumeration values %0 and %1 not handled in switch">,
+  InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_case3 : Warning<
+  "enumeration values %0, %1, and %2 not handled in switch">,
+  InGroup<DiagGroup<"switch-enum"> >;
+def warn_missing_cases : Warning<
+  "%0 enumeration values not handled in switch: %1, %2, %3...">,
+  InGroup<DiagGroup<"switch-enum"> >;
+
 def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
   InGroup<DiagGroup<"switch-enum"> >; 
 def err_typecheck_statement_requires_scalar : Error<
index c9a6da13fbe1551ff2051b4b162d3dc251503ae5..8ec12a460db6298983c2e948d9ea15a7f761cffa 100644 (file)
@@ -703,7 +703,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
     // we still do the analysis to preserve this information in the AST
     // (which can be used by flow-based analyes).
     //
-    const EnumTypeET = CondTypeBeforePromotion->getAs<EnumType>();
+    const EnumType *ET = CondTypeBeforePromotion->getAs<EnumType>();
 
     // If switch has default case, then ignore it.
     if (!CaseListIsErroneous  && !HasConstantCond && ET) {
@@ -760,13 +760,16 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
               << ED->getDeclName();
         }
       }
+      
       // Check which enum vals aren't in switch
       CaseValsTy::const_iterator CI = CaseVals.begin();
       CaseRangesTy::const_iterator RI = CaseRanges.begin();
       bool hasCasesNotInSwitch = false;
 
+      llvm::SmallVector<DeclarationName,8> UnhandledNames;
+      
       for (EnumValsTy::const_iterator EI = EnumVals.begin(); EI != EIend; EI++){
-        //Drop unneeded case values
+        // Drop unneeded case values
         llvm::APSInt CIVal;
         while (CI != CaseVals.end() && CI->first < EI->first)
           CI++;
@@ -784,10 +787,31 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
         if (RI == CaseRanges.end() || EI->first < RI->first) {
           hasCasesNotInSwitch = true;
           if (!TheDefaultStmt)
-            Diag(CondExpr->getExprLoc(), diag::warn_missing_cases)
-              << EI->second->getDeclName();
+            UnhandledNames.push_back(EI->second->getDeclName());
         }
       }
+      
+      // Produce a nice diagnostic if multiple values aren't handled.
+      switch (UnhandledNames.size()) {
+      case 0: break;
+      case 1:
+        Diag(CondExpr->getExprLoc(), diag::warn_missing_case1)
+          << UnhandledNames[0];
+        break;
+      case 2:
+        Diag(CondExpr->getExprLoc(), diag::warn_missing_case2)
+          << UnhandledNames[0] << UnhandledNames[1];
+        break;
+      case 3:
+        Diag(CondExpr->getExprLoc(), diag::warn_missing_case3)
+          << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
+        break;
+      default:
+        Diag(CondExpr->getExprLoc(), diag::warn_missing_cases)
+          << (unsigned)UnhandledNames.size()
+          << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
+        break;
+      }
 
       if (!hasCasesNotInSwitch)
         SS->setAllEnumCasesCovered();
index e3c41f3e1aaf331e6d60c414ec1c5984acb3f67a..61eafe6ff038acb6b13e46cdb004a41805cbe48a 100644 (file)
@@ -50,4 +50,43 @@ int test12(enum Numbers num) {
   case kThree:
     break;
   }
-}
\ No newline at end of file
+}
+
+
+enum x { a, b, c, d, e, f, g };
+
+void foo(enum x X) {
+  switch (X) { // expected-warning {{enumeration value 'g' not handled in switch}}
+  case a:
+  case b:
+  case c:
+  case d:
+  case e:
+  case f:
+    break;
+  }
+
+  switch (X) { // expected-warning {{enumeration values 'f' and 'g' not handled in switch}}
+  case a:
+  case b:
+  case c:
+  case d:
+  case e:
+    break;
+  }
+
+  switch (X) {  // expected-warning {{enumeration values 'e', 'f', and 'g' not handled in switch}}
+    case a:
+    case b:
+    case c:
+    case d:
+      break;
+  }
+
+  switch (X) { // expected-warning {{5 enumeration values not handled in switch: 'c', 'd', 'e'...}}
+  case a:
+  case b:
+    break;
+  }
+}
+