aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-05-01 23:13:35 +0000
committerTed Kremenek <kremenek@apple.com>2008-05-01 23:13:35 +0000
commitc9fa2f7bcc3061aa8bcdbe0df26d2c7cf7281539 (patch)
treee93a22d8f23f4d41b3d2d0b600cdec4c43052ea9 /lib/Analysis/CFRefCount.cpp
parentbb77e9b908658b354b058509d3801f3aed052bec (diff)
Added line number diagnostics to indicate the allocation site of the leaked object.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50553 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r--lib/Analysis/CFRefCount.cpp56
1 files changed, 53 insertions, 3 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index ea036f047b..104391c13a 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -14,6 +14,7 @@
#include "GRSimpleVals.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/LocalCheckers.h"
@@ -1446,7 +1447,7 @@ namespace {
CFRefCount& getTF() { return TF; }
- virtual bool ReportRanges() const { return true; }
+ virtual bool isLeak() const { return false; }
};
class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
@@ -1494,7 +1495,7 @@ namespace {
virtual void EmitWarnings(BugReporter& BR);
virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
- virtual bool ReportRanges() const { return false; }
+ virtual bool isLeak() const { return true; }
};
//===---------===//
@@ -1519,7 +1520,7 @@ namespace {
virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
const SourceRange*& end) {
- if (getBugType().ReportRanges())
+ if (getBugType().isLeak())
RangedBugReport::getRanges(BR, beg, end);
else {
beg = 0;
@@ -1527,6 +1528,9 @@ namespace {
}
}
+ virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
+ ExplodedNode<ValueState>* N);
+
virtual std::pair<const char**,const char**> getExtraDescriptiveText();
virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
@@ -1699,6 +1703,52 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
return P;
}
+PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
+ ExplodedNode<ValueState>* N) {
+
+ if (!getBugType().isLeak())
+ return RangedBugReport::getEndPath(BR, N);
+
+ // We are a leak. Walk up the graph to get to the first node where the
+ // symbol appeared.
+
+ ExplodedNode<ValueState>* Last = N;
+ typedef CFRefCount::RefBindings RefBindings;
+
+ // Find the first node that referred to the tracked symbol.
+
+ while (N) {
+ ValueState* St = N->getState();
+ RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
+
+ if (!B.SlimFind(Sym))
+ break;
+
+ Last = N;
+ N = N->pred_empty() ? NULL : *(N->pred_begin());
+ }
+
+ // Get the location.
+
+ assert (Last);
+ Stmt* FirstStmt = cast<PostStmt>(Last->getLocation()).getStmt();
+
+ unsigned Line =
+ BR.getSourceManager().getLogicalLineNumber(FirstStmt->getLocStart());
+
+ // FIXME: Also get the name of the variable.
+
+ std::ostringstream os;
+ os << "Object allocated on line " << Line << " is leaked.";
+
+ Stmt* S = getStmt(BR);
+ assert (S);
+ FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
+ PathDiagnosticPiece* P = new PathDiagnosticPiece(L, os.str());
+
+ return P;
+}
+
void UseAfterRelease::EmitWarnings(BugReporter& BR) {
for (CFRefCount::use_after_iterator I = TF.use_after_begin(),