summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/ReachableCode.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2014-02-27 21:56:47 +0000
committerTed Kremenek <kremenek@apple.com>2014-02-27 21:56:47 +0000
commit08da97819a87df1ba5b5596bfaafbdcb7cf041e9 (patch)
treea5a0afb9caa594b1ada843032561a00ae36238fc /clang/lib/Analysis/ReachableCode.cpp
parent9238c5c878c066fe46bd63ddbf4daf1a5e4f99bc (diff)
downloadbcm5719-llvm-08da97819a87df1ba5b5596bfaafbdcb7cf041e9.tar.gz
bcm5719-llvm-08da97819a87df1ba5b5596bfaafbdcb7cf041e9.zip
[-Wunreachable-code] always treat 'case:' and 'default:' cases as reachable.
This is a heuristic. Many switch statements, although they look covered over an enum, may actually handle at runtime more values than in the enum. This is overly conservative, as there are some cases that clearly can be ruled as being clearly unreachable, e.g. 'switch (42) { case 1: ... }'. We can refine this later. llvm-svn: 202436
Diffstat (limited to 'clang/lib/Analysis/ReachableCode.cpp')
-rw-r--r--clang/lib/Analysis/ReachableCode.cpp35
1 files changed, 27 insertions, 8 deletions
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index 797e02ed6f5..4a192802e71 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/lib/Analysis/ReachableCode.cpp
@@ -337,12 +337,6 @@ void DeadCodeScan::reportDeadCode(const CFGBlock *B,
if (isTrivialReturnPrecededByNoReturn(B, S))
return;
- // Was this an unreachable 'default' case? Such cases are covered
- // by -Wcovered-switch-default, if the user so desires.
- const Stmt *Label = B->getLabel();
- if (Label && isa<DefaultStmt>(Label))
- return;
-
SourceRange R1, R2;
SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
CB.HandleUnreachable(Loc, R1, R2);
@@ -374,8 +368,32 @@ unsigned ScanReachableFromBlock(const CFGBlock *Start,
// Look at the successors and mark then reachable.
for (CFGBlock::const_succ_iterator I = item->succ_begin(),
- E = item->succ_end(); I != E; ++I)
- if (const CFGBlock *B = *I) {
+ E = item->succ_end(); I != E; ++I) {
+ const CFGBlock *B = *I;
+ if (!B) {
+ //
+ // 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.
+ //
+ if (const CFGBlock *UB = I->getPossiblyUnreachableBlock()) {
+ const Stmt *Label = UB->getLabel();
+ if (Label && isa<SwitchCase>(Label)) {
+ B = UB;
+ }
+ }
+ }
+ if (B) {
unsigned blockID = B->getBlockID();
if (!Reachable[blockID]) {
Reachable.set(blockID);
@@ -383,6 +401,7 @@ unsigned ScanReachableFromBlock(const CFGBlock *Start,
++count;
}
}
+ }
}
return count;
}
OpenPOWER on IntegriCloud