aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward O'Callaghan <eocallaghan@auroraux.org>2009-10-17 19:32:54 +0000
committerEdward O'Callaghan <eocallaghan@auroraux.org>2009-10-17 19:32:54 +0000
commit12356b119032edd64e9c32f9f01920d12c2acc57 (patch)
tree0c502518b2d34f83e371344b065bfecbd0f662ea
parente38050d47dc673b7edf1e4b4d2e3c822293a8cba (diff)
Fix for PR5190, Credit to Zhanyong Wan.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84346 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/SemaStmt.cpp19
-rw-r--r--test/SemaCXX/switch.cpp15
3 files changed, 31 insertions, 5 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index d1b0445989..6cea79a1b7 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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'">;
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index efa7e22b2e..6081ef5d99 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -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
index 0000000000..b22adb7495
--- /dev/null
+++ b/test/SemaCXX/switch.cpp
@@ -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;
+ }
+}