aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-05-16 18:33:44 +0000
committerTed Kremenek <kremenek@apple.com>2008-05-16 18:33:44 +0000
commit6ed9afc804731284b9b6d275dce7053d13d0c044 (patch)
tree5582e63cdec6abbd0ccbf770e551dc1a5dc6b765 /lib/Analysis/CFRefCount.cpp
parent76d90c8bf83d071fd1bdbffa6d9f2af87c6bb7b5 (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.cpp86
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.
//===----------------------------------------------------------------------===//