aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/BugReporter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2011-10-20 21:14:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2011-10-20 21:14:49 +0000
commit36981b17ed939300f6f8fc2355a255f711fcef71 (patch)
treeee2483e98b09cac943dc93a6969d83ca737ff139 /lib/StaticAnalyzer/Core/BugReporter.cpp
parent180abc3db9ae3b4fc63cd65b15697e6ffcc8a657 (diff)
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Core/BugReporter.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp578
1 files changed, 314 insertions, 264 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 8b5d383ed07f..fbbdb040e4f2 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -33,52 +33,31 @@ using namespace clang;
using namespace ento;
BugReporterVisitor::~BugReporterVisitor() {}
-BugReporterContext::~BugReporterContext() {
- for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I)
- if ((*I)->isOwnedByReporterContext()) delete *I;
-}
-
-void BugReporterContext::addVisitor(BugReporterVisitor* visitor) {
- if (!visitor)
- return;
-
- llvm::FoldingSetNodeID ID;
- visitor->Profile(ID);
- void *InsertPos;
-
- if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
- delete visitor;
- return;
- }
-
- CallbacksSet.InsertNode(visitor, InsertPos);
- Callbacks = F.add(visitor, Callbacks);
-}
//===----------------------------------------------------------------------===//
// Helper routines for walking the ExplodedGraph and fetching statements.
//===----------------------------------------------------------------------===//
-static inline const Stmt* GetStmt(const ProgramPoint &P) {
+static inline const Stmt *GetStmt(const ProgramPoint &P) {
if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P))
return SP->getStmt();
- else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P))
+ else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P))
return BE->getSrc()->getTerminator();
return 0;
}
static inline const ExplodedNode*
-GetPredecessorNode(const ExplodedNode* N) {
+GetPredecessorNode(const ExplodedNode *N) {
return N->pred_empty() ? NULL : *(N->pred_begin());
}
static inline const ExplodedNode*
-GetSuccessorNode(const ExplodedNode* N) {
+GetSuccessorNode(const ExplodedNode *N) {
return N->succ_empty() ? NULL : *(N->succ_begin());
}
-static const Stmt* GetPreviousStmt(const ExplodedNode* N) {
+static const Stmt *GetPreviousStmt(const ExplodedNode *N) {
for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N))
if (const Stmt *S = GetStmt(N->getLocation()))
return S;
@@ -86,7 +65,7 @@ static const Stmt* GetPreviousStmt(const ExplodedNode* N) {
return 0;
}
-static const Stmt* GetNextStmt(const ExplodedNode* N) {
+static const Stmt *GetNextStmt(const ExplodedNode *N) {
for (N = GetSuccessorNode(N); N; N = GetSuccessorNode(N))
if (const Stmt *S = GetStmt(N->getLocation())) {
// Check if the statement is '?' or '&&'/'||'. These are "merges",
@@ -104,11 +83,6 @@ static const Stmt* GetNextStmt(const ExplodedNode* N) {
default:
break;
}
-
- // Some expressions don't have locations.
- if (S->getLocStart().isInvalid())
- continue;
-
return S;
}
@@ -116,7 +90,7 @@ static const Stmt* GetNextStmt(const ExplodedNode* N) {
}
static inline const Stmt*
-GetCurrentOrPreviousStmt(const ExplodedNode* N) {
+GetCurrentOrPreviousStmt(const ExplodedNode *N) {
if (const Stmt *S = GetStmt(N->getLocation()))
return S;
@@ -124,7 +98,7 @@ GetCurrentOrPreviousStmt(const ExplodedNode* N) {
}
static inline const Stmt*
-GetCurrentOrNextStmt(const ExplodedNode* N) {
+GetCurrentOrNextStmt(const ExplodedNode *N) {
if (const Stmt *S = GetStmt(N->getLocation()))
return S;
@@ -145,7 +119,7 @@ public:
NodeMapClosure(NodeBackMap *m) : M(*m) {}
~NodeMapClosure() {}
- const ExplodedNode* getOriginalNode(const ExplodedNode* N) {
+ const ExplodedNode *getOriginalNode(const ExplodedNode *N) {
NodeBackMap::iterator I = M.find(N);
return I == M.end() ? 0 : I->second;
}
@@ -153,25 +127,29 @@ public:
class PathDiagnosticBuilder : public BugReporterContext {
BugReport *R;
- PathDiagnosticClient *PDC;
+ PathDiagnosticConsumer *PDC;
llvm::OwningPtr<ParentMap> PM;
NodeMapClosure NMC;
public:
PathDiagnosticBuilder(GRBugReporter &br,
BugReport *r, NodeBackMap *Backmap,
- PathDiagnosticClient *pdc)
+ PathDiagnosticConsumer *pdc)
: BugReporterContext(br),
- R(r), PDC(pdc), NMC(Backmap) {
- addVisitor(R);
- }
+ R(r), PDC(pdc), NMC(Backmap) {}
- PathDiagnosticLocation ExecutionContinues(const ExplodedNode* N);
+ PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);
- PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream& os,
- const ExplodedNode* N);
+ PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
+ const ExplodedNode *N);
+
+ BugReport *getBugReport() { return R; }
Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
+ const LocationContext* getLocationContext() {
+ return R->getErrorNode()->getLocationContext();
+ }
+
ParentMap& getParentMap() { return R->getErrorNode()->getParentMap(); }
const Stmt *getParent(const Stmt *S) {
@@ -182,8 +160,8 @@ public:
PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
- PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const {
- return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive;
+ PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
+ return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Extensive;
}
bool supportsLogicalOpControlFlow() const {
@@ -193,17 +171,17 @@ public:
} // end anonymous namespace
PathDiagnosticLocation
-PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode* N) {
+PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
if (const Stmt *S = GetNextStmt(N))
- return PathDiagnosticLocation(S, getSourceManager());
+ return PathDiagnosticLocation(S, getSourceManager(), getLocationContext());
- return FullSourceLoc(N->getLocationContext()->getDecl()->getBodyRBrace(),
- getSourceManager());
+ return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(),
+ getSourceManager());
}
PathDiagnosticLocation
-PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os,
- const ExplodedNode* N) {
+PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream &os,
+ const ExplodedNode *N) {
// Slow, but probably doesn't matter.
if (os.str().empty())
@@ -213,7 +191,7 @@ PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os,
if (Loc.asStmt())
os << "Execution continues on line "
- << getSourceManager().getInstantiationLineNumber(Loc.asLocation())
+ << getSourceManager().getExpansionLineNumber(Loc.asLocation())
<< '.';
else {
os << "Execution jumps to the end of the ";
@@ -253,9 +231,10 @@ static bool IsNested(const Stmt *S, ParentMap &PM) {
PathDiagnosticLocation
PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
- assert(S && "Null Stmt* passed to getEnclosingStmtLocation");
+ assert(S && "Null Stmt *passed to getEnclosingStmtLocation");
ParentMap &P = getParentMap();
SourceManager &SMgr = getSourceManager();
+ const LocationContext *LC = getLocationContext();
while (IsNested(S, P)) {
const Stmt *Parent = P.getParentIgnoreParens(S);
@@ -267,44 +246,44 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
case Stmt::BinaryOperatorClass: {
const BinaryOperator *B = cast<BinaryOperator>(Parent);
if (B->isLogicalOp())
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
break;
}
case Stmt::CompoundStmtClass:
case Stmt::StmtExprClass:
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
case Stmt::ChooseExprClass:
// Similar to '?' if we are referring to condition, just have the edge
// point to the entire choose expression.
if (cast<ChooseExpr>(Parent)->getCond() == S)
- return PathDiagnosticLocation(Parent, SMgr);
+ return PathDiagnosticLocation(Parent, SMgr, LC);
else
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
// For '?', if we are referring to condition, just have the edge point
// to the entire '?' expression.
if (cast<AbstractConditionalOperator>(Parent)->getCond() == S)
- return PathDiagnosticLocation(Parent, SMgr);
+ return PathDiagnosticLocation(Parent, SMgr, LC);
else
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
case Stmt::DoStmtClass:
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
case Stmt::ForStmtClass:
if (cast<ForStmt>(Parent)->getBody() == S)
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
break;
case Stmt::IfStmtClass:
if (cast<IfStmt>(Parent)->getCond() != S)
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
break;
case Stmt::ObjCForCollectionStmtClass:
if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
break;
case Stmt::WhileStmtClass:
if (cast<WhileStmt>(Parent)->getCond() != S)
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
break;
default:
break;
@@ -322,7 +301,7 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
switch (Parent->getStmtClass()) {
case Stmt::ForStmtClass:
case Stmt::ObjCForCollectionStmtClass:
- return PathDiagnosticLocation(Parent, SMgr);
+ return PathDiagnosticLocation(Parent, SMgr, LC);
default:
break;
}
@@ -335,20 +314,20 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
if (const ForStmt *FS =
dyn_cast_or_null<ForStmt>(P.getParentIgnoreParens(S))) {
if (FS->getInit() == S)
- return PathDiagnosticLocation(FS, SMgr);
+ return PathDiagnosticLocation(FS, SMgr, LC);
}
}
- return PathDiagnosticLocation(S, SMgr);
+ return PathDiagnosticLocation(S, SMgr, LC);
}
//===----------------------------------------------------------------------===//
// ScanNotableSymbols: closure-like callback for scanning Store bindings.
//===----------------------------------------------------------------------===//
-static const VarDecl*
-GetMostRecentVarDeclBinding(const ExplodedNode* N,
- GRStateManager& VMgr, SVal X) {
+static const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N,
+ ProgramStateManager& VMgr,
+ SVal X) {
for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
@@ -357,7 +336,7 @@ GetMostRecentVarDeclBinding(const ExplodedNode* N,
if (!isa<PostStmt>(P))
continue;
- const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt());
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt());
if (!DR)
continue;
@@ -367,7 +346,7 @@ GetMostRecentVarDeclBinding(const ExplodedNode* N,
if (X != Y)
continue;
- const VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl());
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
continue;
@@ -383,19 +362,29 @@ class NotableSymbolHandler
: public StoreManager::BindingsHandler {
SymbolRef Sym;
- const GRState* PrevSt;
- const Stmt* S;
- GRStateManager& VMgr;
- const ExplodedNode* Pred;
+ const ProgramState *PrevSt;
+ const Stmt *S;
+ ProgramStateManager& VMgr;
+ const ExplodedNode *Pred;
PathDiagnostic& PD;
BugReporter& BR;
public:
- NotableSymbolHandler(SymbolRef sym, const GRState* prevst, const Stmt* s,
- GRStateManager& vmgr, const ExplodedNode* pred,
- PathDiagnostic& pd, BugReporter& br)
- : Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {}
+ NotableSymbolHandler(SymbolRef sym,
+ const ProgramState *prevst,
+ const Stmt *s,
+ ProgramStateManager& vmgr,
+ const ExplodedNode *pred,
+ PathDiagnostic& pd,
+ BugReporter& br)
+ : Sym(sym),
+ PrevSt(prevst),
+ S(s),
+ VMgr(vmgr),
+ Pred(pred),
+ PD(pd),
+ BR(br) {}
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
SVal V) {
@@ -422,14 +411,14 @@ public:
return true;
// What variable did we assign to?
- DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
+ DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
if (!DR)
return true;
VD = dyn_cast<VarDecl>(DR->getDecl());
}
- else if (const DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+ else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
// FIXME: Eventually CFGs won't have DeclStmts. Right now we
// assume that each DeclStmt has a single Decl. This invariant
// holds by construction in the CFG.
@@ -440,19 +429,20 @@ public:
return true;
// What is the most recently referenced variable with this binding?
- const VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
+ const VarDecl *MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
if (!MostRecent)
return true;
// Create the diagnostic.
- FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
-
if (Loc::isLocType(VD->getType())) {
- std::string msg = "'" + std::string(VD->getNameAsString()) +
- "' now aliases '" + MostRecent->getNameAsString() + "'";
-
- PD.push_front(new PathDiagnosticEventPiece(L, msg));
+ llvm::SmallString<64> buf;
+ llvm::raw_svector_ostream os(buf);
+ os << '\'' << *VD << "' now aliases '" << *MostRecent << '\'';
+ PathDiagnosticLocation L =
+ PathDiagnosticLocation::createBegin(S, BR.getSourceManager(),
+ Pred->getLocationContext());
+ PD.push_front(new PathDiagnosticEventPiece(L, os.str()));
}
return true;
@@ -460,20 +450,20 @@ public:
};
}
-static void HandleNotableSymbol(const ExplodedNode* N,
- const Stmt* S,
+static void HandleNotableSymbol(const ExplodedNode *N,
+ const Stmt *S,
SymbolRef Sym, BugReporter& BR,
PathDiagnostic& PD) {
- const ExplodedNode* Pred = N->pred_empty() ? 0 : *N->pred_begin();
- const GRState* PrevSt = Pred ? Pred->getState() : 0;
+ const ExplodedNode *Pred = N->pred_empty() ? 0 : *N->pred_begin();
+ const ProgramState *PrevSt = Pred ? Pred->getState() : 0;
if (!PrevSt)
return;
// Look at the region bindings of the current state that map to the
// specified symbol. Are any of them not in the previous state?
- GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
+ ProgramStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
}
@@ -483,13 +473,13 @@ class ScanNotableSymbols
: public StoreManager::BindingsHandler {
llvm::SmallSet<SymbolRef, 10> AlreadyProcessed;
- const ExplodedNode* N;
- const Stmt* S;
+ const ExplodedNode *N;
+ const Stmt *S;
GRBugReporter& BR;
PathDiagnostic& PD;
public:
- ScanNotableSymbols(const ExplodedNode* n, const Stmt* s,
+ ScanNotableSymbols(const ExplodedNode *n, const Stmt *s,
GRBugReporter& br, PathDiagnostic& pd)
: N(n), S(s), BR(br), PD(pd) {}
@@ -526,7 +516,8 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
const ExplodedNode *N) {
SourceManager& SMgr = PDB.getSourceManager();
- const ExplodedNode* NextNode = N->pred_empty()
+ const LocationContext *LC = PDB.getLocationContext();
+ const ExplodedNode *NextNode = N->pred_empty()
? NULL : *(N->pred_begin());
while (NextNode) {
N = NextNode;
@@ -534,15 +525,17 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
ProgramPoint P = N->getLocation();
- if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
- const CFGBlock* Src = BE->getSrc();
- const CFGBlock* Dst = BE->getDst();
- const Stmt* T = Src->getTerminator();
+ if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
+ const CFGBlock *Src = BE->getSrc();
+ const CFGBlock *Dst = BE->getDst();
+ const Stmt *T = Src->getTerminator();
if (!T)
continue;
- FullSourceLoc Start(T->getLocStart(), SMgr);
+ PathDiagnosticLocation Start =
+ PathDiagnosticLocation::createBegin(T, SMgr,
+ N->getLocationContext());
switch (T->getStmtClass()) {
default:
@@ -550,7 +543,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
case Stmt::GotoStmtClass:
case Stmt::IndirectGotoStmtClass: {
- const Stmt* S = GetNextStmt(N);
+ const Stmt *S = GetNextStmt(N);
if (!S)
continue;
@@ -560,7 +553,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S);
os << "Control jumps to line "
- << End.asLocation().getInstantiationLineNumber();
+ << End.asLocation().getExpansionLineNumber();
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
break;
@@ -571,45 +564,45 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
- if (const Stmt* S = Dst->getLabel()) {
- PathDiagnosticLocation End(S, SMgr);
+ if (const Stmt *S = Dst->getLabel()) {
+ PathDiagnosticLocation End(S, SMgr, LC);
switch (S->getStmtClass()) {
default:
os << "No cases match in the switch statement. "
"Control jumps to line "
- << End.asLocation().getInstantiationLineNumber();
+ << End.asLocation().getExpansionLineNumber();
break;
case Stmt::DefaultStmtClass:
os << "Control jumps to the 'default' case at line "
- << End.asLocation().getInstantiationLineNumber();
+ << End.asLocation().getExpansionLineNumber();
break;
case Stmt::CaseStmtClass: {
os << "Control jumps to 'case ";
- const CaseStmt* Case = cast<CaseStmt>(S);
- const Expr* LHS = Case->getLHS()->IgnoreParenCasts();
+ const CaseStmt *Case = cast<CaseStmt>(S);
+ const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
// Determine if it is an enum.
bool GetRawInt = true;
- if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
// FIXME: Maybe this should be an assertion. Are there cases
// were it is not an EnumConstantDecl?
- const EnumConstantDecl* D =
+ const EnumConstantDecl *D =
dyn_cast<EnumConstantDecl>(DR->getDecl());
if (D) {
GetRawInt = false;
- os << D;
+ os << *D;
}
}
if (GetRawInt)
- os << LHS->EvaluateAsInt(PDB.getASTContext());
+ os << LHS->EvaluateKnownConstInt(PDB.getASTContext());
os << ":' at line "
- << End.asLocation().getInstantiationLineNumber();
+ << End.asLocation().getExpansionLineNumber();
break;
}
}
@@ -673,14 +666,15 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
if (*(Src->succ_begin()+1) == Dst) {
os << "false";
- PathDiagnosticLocation End(B->getLHS(), SMgr);
- PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
+ PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
+ PathDiagnosticLocation Start =
+ PathDiagnosticLocation::createOperatorLoc(B, SMgr);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
}
else {
os << "true";
- PathDiagnosticLocation Start(B->getLHS(), SMgr);
+ PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
PathDiagnosticLocation End = PDB.ExecutionContinues(N);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
@@ -692,15 +686,16 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
if (*(Src->succ_begin()+1) == Dst) {
os << "false";
- PathDiagnosticLocation Start(B->getLHS(), SMgr);
+ PathDiagnosticLocation Start(B->getLHS(), SMgr, LC);
PathDiagnosticLocation End = PDB.ExecutionContinues(N);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
}
else {
os << "true";
- PathDiagnosticLocation End(B->getLHS(), SMgr);
- PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr);
+ PathDiagnosticLocation End(B->getLHS(), SMgr, LC);
+ PathDiagnosticLocation Start =
+ PathDiagnosticLocation::createOperatorLoc(B, SMgr);
PD.push_front(new PathDiagnosticControlFlowPiece(Start, End,
os.str()));
}
@@ -781,14 +776,16 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
}
if (NextNode) {
- for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(),
- E = PDB.visitor_end(); I!=E; ++I) {
- if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB))
+ // Add diagnostic pieces from custom visitors.
+ BugReport *R = PDB.getBugReport();
+ for (BugReport::visitor_iterator I = R->visitor_begin(),
+ E = R->visitor_end(); I!=E; ++I) {
+ if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R))
PD.push_front(p);
}
}
- if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
+ if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) {
// Scan the region bindings, and see if a "notable" symbol has a new
// lval binding.
ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD);
@@ -882,11 +879,11 @@ class EdgeBuilder {
}
if (S != Original)
- L = PathDiagnosticLocation(S, L.getManager());
+ L = PathDiagnosticLocation(S, L.getManager(), PDB.getLocationContext());
}
if (firstCharOnly)
- L = PathDiagnosticLocation(L.asLocation());
+ L = PathDiagnosticLocation::createSingleLocation(L);
return L;
}
@@ -915,17 +912,14 @@ public:
~EdgeBuilder() {
while (!CLocs.empty()) popLocation();
-
+
// Finally, add an initial edge from the start location of the first
// statement (if it doesn't already exist).
- // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
- if (const CompoundStmt *CS =
- dyn_cast_or_null<CompoundStmt>(PDB.getCodeDecl().getBody()))
- if (!CS->body_empty()) {
- SourceLocation Loc = (*CS->body_begin())->getLocStart();
- rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager()));
- }
-
+ PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin(
+ PDB.getLocationContext(),
+ PDB.getSourceManager());
+ if (L.isValid())
+ rawAddEdge(L);
}
void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
@@ -974,15 +968,15 @@ bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
SourceRange ContaineeR = Containee.asRange();
SourceManager &SM = PDB.getSourceManager();
- SourceLocation ContainerRBeg = SM.getInstantiationLoc(ContainerR.getBegin());
- SourceLocation ContainerREnd = SM.getInstantiationLoc(ContainerR.getEnd());
- SourceLocation ContaineeRBeg = SM.getInstantiationLoc(ContaineeR.getBegin());
- SourceLocation ContaineeREnd = SM.getInstantiationLoc(ContaineeR.getEnd());
+ SourceLocation ContainerRBeg = SM.getExpansionLoc(ContainerR.getBegin());
+ SourceLocation ContainerREnd = SM.getExpansionLoc(ContainerR.getEnd());
+ SourceLocation ContaineeRBeg = SM.getExpansionLoc(ContaineeR.getBegin());
+ SourceLocation ContaineeREnd = SM.getExpansionLoc(ContaineeR.getEnd());
- unsigned ContainerBegLine = SM.getInstantiationLineNumber(ContainerRBeg);
- unsigned ContainerEndLine = SM.getInstantiationLineNumber(ContainerREnd);
- unsigned ContaineeBegLine = SM.getInstantiationLineNumber(ContaineeRBeg);
- unsigned ContaineeEndLine = SM.getInstantiationLineNumber(ContaineeREnd);
+ unsigned ContainerBegLine = SM.getExpansionLineNumber(ContainerRBeg);
+ unsigned ContainerEndLine = SM.getExpansionLineNumber(ContainerREnd);
+ unsigned ContaineeBegLine = SM.getExpansionLineNumber(ContaineeRBeg);
+ unsigned ContaineeEndLine = SM.getExpansionLineNumber(ContaineeREnd);
assert(ContainerBegLine <= ContainerEndLine);
assert(ContaineeBegLine <= ContaineeEndLine);
@@ -990,11 +984,11 @@ bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
return (ContainerBegLine <= ContaineeBegLine &&
ContainerEndLine >= ContaineeEndLine &&
(ContainerBegLine != ContaineeBegLine ||
- SM.getInstantiationColumnNumber(ContainerRBeg) <=
- SM.getInstantiationColumnNumber(ContaineeRBeg)) &&
+ SM.getExpansionColumnNumber(ContainerRBeg) <=
+ SM.getExpansionColumnNumber(ContaineeRBeg)) &&
(ContainerEndLine != ContaineeEndLine ||
- SM.getInstantiationColumnNumber(ContainerREnd) >=
- SM.getInstantiationColumnNumber(ContainerREnd)));
+ SM.getExpansionColumnNumber(ContainerREnd) >=
+ SM.getExpansionColumnNumber(ContainerREnd)));
}
void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
@@ -1010,8 +1004,8 @@ void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
return;
// FIXME: Ignore intra-macro edges for now.
- if (NewLocClean.asLocation().getInstantiationLoc() ==
- PrevLocClean.asLocation().getInstantiationLoc())
+ if (NewLocClean.asLocation().getExpansionLoc() ==
+ PrevLocClean.asLocation().getExpansionLoc())
return;
PD.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, PrevLocClean));
@@ -1099,7 +1093,7 @@ void EdgeBuilder::addContext(const Stmt *S) {
if (!S)
return;
- PathDiagnosticLocation L(S, PDB.getSourceManager());
+ PathDiagnosticLocation L(S, PDB.getSourceManager(), PDB.getLocationContext());
while (!CLocs.empty()) {
const PathDiagnosticLocation &TopContextLoc = CLocs.back();
@@ -1124,8 +1118,9 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
PathDiagnosticBuilder &PDB,
const ExplodedNode *N) {
EdgeBuilder EB(PD, PDB);
+ const SourceManager& SM = PDB.getSourceManager();
- const ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
+ const ExplodedNode *NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
while (NextNode) {
N = NextNode;
NextNode = GetPredecessorNode(N);
@@ -1139,7 +1134,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getDst()->getLoopTarget()) {
- PathDiagnosticLocation L(Loop, PDB.getSourceManager());
+ PathDiagnosticLocation L(Loop, SM, PDB.getLocationContext());
const CompoundStmt *CS = NULL;
if (!Term) {
@@ -1157,9 +1152,8 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
PD.push_front(p);
if (CS) {
- PathDiagnosticLocation BL(CS->getRBracLoc(),
- PDB.getSourceManager());
- BL = PathDiagnosticLocation(BL.asLocation());
+ PathDiagnosticLocation BL =
+ PathDiagnosticLocation::createEndBrace(CS, SM);
EB.addEdge(BL);
}
}
@@ -1188,9 +1182,11 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
if (!NextNode)
continue;
- for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(),
- E = PDB.visitor_end(); I!=E; ++I) {
- if (PathDiagnosticPiece* p = (*I)->VisitNode(N, NextNode, PDB)) {
+ // Add pieces from custom visitors.
+ BugReport *R = PDB.getBugReport();
+ for (BugReport::visitor_iterator I = R->visitor_begin(),
+ E = R->visitor_end(); I!=E; ++I) {
+ if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) {
const PathDiagnosticLocation &Loc = p->getLocation();
EB.addEdge(Loc, true);
PD.push_front(p);
@@ -1211,14 +1207,58 @@ void BugType::FlushReports(BugReporter &BR) {}
//===----------------------------------------------------------------------===//
// Methods for BugReport and subclasses.
//===----------------------------------------------------------------------===//
-BugReport::~BugReport() {}
-RangedBugReport::~RangedBugReport() {}
-const Stmt* BugReport::getStmt() const {
+void BugReport::addVisitor(BugReporterVisitor* visitor) {
+ if (!visitor)
+ return;
+
+ llvm::FoldingSetNodeID ID;
+ visitor->Profile(ID);
+ void *InsertPos;
+
+ if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
+ delete visitor;
+ return;
+ }
+
+ CallbacksSet.InsertNode(visitor, InsertPos);
+ Callbacks = F.add(visitor, Callbacks);
+}
+
+BugReport::~BugReport() {
+ for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) {
+ delete *I;
+ }
+}
+
+void BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
+ hash.AddPointer(&BT);
+ hash.AddString(Description);
+ if (Location.isValid()) {
+ Location.Profile(hash);
+ } else {
+ assert(ErrorNode);
+ hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
+ }
+
+ for (SmallVectorImpl<SourceRange>::const_iterator I =
+ Ranges.begin(), E = Ranges.end(); I != E; ++I) {
+ const SourceRange range = *I;
+ if (!range.isValid())
+ continue;
+ hash.AddInteger(range.getBegin().getRawEncoding());
+ hash.AddInteger(range.getEnd().getRawEncoding());
+ }
+}
+
+const Stmt *BugReport::getStmt() const {
+ if (!ErrorNode)
+ return 0;
+
ProgramPoint ProgP = ErrorNode->getLocation();
const Stmt *S = NULL;
- if (BlockEntrance* BE = dyn_cast<BlockEntrance>(&ProgP)) {
+ if (BlockEntrance *BE = dyn_cast<BlockEntrance>(&ProgP)) {
CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
if (BE->getBlock() == &Exit)
S = GetPreviousStmt(ErrorNode);
@@ -1229,61 +1269,47 @@ const Stmt* BugReport::getStmt() const {
return S;
}
-PathDiagnosticPiece*
-BugReport::getEndPath(BugReporterContext& BRC,
- const ExplodedNode* EndPathNode) {
-
- const Stmt* S = getStmt();
-
- if (!S)
- return NULL;
-
- BugReport::ranges_iterator Beg, End;
- llvm::tie(Beg, End) = getRanges();
- PathDiagnosticLocation L(S, BRC.getSourceManager());
-
- // Only add the statement itself as a range if we didn't specify any
- // special ranges for this report.
- PathDiagnosticPiece* P = new PathDiagnosticEventPiece(L, getDescription(),
- Beg == End);
+std::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
+BugReport::getRanges() {
+ // If no custom ranges, add the range of the statement corresponding to
+ // the error node.
+ if (Ranges.empty()) {
+ if (const Expr *E = dyn_cast_or_null<Expr>(getStmt()))
+ addRange(E->getSourceRange());
+ else
+ return std::make_pair(ranges_iterator(), ranges_iterator());
+ }
- for (; Beg != End; ++Beg)
- P->addRange(*Beg);
+ // User-specified absence of range info.
+ if (Ranges.size() == 1 && !Ranges.begin()->isValid())
+ return std::make_pair(ranges_iterator(), ranges_iterator());
- return P;
+ return std::make_pair(Ranges.begin(), Ranges.end());
}
-std::pair<BugReport::ranges_iterator, BugReport::ranges_iterator>
-BugReport::getRanges() const {
- if (const Expr* E = dyn_cast_or_null<Expr>(getStmt())) {
- R = E->getSourceRange();
- assert(R.isValid());
- return std::make_pair(&R, &R+1);
- }
- else
- return std::make_pair(ranges_iterator(), ranges_iterator());
-}
+PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
+ if (ErrorNode) {
+ assert(!Location.isValid() &&
+ "Either Location or ErrorNode should be specified but not both.");
+
+ if (const Stmt *S = GetCurrentOrPreviousStmt(ErrorNode)) {
+ const LocationContext *LC = ErrorNode->getLocationContext();
-SourceLocation BugReport::getLocation() const {
- if (ErrorNode)
- if (const Stmt* S = GetCurrentOrPreviousStmt(ErrorNode)) {
// For member expressions, return the location of the '.' or '->'.
if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
- return ME->getMemberLoc();
+ return PathDiagnosticLocation::createMemberLoc(ME, SM);
// For binary operators, return the location of the operator.
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
- return B->getOperatorLoc();
+ return PathDiagnosticLocation::createOperatorLoc(B, SM);
- return S->getLocStart();
+ return PathDiagnosticLocation::createBegin(S, SM, LC);
}
+ } else {
+ assert(Location.isValid());
+ return Location;
+ }
- return FullSourceLoc();
-}
-
-PathDiagnosticPiece* BugReport::VisitNode(const ExplodedNode* N,
- const ExplodedNode* PrevN,
- BugReporterContext &BRC) {
- return NULL;
+ return PathDiagnosticLocation();
}
//===----------------------------------------------------------------------===//
@@ -1299,10 +1325,19 @@ BugReporterData::~BugReporterData() {}
ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
-GRStateManager&
+ProgramStateManager&
GRBugReporter::getStateManager() { return Eng.getStateManager(); }
-BugReporter::~BugReporter() { FlushReports(); }
+BugReporter::~BugReporter() {
+ FlushReports();
+
+ // Free the bug reports we are tracking.
+ typedef std::vector<BugReportEquivClass *> ContTy;
+ for (ContTy::iterator I = EQClassesVector.begin(), E = EQClassesVector.end();
+ I != E; ++I) {
+ delete *I;
+ }
+}
void BugReporter::FlushReports() {
if (BugTypes.isEmpty())
@@ -1312,10 +1347,10 @@ void BugReporter::FlushReports() {
// warnings and new BugTypes.
// FIXME: Only NSErrorChecker needs BugType's FlushReports.
// Turn NSErrorChecker into a proper checker and remove this.
- llvm::SmallVector<const BugType*, 16> bugTypes;
+ SmallVector<const BugType*, 16> bugTypes;
for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
bugTypes.push_back(*I);
- for (llvm::SmallVector<const BugType*, 16>::iterator
+ for (SmallVector<const BugType*, 16>::iterator
I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
const_cast<BugType*>(*I)->FlushReports(*this);
@@ -1344,7 +1379,7 @@ void BugReporter::FlushReports() {
static std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
std::pair<ExplodedNode*, unsigned> >
MakeReportGraph(const ExplodedGraph* G,
- llvm::SmallVectorImpl<const ExplodedNode*> &nodes) {
+ SmallVectorImpl<const ExplodedNode*> &nodes) {
// Create the trimmed graph. It will contain the shortest paths from the
// error nodes to the root. In the new graph we should only have one
@@ -1390,10 +1425,10 @@ MakeReportGraph(const ExplodedGraph* G,
llvm::DenseMap<const void*,unsigned> Visited;
unsigned cnt = 0;
- const ExplodedNode* Root = 0;
+ const ExplodedNode *Root = 0;
while (!WS.empty()) {
- const ExplodedNode* Node = WS.front();
+ const ExplodedNode *Node = WS.front();
WS.pop();
if (Visited.find(Node) != Visited.end())
@@ -1426,7 +1461,7 @@ MakeReportGraph(const ExplodedGraph* G,
// Create the equivalent node in the new graph with the same state
// and location.
- ExplodedNode* NewN = GNew->getNode(N->getLocation(), N->getState());
+ ExplodedNode *NewN = GNew->getNode(N->getLocation(), N->getState());
// Store the mapping to the original node.
llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N);
@@ -1495,7 +1530,7 @@ static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
// Determine the instantiation location, which is the location we group
// related PathDiagnosticPieces.
SourceLocation InstantiationLoc = Loc.isMacroID() ?
- SM.getInstantiationLoc(Loc) :
+ SM.getExpansionLoc(Loc) :
SourceLocation();
if (Loc.isFileID()) {
@@ -1517,7 +1552,7 @@ static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
PathDiagnosticMacroPiece *MacroGroup = 0;
SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
- SM.getInstantiationLoc(Loc) :
+ SM.getExpansionLoc(Loc) :
SourceLocation();
// Walk the entire macro stack.
@@ -1537,7 +1572,9 @@ static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
// Create a new macro group and add it to the stack.
- PathDiagnosticMacroPiece *NewGroup = new PathDiagnosticMacroPiece(Loc);
+ PathDiagnosticMacroPiece *NewGroup =
+ new PathDiagnosticMacroPiece(
+ PathDiagnosticLocation::createSingleLocation(I->getLocation()));
if (MacroGroup)
MacroGroup->push_back(NewGroup);
@@ -1569,11 +1606,11 @@ static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
}
void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
- llvm::SmallVectorImpl<BugReport *> &bugReports) {
+ SmallVectorImpl<BugReport *> &bugReports) {
assert(!bugReports.empty());
- llvm::SmallVector<const ExplodedNode *, 10> errorNodes;
- for (llvm::SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(),
+ SmallVector<const ExplodedNode *, 10> errorNodes;
+ for (SmallVectorImpl<BugReport*>::iterator I = bugReports.begin(),
E = bugReports.end(); I != E; ++I) {
errorNodes.push_back((*I)->getErrorNode());
}
@@ -1594,22 +1631,36 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
const ExplodedNode *N = GPair.second.first;
// Start building the path diagnostic...
- PathDiagnosticBuilder PDB(*this, R, BackMap.get(), getPathDiagnosticClient());
+ PathDiagnosticBuilder PDB(*this, R, BackMap.get(),
+ getPathDiagnosticConsumer());
- if (PathDiagnosticPiece* Piece = R->getEndPath(PDB, N))
- PD.push_back(Piece);
+ // Register additional node visitors.
+ R->addVisitor(new NilReceiverBRVisitor());
+ R->addVisitor(new ConditionBRVisitor());
+
+ // Generate the very last diagnostic piece - the piece is visible before
+ // the trace is expanded.
+ PathDiagnosticPiece *LastPiece = 0;
+ for (BugReport::visitor_iterator I = R->visitor_begin(),
+ E = R->visitor_end(); I!=E; ++I) {
+ if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) {
+ assert (!LastPiece &&
+ "There can only be one final piece in a diagnostic.");
+ LastPiece = Piece;
+ }
+ }
+ if (!LastPiece)
+ LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R);
+ if (LastPiece)
+ PD.push_back(LastPiece);
else
return;
- // Register node visitors.
- R->registerInitialVisitors(PDB, N);
- bugreporter::registerNilReceiverVisitor(PDB);
-
switch (PDB.getGenerationScheme()) {
- case PathDiagnosticClient::Extensive:
+ case PathDiagnosticConsumer::Extensive:
GenerateExtensivePathDiagnostic(PD, PDB, N);
break;
- case PathDiagnosticClient::Minimal:
+ case PathDiagnosticConsumer::Minimal:
GenerateMinimalPathDiagnostic(PD, PDB, N);
break;
}
@@ -1633,6 +1684,7 @@ void BugReporter::EmitReport(BugReport* R) {
if (!EQ) {
EQ = new BugReportEquivClass(R);
EQClasses.InsertNode(EQ, InsertPos);
+ EQClassesVector.push_back(EQ);
}
else
EQ->AddReport(R);
@@ -1655,7 +1707,7 @@ struct FRIEC_WLItem {
static BugReport *
FindReportInEquivalenceClass(BugReportEquivClass& EQ,
- llvm::SmallVectorImpl<BugReport*> &bugReports) {
+ SmallVectorImpl<BugReport*> &bugReports) {
BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
assert(I != E);
@@ -1667,7 +1719,7 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
// to 'Nodes'. Any of the reports will serve as a "representative" report.
if (!BT.isSuppressOnSink()) {
for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
- const ExplodedNode* N = I->getErrorNode();
+ const ExplodedNode *N = I->getErrorNode();
if (N) {
R = *I;
bugReports.push_back(R);
@@ -1691,9 +1743,8 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
if (!errorNode)
continue;
if (errorNode->isSink()) {
- assert(false &&
+ llvm_unreachable(
"BugType::isSuppressSink() should not be 'true' for sink end nodes");
- return 0;
}
// No successors? By definition this nodes isn't post-dominated by a sink.
if (errorNode->succ_empty()) {
@@ -1706,7 +1757,7 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
// At this point we know that 'N' is not a sink and it has at least one
// successor. Use a DFS worklist to find a non-sink end-of-path node.
typedef FRIEC_WLItem WLItem;
- typedef llvm::SmallVector<WLItem, 10> DFSWorkList;
+ typedef SmallVector<WLItem, 10> DFSWorkList;
llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
DFSWorkList WL;
@@ -1763,11 +1814,8 @@ class DiagCacheItem : public llvm::FoldingSetNode {
llvm::FoldingSetNodeID ID;
public:
DiagCacheItem(BugReport *R, PathDiagnostic *PD) {
- ID.AddString(R->getBugType().getName());
- ID.AddString(R->getBugType().getCategory());
- ID.AddString(R->getDescription());
- ID.AddInteger(R->getLocation().getRawEncoding());
- PD->Profile(ID);
+ R->Profile(ID);
+ PD->Profile(ID);
}
void Profile(llvm::FoldingSetNodeID &id) {
@@ -1798,12 +1846,12 @@ static bool IsCachedDiagnostic(BugReport *R, PathDiagnostic *PD) {
}
void BugReporter::FlushReport(BugReportEquivClass& EQ) {
- llvm::SmallVector<BugReport*, 10> bugReports;
+ SmallVector<BugReport*, 10> bugReports;
BugReport *exampleReport = FindReportInEquivalenceClass(EQ, bugReports);
if (!exampleReport)
return;
- PathDiagnosticClient* PD = getPathDiagnosticClient();
+ PathDiagnosticConsumer* PD = getPathDiagnosticConsumer();
// FIXME: Make sure we use the 'R' for the path that was actually used.
// Probably doesn't make a difference in practice.
@@ -1823,47 +1871,50 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
return;
// Get the meta data.
- std::pair<const char**, const char**> Meta =
- exampleReport->getExtraDescriptiveText();
- for (const char** s = Meta.first; s != Meta.second; ++s)
- D->addMeta(*s);
+ const BugReport::ExtraTextList &Meta =
+ exampleReport->getExtraText();
+ for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
+ e = Meta.end(); i != e; ++i) {
+ D->addMeta(*i);
+ }
// Emit a summary diagnostic to the regular Diagnostics engine.
BugReport::ranges_iterator Beg, End;
llvm::tie(Beg, End) = exampleReport->getRanges();
- Diagnostic &Diag = getDiagnostic();
- FullSourceLoc L(exampleReport->getLocation(), getSourceManager());
+ DiagnosticsEngine &Diag = getDiagnostic();
// Search the description for '%', as that will be interpretted as a
// format character by FormatDiagnostics.
- llvm::StringRef desc = exampleReport->getShortDescription();
+ StringRef desc = exampleReport->getShortDescription();
unsigned ErrorDiag;
{
llvm::SmallString<512> TmpStr;
llvm::raw_svector_ostream Out(TmpStr);
- for (llvm::StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I)
+ for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I)
if (*I == '%')
Out << "%%";
else
Out << *I;
Out.flush();
- ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, TmpStr);
+ ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, TmpStr);
}
{
- DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
+ DiagnosticBuilder diagBuilder = Diag.Report(
+ exampleReport->getLocation(getSourceManager()).asLocation(), ErrorDiag);
for (BugReport::ranges_iterator I = Beg; I != End; ++I)
diagBuilder << *I;
}
- // Emit a full diagnostic for the path if we have a PathDiagnosticClient.
+ // Emit a full diagnostic for the path if we have a PathDiagnosticConsumer.
if (!PD)
return;
if (D->empty()) {
- PathDiagnosticPiece* piece =
- new PathDiagnosticEventPiece(L, exampleReport->getDescription());
+ PathDiagnosticPiece *piece = new PathDiagnosticEventPiece(
+ exampleReport->getLocation(getSourceManager()),
+ exampleReport->getDescription());
for ( ; Beg != End; ++Beg) piece->addRange(*Beg);
D->push_back(piece);
@@ -1872,27 +1923,26 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
PD->HandlePathDiagnostic(D.take());
}
-void BugReporter::EmitBasicReport(llvm::StringRef name, llvm::StringRef str,
- SourceLocation Loc,
+void BugReporter::EmitBasicReport(StringRef name, StringRef str,
+ PathDiagnosticLocation Loc,
SourceRange* RBeg, unsigned NumRanges) {
EmitBasicReport(name, "", str, Loc, RBeg, NumRanges);
}
-void BugReporter::EmitBasicReport(llvm::StringRef name,
- llvm::StringRef category,
- llvm::StringRef str, SourceLocation Loc,
+void BugReporter::EmitBasicReport(StringRef name,
+ StringRef category,
+ StringRef str, PathDiagnosticLocation Loc,
SourceRange* RBeg, unsigned NumRanges) {
// 'BT' is owned by BugReporter.
BugType *BT = getBugTypeForName(name, category);
- FullSourceLoc L = getContext().getFullLoc(Loc);
- RangedBugReport *R = new DiagBugReport(*BT, str, L);
+ BugReport *R = new BugReport(*BT, str, Loc);
for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
EmitReport(R);
}
-BugType *BugReporter::getBugTypeForName(llvm::StringRef name,
- llvm::StringRef category) {
+BugType *BugReporter::getBugTypeForName(StringRef name,
+ StringRef category) {
llvm::SmallString<136> fullDesc;
llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
llvm::StringMapEntry<BugType *> &