[-Wunreachable-code] Refine treating all branches of 'switch' as reachable, which includes those with all cases covered but with no 'default:'.

llvm-svn: 203094
This commit is contained in:
Ted Kremenek 2014-03-06 08:09:00 +00:00
parent cf96c257f4
commit 6999d02587
2 changed files with 15 additions and 18 deletions

View File

@ -457,6 +457,10 @@ static bool isConfigurationValue(const Stmt *S) {
/// Returns true if we should always explore all successors of a block.
static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
if (const Stmt *Term = B->getTerminator())
if (isa<SwitchStmt>(Term))
return true;
return isConfigurationValue(B->getTerminatorCondition());
}
@ -500,24 +504,6 @@ unsigned ScanReachableFromBlock(const CFGBlock *Start,
B = UB;
break;
}
// For switch statements, treat all cases as being reachable.
// There are many cases where a switch can contain values that
// are not in an enumeration but they are still reachable because
// other values are possible.
//
// Note that this is quite conservative. If one saw:
//
// switch (1) {
// case 2: ...
//
// we should be able to say that 'case 2' is unreachable. To do
// this we can either put more heuristics here, or possibly retain
// that information in the CFG itself.
//
const Stmt *Label = UB->getLabel();
if (Label && isa<SwitchCase>(Label))
B = UB;
}
while (false);

View File

@ -226,6 +226,17 @@ MyEnum nontrivial_dead_return_enum_2(int x) {
return calledFun(); // expected-warning {{will never be executed}}
}
enum X { A, B, C };
int covered_switch(enum X x) {
switch (x) {
case A: return 1;
case B: return 2;
case C: return 3;
}
return 4; // no-warning
}
// Test unreachable code depending on configuration values
#define CONFIG_CONSTANT 1
int test_config_constant(int x) {