]> granicus.if.org Git - clang/commitdiff
Implement -Wswitch-enum correctly.
authorDavid Blaikie <dblaikie@gmail.com>
Mon, 23 Jan 2012 04:46:12 +0000 (04:46 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Mon, 23 Jan 2012 04:46:12 +0000 (04:46 +0000)
Clang previously implemented -Wswitch-enum the same as -Wswitch. This patch
corrects the behavior to match GCC's. The critical/only difference being that
-Wswitch-enum is not silenced by the presence of a default case in the switch.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaStmt.cpp
test/Sema/switch-enum.c [new file with mode: 0644]

index b4f61ce1ca7bd13712d8f36f68a75f163c434bf4..d02910a40eec705acdf186444579be6ea45e0d22 100644 (file)
@@ -4945,6 +4945,20 @@ 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_def_missing_case1 : Warning<
+  "enumeration value %0 not handled in switch">,
+  InGroup<SwitchEnum>, DefaultIgnore;
+def warn_def_missing_case2 : Warning<
+  "enumeration values %0 and %1 not handled in switch">,
+  InGroup<SwitchEnum>, DefaultIgnore;
+def warn_def_missing_case3 : Warning<
+  "enumeration values %0, %1, and %2 not handled in switch">,
+  InGroup<SwitchEnum>, DefaultIgnore;
+def warn_def_missing_cases : Warning<
+  "%0 enumeration values not handled in switch: %1, %2, %3...">,
+  InGroup<SwitchEnum>, DefaultIgnore;
+
 def warn_missing_case1 : Warning<"enumeration value %0 not handled in switch">,
   InGroup<Switch>;
 def warn_missing_case2 : Warning<
@@ -4956,10 +4970,10 @@ def warn_missing_case3 : Warning<
 def warn_missing_cases : Warning<
   "%0 enumeration values not handled in switch: %1, %2, %3...">,
   InGroup<Switch>;
+
 def warn_unreachable_default : Warning<
   "default is unreachable as all enumeration values are accounted for">,
   InGroup<SwitchEnumRedundantDefault>;
-
 def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
   InGroup<Switch>; 
 def err_typecheck_statement_requires_scalar : Error<
index f74159373649baded1df5503bd0d5f34f3379afc..2d843393a2ee22be31a2b6998ed36feb331d46f9 100644 (file)
@@ -924,30 +924,30 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
         }
       }
 
-      if (TheDefaultStmt) {
-        if (UnhandledNames.size() == 0)
-          Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default);
-        else
-          UnhandledNames.clear();
-      }
+      if (TheDefaultStmt && UnhandledNames.empty())
+        Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default);
 
       // 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)
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt 
+          ? diag::warn_def_missing_case1 : diag::warn_missing_case1)
           << UnhandledNames[0];
         break;
       case 2:
-        Diag(CondExpr->getExprLoc(), diag::warn_missing_case2)
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt 
+          ? diag::warn_def_missing_case2 : diag::warn_missing_case2)
           << UnhandledNames[0] << UnhandledNames[1];
         break;
       case 3:
-        Diag(CondExpr->getExprLoc(), diag::warn_missing_case3)
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt
+          ? diag::warn_def_missing_case3 : diag::warn_missing_case3)
           << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
         break;
       default:
-        Diag(CondExpr->getExprLoc(), diag::warn_missing_cases)
+        Diag(CondExpr->getExprLoc(), TheDefaultStmt
+          ? diag::warn_def_missing_cases : diag::warn_missing_cases)
           << (unsigned)UnhandledNames.size()
           << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2];
         break;
diff --git a/test/Sema/switch-enum.c b/test/Sema/switch-enum.c
new file mode 100644 (file)
index 0000000..5cf98f7
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wswitch-enum -Wno-switch-enum-redundant-default %s
+
+int test1() {
+  enum { A, B } a;
+  switch (a) { //expected-warning{{enumeration value 'B' not handled in switch}}
+  case A: return 1;
+  default: return 2;
+  }
+}
+
+int test2() {
+  enum { A, B } a;
+  switch (a) {
+  case A: return 1;
+  case B: return 2;
+  default: return 3;
+  }
+}