From 9366750a5a97c8aeae1df4898ea849b087865195 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sun, 22 Jan 2012 02:31:55 +0000 Subject: [PATCH] Fix -Wswitch to warn about out of bounds enum cases even when there's a default For consistency with GCC & reasonable sanity. The FIXME suggests that the original author was perhaps using the default check for some other purpose, not realizing the more obvious limitation/false-negatives it creates, but this doesn't seem to produce any regressions & fixes the included test. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148649 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaStmt.cpp | 60 ++++++++++++++++++++----------------------- test/Sema/switch.c | 8 ++++++ 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0be3e43b5a..b9b5b212c3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -862,39 +862,35 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); // See which case values aren't in enum. - // TODO: we might want to check whether case values are out of the - // enum even if we don't want to check whether all cases are handled. - if (!TheDefaultStmt) { - EnumValsTy::const_iterator EI = EnumVals.begin(); - for (CaseValsTy::const_iterator CI = CaseVals.begin(); - CI != CaseVals.end(); CI++) { - while (EI != EIend && EI->first < CI->first) - EI++; - if (EI == EIend || EI->first > CI->first) - Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) - << ED->getDeclName(); + EnumValsTy::const_iterator EI = EnumVals.begin(); + for (CaseValsTy::const_iterator CI = CaseVals.begin(); + CI != CaseVals.end(); CI++) { + while (EI != EIend && EI->first < CI->first) + EI++; + if (EI == EIend || EI->first > CI->first) + Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) + << ED->getDeclName(); + } + // See which of case ranges aren't in enum + EI = EnumVals.begin(); + for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); + RI != CaseRanges.end() && EI != EIend; RI++) { + while (EI != EIend && EI->first < RI->first) + EI++; + + if (EI == EIend || EI->first != RI->first) { + Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) + << ED->getDeclName(); } - // See which of case ranges aren't in enum - EI = EnumVals.begin(); - for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); - RI != CaseRanges.end() && EI != EIend; RI++) { - while (EI != EIend && EI->first < RI->first) - EI++; - - if (EI == EIend || EI->first != RI->first) { - Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) - << ED->getDeclName(); - } - llvm::APSInt Hi = - RI->second->getRHS()->EvaluateKnownConstInt(Context); - AdjustAPSInt(Hi, CondWidth, CondIsSigned); - while (EI != EIend && EI->first < Hi) - EI++; - if (EI == EIend || EI->first != Hi) - Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum) - << ED->getDeclName(); - } + llvm::APSInt Hi = + RI->second->getRHS()->EvaluateKnownConstInt(Context); + AdjustAPSInt(Hi, CondWidth, CondIsSigned); + while (EI != EIend && EI->first < Hi) + EI++; + if (EI == EIend || EI->first != Hi) + Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum) + << ED->getDeclName(); } // Check which enum vals aren't in switch @@ -904,7 +900,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, SmallVector UnhandledNames; - for (EnumValsTy::const_iterator EI = EnumVals.begin(); EI != EIend; EI++){ + for (EI = EnumVals.begin(); EI != EIend; EI++){ // Drop unneeded case values llvm::APSInt CIVal; while (CI != CaseVals.end() && CI->first < EI->first) diff --git a/test/Sema/switch.c b/test/Sema/switch.c index 63ffed18e3..f36ecb255f 100644 --- a/test/Sema/switch.c +++ b/test/Sema/switch.c @@ -297,3 +297,11 @@ int test18() { default: return 2; // expected-warning {{default is unreachable as all enumeration values are accounted for}} } } + +int test19() { + enum { A, B } a; + switch (a) { + case 7: return 1; // expected-warning {{case value not in enumerated type}} + default: return 3; + } +} -- 2.40.0