diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-02-11 23:24:26 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-02-11 23:24:26 +0000 |
commit | 848ec83483ca4ba52ed72c7e29ebc330f8c87252 (patch) | |
tree | 89ca61710a05824b6868a80b68884e91faffd644 /lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | |
parent | 21af8878b96ab1f9b077407ca3c512e5dc5d0ad6 (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.cpp | 66 |
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); } |