From: Chris Lattner Date: Thu, 16 Sep 2010 17:09:42 +0000 (+0000) Subject: improve the "enumeration value 'g' not handled in switch" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ce78461303f45fecb3460d1c49c9b71f27ad19c3;p=clang improve the "enumeration value 'g' not handled in switch" warning to handle multiple enumerators with one warning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114093 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1ccc89f068..e796a4d564 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3142,8 +3142,18 @@ 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_missing_cases : Warning<"enumeration value %0 not handled in switch">, +def warn_missing_case1 : Warning<"enumeration value %0 not handled in switch">, InGroup >; +def warn_missing_case2 : Warning< + "enumeration values %0 and %1 not handled in switch">, + InGroup >; +def warn_missing_case3 : Warning< + "enumeration values %0, %1, and %2 not handled in switch">, + InGroup >; +def warn_missing_cases : Warning< + "%0 enumeration values not handled in switch: %1, %2, %3...">, + 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 c9a6da13fb..8ec12a460d 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -703,7 +703,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // we still do the analysis to preserve this information in the AST // (which can be used by flow-based analyes). // - const EnumType* ET = CondTypeBeforePromotion->getAs(); + const EnumType *ET = CondTypeBeforePromotion->getAs(); // If switch has default case, then ignore it. if (!CaseListIsErroneous && !HasConstantCond && ET) { @@ -760,13 +760,16 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, << ED->getDeclName(); } } + // Check which enum vals aren't in switch CaseValsTy::const_iterator CI = CaseVals.begin(); CaseRangesTy::const_iterator RI = CaseRanges.begin(); bool hasCasesNotInSwitch = false; + llvm::SmallVector UnhandledNames; + for (EnumValsTy::const_iterator EI = EnumVals.begin(); EI != EIend; EI++){ - //Drop unneeded case values + // Drop unneeded case values llvm::APSInt CIVal; while (CI != CaseVals.end() && CI->first < EI->first) CI++; @@ -784,10 +787,31 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (RI == CaseRanges.end() || EI->first < RI->first) { hasCasesNotInSwitch = true; if (!TheDefaultStmt) - Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) - << EI->second->getDeclName(); + UnhandledNames.push_back(EI->second->getDeclName()); } } + + // 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) + << UnhandledNames[0]; + break; + case 2: + Diag(CondExpr->getExprLoc(), diag::warn_missing_case2) + << UnhandledNames[0] << UnhandledNames[1]; + break; + case 3: + Diag(CondExpr->getExprLoc(), diag::warn_missing_case3) + << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; + break; + default: + Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) + << (unsigned)UnhandledNames.size() + << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; + break; + } if (!hasCasesNotInSwitch) SS->setAllEnumCasesCovered(); diff --git a/test/Sema/statements.c b/test/Sema/statements.c index e3c41f3e1a..61eafe6ff0 100644 --- a/test/Sema/statements.c +++ b/test/Sema/statements.c @@ -50,4 +50,43 @@ int test12(enum Numbers num) { case kThree: break; } -} \ No newline at end of file +} + + +enum x { a, b, c, d, e, f, g }; + +void foo(enum x X) { + switch (X) { // expected-warning {{enumeration value 'g' not handled in switch}} + case a: + case b: + case c: + case d: + case e: + case f: + break; + } + + switch (X) { // expected-warning {{enumeration values 'f' and 'g' not handled in switch}} + case a: + case b: + case c: + case d: + case e: + break; + } + + switch (X) { // expected-warning {{enumeration values 'e', 'f', and 'g' not handled in switch}} + case a: + case b: + case c: + case d: + break; + } + + switch (X) { // expected-warning {{5 enumeration values not handled in switch: 'c', 'd', 'e'...}} + case a: + case b: + break; + } +} +