Added line number diagnostics to indicate the allocation site of the leaked object.

llvm-svn: 50553
This commit is contained in:
Ted Kremenek 2008-05-01 23:13:35 +00:00
parent fabfb4677d
commit 1097b4c61f
3 changed files with 57 additions and 7 deletions

View File

@ -143,6 +143,8 @@ public:
ASTContext& getContext() { return Ctx; }
SourceManager& getSourceManager() { return Ctx.getSourceManager(); }
ExplodedGraph<ValueState>& getGraph();
GRExprEngine& getEngine() { return Eng; }

View File

@ -112,10 +112,8 @@ BugReport::getEndPath(BugReporter& BR,
if (!S)
return NULL;
FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
PathDiagnosticPiece* P =
new PathDiagnosticPiece(L, getDescription());
FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
PathDiagnosticPiece* P = new PathDiagnosticPiece(L, getDescription());
const SourceRange *Beg, *End;
getRanges(BR, Beg, End);

View File

@ -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(),