From: Edward O'Callaghan Date: Sat, 17 Oct 2009 19:32:54 +0000 (+0000) Subject: Fix for PR5190, Credit to Zhanyong Wan. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=12356b119032edd64e9c32f9f01920d12c2acc57;p=clang Fix for PR5190, Credit to Zhanyong Wan. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84346 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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; + } +}