diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-04-24 23:57:27 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-04-24 23:57:27 +0000 |
commit | 652adc6c5de6476d63791cec3e1166ee039e09b6 (patch) | |
tree | 0cc5b0ce6f2c5e728afeab80b61f9b79607f186d /lib/Analysis/CFRefCount.cpp | |
parent | 7fc89572d177ee491fa6209a474e65831b265520 (diff) |
Add preliminary support for flagging leaks around when they happen (doesn't work yet).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50237 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 2e0c1aa760..a1380af497 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -684,6 +684,13 @@ public: virtual void EvalEndPath(GRExprEngine& Engine, GREndPathNodeBuilder<ValueState>& Builder); + virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder<ValueState>& Builder, + ProgramPoint P, ExplodedNode<ValueState>* Pred, + ValueState* St, + const ValueStateManager::DeadSymbolsTy& Dead); + // Return statements. virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst, @@ -1066,10 +1073,13 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng, if (hasLeak) Leaked.push_back((*I).first); } - + + if (Leaked.empty()) + return; + ExplodedNode<ValueState>* N = Builder.MakeNode(St); - if (!N || Leaked.empty()) + if (!N) return; std::vector<SymbolID>*& LeaksAtNode = Leaks[N]; @@ -1081,6 +1091,64 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng, (*LeaksAtNode).push_back(*I); } +// Dead symbols. + +void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst, + GRExprEngine& Eng, + GRStmtNodeBuilder<ValueState>& Builder, + ProgramPoint P, ExplodedNode<ValueState>* Pred, + ValueState* St, + const ValueStateManager::DeadSymbolsTy& Dead) { + + // FIXME: Have GRStmtNodeBuilder handle the case where 'P' is not PostStmt; + // This won't result in missed leaks; we'll just flag these ones at the + // end-of-path. + + Stmt* S = NULL; + + if (!isa<PostStmt>(P)) + return; + + S = cast<PostStmt>(P).getStmt(); + + // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor. + + RefBindings B = GetRefBindings(*St); + llvm::SmallVector<SymbolID, 10> Leaked; + + for (ValueStateManager::DeadSymbolsTy::const_iterator + I=Dead.begin(), E=Dead.end(); I!=E; ++I) { + + RefBindings::TreeTy* T = B.SlimFind(*I); + + if (!T) + continue; + + bool hasLeak = false; + + St = HandleSymbolDeath(Eng.getStateManager(), St, + *I, T->getValue().second, hasLeak); + + if (hasLeak) Leaked.push_back(*I); + } + + if (Leaked.empty()) + return; + + ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St); + + if (!N) + return; + + std::vector<SymbolID>*& LeaksAtNode = Leaks[N]; + assert (!LeaksAtNode); + LeaksAtNode = new std::vector<SymbolID>(); + + for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(), + E = Leaked.end(); I != E; ++I) + (*LeaksAtNode).push_back(*I); +} + // Return statements. void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst, |