From: Ted Kremenek Date: Thu, 24 Apr 2008 23:57:27 +0000 (+0000) Subject: Add preliminary support for flagging leaks around when they happen (doesn't work... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=652adc6c5de6476d63791cec3e1166ee039e09b6;p=clang 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 --- 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& Builder); + virtual void EvalDeadSymbols(ExplodedNodeSet& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder& Builder, + ProgramPoint P, ExplodedNode* Pred, + ValueState* St, + const ValueStateManager::DeadSymbolsTy& Dead); + // Return statements. virtual void EvalReturn(ExplodedNodeSet& Dst, @@ -1066,10 +1073,13 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng, if (hasLeak) Leaked.push_back((*I).first); } - + + if (Leaked.empty()) + return; + ExplodedNode* N = Builder.MakeNode(St); - if (!N || Leaked.empty()) + if (!N) return; std::vector*& LeaksAtNode = Leaks[N]; @@ -1081,6 +1091,64 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng, (*LeaksAtNode).push_back(*I); } +// Dead symbols. + +void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst, + GRExprEngine& Eng, + GRStmtNodeBuilder& Builder, + ProgramPoint P, ExplodedNode* 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(P)) + return; + + S = cast(P).getStmt(); + + // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor. + + RefBindings B = GetRefBindings(*St); + llvm::SmallVector 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* N = Builder.MakeNode(Dst, S, Pred, St); + + if (!N) + return; + + std::vector*& LeaksAtNode = Leaks[N]; + assert (!LeaksAtNode); + LeaksAtNode = new std::vector(); + + for (llvm::SmallVector::iterator I=Leaked.begin(), + E = Leaked.end(); I != E; ++I) + (*LeaksAtNode).push_back(*I); +} + // Return statements. void CFRefCount::EvalReturn(ExplodedNodeSet& Dst,