Add preliminary support for flagging leaks around when they happen (doesn't work yet).

llvm-svn: 50237
This commit is contained in:
Ted Kremenek 2008-04-24 23:57:27 +00:00
parent ddb4887ed6
commit b0daf2f6f5
1 changed files with 70 additions and 2 deletions

View File

@ -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,