diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-05-16 18:33:44 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-05-16 18:33:44 +0000 |
commit | 6ed9afc804731284b9b6d275dce7053d13d0c044 (patch) | |
tree | 5582e63cdec6abbd0ccbf770e551dc1a5dc6b765 /lib/Analysis/CFRefCount.cpp | |
parent | 76d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5 (diff) |
Cache leaks by the allocation site, not the leak location.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51198 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index fd47f03d3e..35f380ebc3 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Compiler.h" +#include "llvm/ADT/STLExtras.h" #include <ostream> #include <sstream> @@ -1740,6 +1741,7 @@ namespace { virtual void EmitWarnings(BugReporter& BR); virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes); virtual bool isLeak() const { return true; } + virtual bool isCached(BugReport& R); }; //===---------===// @@ -1772,6 +1774,8 @@ namespace { } } + SymbolID getSymbol() const { return Sym; } + virtual PathDiagnosticPiece* getEndPath(BugReporter& BR, ExplodedNode<ValueState>* N); @@ -1963,37 +1967,17 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N, return P; } - -PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR, - ExplodedNode<ValueState>* EndN) { - - if (!getBugType().isLeak()) - return RangedBugReport::getEndPath(BR, EndN); +static std::pair<ExplodedNode<ValueState>*,VarDecl*> +GetAllocationSite(ExplodedNode<ValueState>* N, SymbolID Sym) { typedef CFRefCount::RefBindings RefBindings; - - // Get the retain count. - unsigned long RetCount = 0; - - { - ValueState* St = EndN->getState(); - RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState); - RefBindings::TreeTy* T = B.SlimFind(Sym); - assert (T); - RetCount = GetCount(T->getValue().second); - } - - // We are a leak. Walk up the graph to get to the first node where the - // symbol appeared. - - ExplodedNode<ValueState>* N = EndN; ExplodedNode<ValueState>* Last = N; // Find the first node that referred to the tracked symbol. We also // try and find the first VarDecl the value was stored to. VarDecl* FirstDecl = 0; - + while (N) { ValueState* St = N->getState(); RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState); @@ -2001,7 +1985,7 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR, if (!T) break; - + VarDecl* VD = 0; // Determine if there is an LVal binding to the symbol. @@ -2019,15 +2003,44 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR, } if (VD) FirstDecl = VD; - + Last = N; N = N->pred_empty() ? NULL : *(N->pred_begin()); } - // Get the allocate site. + return std::make_pair(Last, FirstDecl); +} + +PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR, + ExplodedNode<ValueState>* EndN) { - assert (Last); - Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt(); + if (!getBugType().isLeak()) + return RangedBugReport::getEndPath(BR, EndN); + + typedef CFRefCount::RefBindings RefBindings; + + // Get the retain count. + unsigned long RetCount = 0; + + { + ValueState* St = EndN->getState(); + RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState); + RefBindings::TreeTy* T = B.SlimFind(Sym); + assert (T); + RetCount = GetCount(T->getValue().second); + } + + // We are a leak. Walk up the graph to get to the first node where the + // symbol appeared, and also get the first VarDecl that tracked object + // is stored to. + + ExplodedNode<ValueState>* AllocNode = 0; + VarDecl* FirstDecl = 0; + llvm::tie(AllocNode, FirstDecl) = GetAllocationSite(EndN, Sym); + + // Get the allocate site. + assert (AllocNode); + Stmt* FirstStmt = cast<PostStmt>(AllocNode->getLocation()).getStmt(); SourceManager& SMgr = BR.getContext().getSourceManager(); unsigned AllocLine = SMgr.getLogicalLineNumber(FirstStmt->getLocStart()); @@ -2128,6 +2141,23 @@ void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) { Nodes.push_back(I->first); } +bool Leak::isCached(BugReport& R) { + + // Most bug reports are cached at the location where they occured. + // With leaks, we want to unique them by the location where they were + // allocated, and only report only a single path. + + SymbolID Sym = static_cast<CFRefReport&>(R).getSymbol(); + + ExplodedNode<ValueState>* AllocNode = + GetAllocationSite(R.getEndNode(), Sym).first; + + if (!AllocNode) + return false; + + return BugTypeCacheLocation::isCached(AllocNode->getLocation()); +} + //===----------------------------------------------------------------------===// // Transfer function creation for external clients. //===----------------------------------------------------------------------===// |