forked from OSchip/llvm-project
Added line number diagnostics to indicate the allocation site of the leaked object.
llvm-svn: 50553
This commit is contained in:
parent
fabfb4677d
commit
1097b4c61f
|
@ -143,6 +143,8 @@ public:
|
||||||
|
|
||||||
ASTContext& getContext() { return Ctx; }
|
ASTContext& getContext() { return Ctx; }
|
||||||
|
|
||||||
|
SourceManager& getSourceManager() { return Ctx.getSourceManager(); }
|
||||||
|
|
||||||
ExplodedGraph<ValueState>& getGraph();
|
ExplodedGraph<ValueState>& getGraph();
|
||||||
|
|
||||||
GRExprEngine& getEngine() { return Eng; }
|
GRExprEngine& getEngine() { return Eng; }
|
||||||
|
|
|
@ -112,10 +112,8 @@ BugReport::getEndPath(BugReporter& BR,
|
||||||
if (!S)
|
if (!S)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
|
FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
|
||||||
|
PathDiagnosticPiece* P = new PathDiagnosticPiece(L, getDescription());
|
||||||
PathDiagnosticPiece* P =
|
|
||||||
new PathDiagnosticPiece(L, getDescription());
|
|
||||||
|
|
||||||
const SourceRange *Beg, *End;
|
const SourceRange *Beg, *End;
|
||||||
getRanges(BR, Beg, End);
|
getRanges(BR, Beg, End);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "GRSimpleVals.h"
|
#include "GRSimpleVals.h"
|
||||||
#include "clang/Basic/LangOptions.h"
|
#include "clang/Basic/LangOptions.h"
|
||||||
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "clang/Analysis/PathSensitive/ValueState.h"
|
#include "clang/Analysis/PathSensitive/ValueState.h"
|
||||||
#include "clang/Analysis/PathDiagnostic.h"
|
#include "clang/Analysis/PathDiagnostic.h"
|
||||||
#include "clang/Analysis/LocalCheckers.h"
|
#include "clang/Analysis/LocalCheckers.h"
|
||||||
|
@ -1446,7 +1447,7 @@ namespace {
|
||||||
|
|
||||||
CFRefCount& getTF() { return TF; }
|
CFRefCount& getTF() { return TF; }
|
||||||
|
|
||||||
virtual bool ReportRanges() const { return true; }
|
virtual bool isLeak() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
|
class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
|
||||||
|
@ -1494,7 +1495,7 @@ namespace {
|
||||||
|
|
||||||
virtual void EmitWarnings(BugReporter& BR);
|
virtual void EmitWarnings(BugReporter& BR);
|
||||||
virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
|
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,
|
virtual void getRanges(BugReporter& BR, const SourceRange*& beg,
|
||||||
const SourceRange*& end) {
|
const SourceRange*& end) {
|
||||||
|
|
||||||
if (getBugType().ReportRanges())
|
if (getBugType().isLeak())
|
||||||
RangedBugReport::getRanges(BR, beg, end);
|
RangedBugReport::getRanges(BR, beg, end);
|
||||||
else {
|
else {
|
||||||
beg = 0;
|
beg = 0;
|
||||||
|
@ -1527,6 +1528,9 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
|
||||||
|
ExplodedNode<ValueState>* N);
|
||||||
|
|
||||||
virtual std::pair<const char**,const char**> getExtraDescriptiveText();
|
virtual std::pair<const char**,const char**> getExtraDescriptiveText();
|
||||||
|
|
||||||
virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
|
virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
|
||||||
|
@ -1699,6 +1703,52 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
|
||||||
return P;
|
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) {
|
void UseAfterRelease::EmitWarnings(BugReporter& BR) {
|
||||||
|
|
||||||
for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
|
for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
|
||||||
|
|
Loading…
Reference in New Issue