Determining the allocation site for a leak when constructing a CFRefLeakReport. This avoids repeated calls to GetAllocationSite when Profiling a CFRefLeakReport object.

llvm-svn: 64036
This commit is contained in:
Ted Kremenek 2009-02-07 22:19:59 +00:00
parent 21eb52a74f
commit 008242f6ea
1 changed files with 34 additions and 17 deletions

View File

@ -2126,18 +2126,19 @@ namespace {
const ExplodedNode<GRState>* PrevN, const ExplodedNode<GRState>* PrevN,
const ExplodedGraph<GRState>& G, const ExplodedGraph<GRState>& G,
BugReporter& BR); BugReporter& BR);
}; };
class VISIBILITY_HIDDEN CFRefLeakReport : public CFRefReport { class VISIBILITY_HIDDEN CFRefLeakReport : public CFRefReport {
SourceLocation AllocSite;
const MemRegion* AllocBinding;
public: public:
CFRefLeakReport(CFRefBug& D, ExplodedNode<GRState> *n, SymbolRef sym) CFRefLeakReport(CFRefBug& D, ExplodedNode<GRState> *n, SymbolRef sym,
: CFRefReport(D, n, sym) {} GRStateManager& StateMgr);
PathDiagnosticPiece* getEndPath(BugReporter& BR, PathDiagnosticPiece* getEndPath(BugReporter& BR,
const ExplodedNode<GRState>* N); const ExplodedNode<GRState>* N);
SourceLocation getLocation() const; SourceLocation getLocation() const { return AllocSite; }
}; };
} // end anonymous namespace } // end anonymous namespace
@ -2387,7 +2388,7 @@ class VISIBILITY_HIDDEN FindUniqueBinding :
} }
static std::pair<const ExplodedNode<GRState>*,const MemRegion*> static std::pair<const ExplodedNode<GRState>*,const MemRegion*>
GetAllocationSite(GRStateManager* StateMgr, const ExplodedNode<GRState>* N, GetAllocationSite(GRStateManager& StateMgr, const ExplodedNode<GRState>* N,
SymbolRef Sym) { SymbolRef Sym) {
// Find both first node that referred to the tracked symbol and the // Find both first node that referred to the tracked symbol and the
@ -2402,11 +2403,9 @@ GetAllocationSite(GRStateManager* StateMgr, const ExplodedNode<GRState>* N,
if (!B.lookup(Sym)) if (!B.lookup(Sym))
break; break;
if (StateMgr) { FindUniqueBinding FB(Sym);
FindUniqueBinding FB(Sym); StateMgr.iterBindings(St, FB);
StateMgr->iterBindings(St, FB); if (FB) FirstBinding = FB.getRegion();
if (FB) FirstBinding = FB.getRegion();
}
Last = N; Last = N;
N = N->pred_empty() ? NULL : *(N->pred_begin()); N = N->pred_empty() ? NULL : *(N->pred_begin());
@ -2440,7 +2439,7 @@ CFRefLeakReport::getEndPath(BugReporter& br, const ExplodedNode<GRState>* EndN){
const MemRegion* FirstBinding = 0; const MemRegion* FirstBinding = 0;
llvm::tie(AllocNode, FirstBinding) = llvm::tie(AllocNode, FirstBinding) =
GetAllocationSite(&BR.getStateManager(), EndN, Sym); GetAllocationSite(BR.getStateManager(), EndN, Sym);
// Get the allocate site. // Get the allocate site.
assert (AllocNode); assert (AllocNode);
@ -2519,13 +2518,29 @@ CFRefLeakReport::getEndPath(BugReporter& br, const ExplodedNode<GRState>* EndN){
} }
SourceLocation CFRefLeakReport::getLocation() const { CFRefLeakReport::CFRefLeakReport(CFRefBug& D, ExplodedNode<GRState> *n,
SymbolRef sym, GRStateManager& StateMgr)
: CFRefReport(D, n, sym)
{
// Most bug reports are cached at the location where they occured. // Most bug reports are cached at the location where they occured.
// With leaks, we want to unique them by the location where they were // With leaks, we want to unique them by the location where they were
// allocated, and only report a single path. // allocated, and only report a single path. To do this, we need to find
// the allocation site of a piece of tracked memory, which we do via a
// call to GetAllocationSite. This will walk the ExplodedGraph backwards.
// Note that this is *not* the trimmed graph; we are guaranteed, however,
// that all ancestor nodes that represent the allocation site have the
// same SourceLocation.
const ExplodedNode<GRState>* AllocNode = 0;
llvm::tie(AllocNode, AllocBinding) = // Set AllocBinding.
GetAllocationSite(StateMgr, getEndNode(), getSymbol());
ProgramPoint P = ProgramPoint P =
GetAllocationSite(0, getEndNode(), getSymbol()).first->getLocation(); GetAllocationSite(StateMgr, getEndNode(), getSymbol()).first->getLocation();
return cast<PostStmt>(P).getStmt()->getLocStart();
// Get the SourceLocation for the allocation site.
AllocSite = cast<PostStmt>(P).getStmt()->getLocStart();
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -2566,7 +2581,8 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
CFRefBug *BT = static_cast<CFRefBug*>(I->second ? leakAtReturn CFRefBug *BT = static_cast<CFRefBug*>(I->second ? leakAtReturn
: leakWithinFunction); : leakWithinFunction);
assert(BT && "BugType not initialized."); assert(BT && "BugType not initialized.");
CFRefLeakReport* report = new CFRefLeakReport(*BT, N, I->first); CFRefLeakReport* report = new CFRefLeakReport(*BT, N, I->first,
Eng.getStateManager());
BR->EmitReport(report); BR->EmitReport(report);
} }
} }
@ -2615,7 +2631,8 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
CFRefBug *BT = static_cast<CFRefBug*>(I->second ? leakAtReturn CFRefBug *BT = static_cast<CFRefBug*>(I->second ? leakAtReturn
: leakWithinFunction); : leakWithinFunction);
assert(BT && "BugType not initialized."); assert(BT && "BugType not initialized.");
CFRefLeakReport* report = new CFRefLeakReport(*BT, N, I->first); CFRefLeakReport* report = new CFRefLeakReport(*BT, N, I->first,
Eng.getStateManager());
BR->EmitReport(report); BR->EmitReport(report);
} }
} }