diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-05-01 23:13:35 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-05-01 23:13:35 +0000 |
commit | c9fa2f7bcc3061aa8bcdbe0df26d2c7cf7281539 (patch) | |
tree | e93a22d8f23f4d41b3d2d0b600cdec4c43052ea9 /lib/Analysis/CFRefCount.cpp | |
parent | bb77e9b908658b354b058509d3801f3aed052bec (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.cpp | 56 |
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(), |