aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-02-11 23:24:26 +0000
committerTed Kremenek <kremenek@apple.com>2011-02-11 23:24:26 +0000
commit848ec83483ca4ba52ed72c7e29ebc330f8c87252 (patch)
tree89ca61710a05824b6868a80b68884e91faffd644 /lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
parent21af8878b96ab1f9b077407ca3c512e5dc5d0ad6 (diff)
Don't report dead stores on unreachable code paths. Fixes <rdar://problem/8405222>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125415 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp66
1 files changed, 61 insertions, 5 deletions
diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index e2b3d81931..442e1b3af7 100644
--- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -28,26 +28,80 @@ using namespace ento;
namespace {
+// FIXME: Eventually migrate into its own file, and have it managed by
+// AnalysisManager.
+class ReachableCode {
+ const CFG &cfg;
+ llvm::BitVector reachable;
+public:
+ ReachableCode(const CFG &cfg)
+ : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
+
+ void computeReachableBlocks();
+
+ bool isReachable(const CFGBlock *block) const {
+ return reachable[block->getBlockID()];
+ }
+};
+}
+
+void ReachableCode::computeReachableBlocks() {
+ if (!cfg.getNumBlockIDs())
+ return;
+
+ llvm::SmallVector<const CFGBlock*, 10> worklist;
+ worklist.push_back(&cfg.getEntry());
+
+ while (!worklist.empty()) {
+ const CFGBlock *block = worklist.back();
+ worklist.pop_back();
+ llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
+ if (isReachable)
+ continue;
+ isReachable = true;
+ for (CFGBlock::const_succ_iterator i = block->succ_begin(),
+ e = block->succ_end(); i != e; ++i)
+ if (const CFGBlock *succ = *i)
+ worklist.push_back(succ);
+ }
+}
+
+namespace {
class DeadStoreObs : public LiveVariables::ObserverTy {
+ const CFG &cfg;
ASTContext &Ctx;
BugReporter& BR;
ParentMap& Parents;
llvm::SmallPtrSet<VarDecl*, 20> Escaped;
+ llvm::OwningPtr<ReachableCode> reachableCode;
+ const CFGBlock *currentBlock;
enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
public:
- DeadStoreObs(ASTContext &ctx, BugReporter& br, ParentMap& parents,
+ DeadStoreObs(const CFG &cfg, ASTContext &ctx,
+ BugReporter& br, ParentMap& parents,
llvm::SmallPtrSet<VarDecl*, 20> &escaped)
- : Ctx(ctx), BR(br), Parents(parents), Escaped(escaped) {}
+ : cfg(cfg), Ctx(ctx), BR(br), Parents(parents),
+ Escaped(escaped), currentBlock(0) {}
virtual ~DeadStoreObs() {}
void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {
if (Escaped.count(V))
return;
+
+ // Compute reachable blocks within the CFG for trivial cases
+ // where a bogus dead store can be reported because itself is unreachable.
+ if (!reachableCode.get()) {
+ reachableCode.reset(new ReachableCode(cfg));
+ reachableCode->computeReachableBlocks();
+ }
+
+ if (!reachableCode->isReachable(currentBlock))
+ return;
- std::string name = V->getNameAsString();
+ const std::string &name = V->getNameAsString();
const char* BugType = 0;
std::string msg;
@@ -127,10 +181,12 @@ public:
return false;
}
- virtual void ObserveStmt(Stmt* S,
+ virtual void ObserveStmt(Stmt* S, const CFGBlock *block,
const LiveVariables::AnalysisDataTy& AD,
const LiveVariables::ValTy& Live) {
+ currentBlock = block;
+
// Skip statements in macros.
if (S->getLocStart().isMacroID())
return;
@@ -284,6 +340,6 @@ void ento::CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &pmap,
BugReporter& BR) {
FindEscaped FS(&cfg);
FS.getCFG().VisitBlockStmts(FS);
- DeadStoreObs A(BR.getContext(), BR, pmap, FS.Escaped);
+ DeadStoreObs A(cfg, BR.getContext(), BR, pmap, FS.Escaped);
L.runOnAllBlocks(cfg, &A);
}