]> granicus.if.org Git - clang/commitdiff
Fix for PR5190, Credit to Zhanyong Wan.
authorEdward O'Callaghan <eocallaghan@auroraux.org>
Sat, 17 Oct 2009 19:32:54 +0000 (19:32 +0000)
committerEdward O'Callaghan <eocallaghan@auroraux.org>
Sat, 17 Oct 2009 19:32:54 +0000 (19:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84346 91177308-0d34-0410-b5e6-96231b3b80d8

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

index d1b0445989fbc531e5133f752e45ee96bb61d688..6cea79a1b7a1eeaec47cd1e080e4f6286f27fda5 100644 (file)
@@ -2166,6 +2166,8 @@ def err_break_not_in_loop_or_switch : Error<
 def err_default_not_in_switch : Error<
   "'default' statement not in switch statement">;
 def err_case_not_in_switch : Error<"'case' statement not in switch statement">;
+def warn_bool_switch_condition : Warning<
+  "switch condition is a bool">;
 def warn_case_value_overflow : Warning<
   "overflow converting case value to switch condition type (%0 to %1)">;
 def err_duplicate_case : Error<"duplicate case value '%0'">;
index efa7e22b2ef4297229b8e4f4a8fee68e7a2b0e03..6081ef5d9973c004f7a064369fbc497d958085ee 100644 (file)
@@ -407,11 +407,20 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
   QualType CondTypeBeforePromotion =
       GetTypeBeforeIntegralPromotion(CondExpr);
 
-  if (!CondExpr->isTypeDependent() &&
-      !CondType->isIntegerType()) { // C99 6.8.4.2p1
-    Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
-      << CondType << CondExpr->getSourceRange();
-    return StmtError();
+  if (!CondExpr->isTypeDependent()) {
+    if (!CondType->isIntegerType()) { // C99 6.8.4.2p1
+      Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
+          << CondType << CondExpr->getSourceRange();
+      return StmtError();
+    }
+
+    if (CondTypeBeforePromotion->isBooleanType()) {
+      // switch(bool_expr) {...} is often a programmer error, e.g.
+      //   switch(n && mask) { ... }  // Doh - should be "n & mask".
+      // One can always use an if statement instead of switch(bool_expr).
+      Diag(SwitchLoc, diag::warn_bool_switch_condition)
+          << CondExpr->getSourceRange();
+    }
   }
 
   // Get the bitwidth of the switched-on value before promotions.  We must
diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp
new file mode 100644 (file)
index 0000000..b22adb7
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void test() {
+  bool x = true;
+  switch (x) { // expected-warning {{bool}}
+    case 0:
+      break;
+  }
+
+  int n = 3;
+  switch (n && 1) { // expected-warning {{bool}}
+    case 1:
+      break;
+  }
+}