ASTContext &Ctx = B.getContext();
// Find CFGBlocks that were not covered by any node
- for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
+ for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) {
const CFGBlock *CB = *I;
// Check if the block is unreachable
if (reachable.count(CB->getBlockID()))
continue;
// Find the entry points for this block
- FindUnreachableEntryPoints(CB);
+ if (!visited.count(CB->getBlockID()))
+ FindUnreachableEntryPoints(CB);
// This block may have been pruned; check if we still want to report it
if (reachable.count(CB->getBlockID()))
// Recursively finds the entry point(s) for this dead CFGBlock.
void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
- bool allPredecessorsReachable = true;
-
visited.insert(CB->getBlockID());
- for (CFGBlock::const_pred_iterator I = CB->pred_begin(); I != CB->pred_end();
- ++I) {
- // Recurse over all unreachable blocks
+ for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end();
+ I != E; ++I) {
if (!reachable.count((*I)->getBlockID())) {
- // At least one predeccessor was unreachable
- allPredecessorsReachable = false;
-
- // Only visit the block once
+ // If we find an unreachable predecessor, mark this block as reachable so
+ // we don't report this block
+ reachable.insert(CB->getBlockID());
if (!visited.count((*I)->getBlockID()))
+ // If we haven't previously visited the unreachable predecessor, recurse
FindUnreachableEntryPoints(*I);
}
}
-
- // If at least one predecessor is unreachable, mark this block as reachable
- // so we don't report this block.
- if (!allPredecessorsReachable) {
- reachable.insert(CB->getBlockID());
- }
}
// Find the Stmt* in a CFGBlock for reporting a warning
-// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-check-objc-mem -analyzer-check-dead-stores -verify -analyzer-opt-analyze-nested-blocks %s
+// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-check-objc-mem -analyzer-check-dead-stores -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s
extern void foo(int a);
switch (a) {
if (a) // expected-warning{{never executed}}
foo(a + 5); // no-warning
- else // no-warning
- foo(a); // no-warning
+ else // no-warning
+ foo(a); // no-warning
case 1:
case 2:
break;
break;
}
}
+
+// Tests from flow-sensitive version
+void test10() {
+ goto c;
+ d:
+ goto e; // expected-warning {{never executed}}
+ c: ;
+ int i;
+ return;
+ goto b; // expected-warning {{never executed}}
+ goto a; // expected-warning {{never executed}}
+ b:
+ i = 1; // expected-warning {{Value stored to 'i' is never read}}
+ a:
+ i = 2; // expected-warning {{Value stored to 'i' is never read}}
+ goto f;
+ e:
+ goto d;
+ f: ;
+}