From: David Blaikie Date: Mon, 23 Jan 2012 04:46:12 +0000 (+0000) Subject: Implement -Wswitch-enum correctly. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=585d7795c2dddaa510b3bb1b3b18633bfcfdf643;p=clang Implement -Wswitch-enum correctly. 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 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b4f61ce1ca..d02910a40e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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, DefaultIgnore; +def warn_def_missing_case2 : Warning< + "enumeration values %0 and %1 not handled in switch">, + InGroup, DefaultIgnore; +def warn_def_missing_case3 : Warning< + "enumeration values %0, %1, and %2 not handled in switch">, + InGroup, DefaultIgnore; +def warn_def_missing_cases : Warning< + "%0 enumeration values not handled in switch: %1, %2, %3...">, + InGroup, DefaultIgnore; + def warn_missing_case1 : Warning<"enumeration value %0 not handled in switch">, InGroup; 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; + def warn_unreachable_default : Warning< "default is unreachable as all enumeration values are accounted for">, InGroup; - def warn_not_in_enum : Warning<"case value not in enumerated type %0">, InGroup; def err_typecheck_statement_requires_scalar : Error< diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index f741593736..2d843393a2 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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 index 0000000000..5cf98f78ac --- /dev/null +++ b/test/Sema/switch-enum.c @@ -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; + } +}