aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BugReporter.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-01-24 00:55:43 +0000
committerTed Kremenek <kremenek@apple.com>2009-01-24 00:55:43 +0000
commit3148eb4a75f70f2636075c364d03104223f004d3 (patch)
tree5b7f56dc02c2201a7fed6502e57845b1bfec6a04 /lib/Analysis/BugReporter.cpp
parentaa23b570b059e8d29c69a656bbdc42f652f7c308 (diff)
More hacking on static analyzer diagnostics. When emitting summary diagnostics the code paths for diagnostics involving paths or single locations are now unified. This patch also constifies many arguments/methods that are touched by this logic, leading to a nice overall code cleanup.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62903 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/BugReporter.cpp')
-rw-r--r--lib/Analysis/BugReporter.cpp184
1 files changed, 76 insertions, 108 deletions
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index 9d4d059341..b08f5cb793 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -64,27 +64,30 @@ static inline Stmt* GetStmt(const CFGBlock* B) {
return (*B)[0];
}
-static inline ExplodedNode<GRState>*
-GetNextNode(ExplodedNode<GRState>* N) {
+static inline const ExplodedNode<GRState>*
+GetNextNode(const ExplodedNode<GRState>* N) {
return N->pred_empty() ? NULL : *(N->pred_begin());
}
-static Stmt* GetLastStmt(ExplodedNode<GRState>* N) {
+static Stmt* GetLastStmt(const ExplodedNode<GRState>* N) {
assert (isa<BlockEntrance>(N->getLocation()));
for (N = GetNextNode(N); N; N = GetNextNode(N)) {
-
ProgramPoint P = N->getLocation();
-
- if (PostStmt* PS = dyn_cast<PostStmt>(&P))
- return PS->getStmt();
+ if (PostStmt* PS = dyn_cast<PostStmt>(&P)) return PS->getStmt();
}
return NULL;
}
+static inline Stmt* GetStmt(const ExplodedNode<GRState>* N) {
+ ProgramPoint ProgP = N->getLocation();
+ return isa<BlockEntrance>(ProgP) ? GetLastStmt(N) : GetStmt(ProgP);
+}
+
+
static void ExecutionContinues(std::ostringstream& os, SourceManager& SMgr,
- Stmt* S) {
+ const Stmt* S) {
if (!S)
return;
@@ -100,7 +103,7 @@ static void ExecutionContinues(std::ostringstream& os, SourceManager& SMgr,
static inline void ExecutionContinues(std::ostringstream& os,
SourceManager& SMgr,
- ExplodedNode<GRState>* N) {
+ const ExplodedNode<GRState>* N) {
ExecutionContinues(os, SMgr, GetStmt(N->getLocation()));
}
@@ -129,7 +132,7 @@ Stmt* BugReport::getStmt(BugReporter& BR) const {
PathDiagnosticPiece*
BugReport::getEndPath(BugReporter& BR,
- ExplodedNode<GRState>* EndPathNode) {
+ const ExplodedNode<GRState>* EndPathNode) {
Stmt* S = getStmt(BR);
@@ -165,7 +168,7 @@ FullSourceLoc BugReport::getLocation(SourceManager& Mgr) {
if (!EndNode)
return FullSourceLoc();
- Stmt* S = GetStmt(EndNode->getLocation());
+ Stmt* S = GetStmt(EndNode);
if (!S)
return FullSourceLoc();
@@ -173,21 +176,22 @@ FullSourceLoc BugReport::getLocation(SourceManager& Mgr) {
return FullSourceLoc(S->getLocStart(), Mgr);
}
-PathDiagnosticPiece* BugReport::VisitNode(ExplodedNode<GRState>* N,
- ExplodedNode<GRState>* PrevN,
- ExplodedGraph<GRState>& G,
+PathDiagnosticPiece* BugReport::VisitNode(const ExplodedNode<GRState>* N,
+ const ExplodedNode<GRState>* PrevN,
+ const ExplodedGraph<GRState>& G,
BugReporter& BR) {
return NULL;
}
static std::pair<ExplodedGraph<GRState>*, ExplodedNode<GRState>*>
-MakeReportGraph(ExplodedGraph<GRState>* G, ExplodedNode<GRState>* N) {
+MakeReportGraph(const ExplodedGraph<GRState>* G,
+ const ExplodedNode<GRState>* N) {
- llvm::OwningPtr<ExplodedGraph<GRState> > GTrim(G->Trim(&N, &N+1));
+ llvm::OwningPtr< ExplodedGraph<GRState> > GTrim(G->Trim(&N, &N+1));
// Find the error node in the trimmed graph.
- ExplodedNode<GRState>* NOld = N;
+ const ExplodedNode<GRState>* NOld = N;
N = 0;
for (ExplodedGraph<GRState>::node_iterator
@@ -203,21 +207,21 @@ MakeReportGraph(ExplodedGraph<GRState>* G, ExplodedNode<GRState>* N) {
assert(N);
// Create a new graph with a single path.
-
- G = new ExplodedGraph<GRState>(GTrim->getCFG(), GTrim->getCodeDecl(),
- GTrim->getContext());
+ ExplodedGraph<GRState> *GNew =
+ new ExplodedGraph<GRState>(GTrim->getCFG(), GTrim->getCodeDecl(),
+ GTrim->getContext());
// Sometimes TrimGraph can contain a cycle. Perform a reverse DFS
// to the root node, and then construct a new graph that contains only
// a single path.
- llvm::DenseMap<void*,unsigned> Visited;
- llvm::SmallVector<ExplodedNode<GRState>*, 10> WS;
+ llvm::DenseMap<const void*,unsigned> Visited;
+ llvm::SmallVector<const ExplodedNode<GRState>*, 10> WS;
WS.push_back(N);
unsigned cnt = 0;
- ExplodedNode<GRState>* Root = 0;
+ const ExplodedNode<GRState>* Root = 0;
while (!WS.empty()) {
- ExplodedNode<GRState>* Node = WS.back();
+ const ExplodedNode<GRState>* Node = WS.back();
WS.pop_back();
if (Visited.find(Node) != Visited.end())
@@ -230,7 +234,7 @@ MakeReportGraph(ExplodedGraph<GRState>* G, ExplodedNode<GRState>* N) {
break;
}
- for (ExplodedNode<GRState>::pred_iterator I=Node->pred_begin(),
+ for (ExplodedNode<GRState>::const_pred_iterator I=Node->pred_begin(),
E=Node->pred_end(); I!=E; ++I)
WS.push_back(*I);
}
@@ -242,15 +246,14 @@ MakeReportGraph(ExplodedGraph<GRState>* G, ExplodedNode<GRState>* N) {
ExplodedNode<GRState> *Last = 0, *First = 0;
for ( N = Root ;;) {
-
// Lookup the number associated with the current node.
- llvm::DenseMap<void*,unsigned>::iterator I=Visited.find(N);
+ llvm::DenseMap<const void*,unsigned>::iterator I = Visited.find(N);
assert (I != Visited.end());
// Create the equivalent node in the new graph with the same state
// and location.
ExplodedNode<GRState>* NewN =
- G->getNode(N->getLocation(), N->getState());
+ GNew->getNode(N->getLocation(), N->getState());
// Link up the new node with the previous node.
if (Last)
@@ -266,8 +269,8 @@ MakeReportGraph(ExplodedGraph<GRState>* G, ExplodedNode<GRState>* N) {
// Find the next successor node. We choose the node that is marked
// with the lowest DFS number.
- ExplodedNode<GRState>::succ_iterator SI = N->succ_begin();
- ExplodedNode<GRState>::succ_iterator SE = N->succ_end();
+ ExplodedNode<GRState>::const_succ_iterator SI = N->succ_begin();
+ ExplodedNode<GRState>::const_succ_iterator SE = N->succ_end();
N = 0;
for (unsigned MinVal = 0; SI != SE; ++SI) {
@@ -287,12 +290,12 @@ MakeReportGraph(ExplodedGraph<GRState>* G, ExplodedNode<GRState>* N) {
}
assert (First);
- return std::make_pair(G, First);
+ return std::make_pair(GNew, First);
}
-static VarDecl* GetMostRecentVarDeclBinding(ExplodedNode<GRState>* N,
- GRStateManager& VMgr,
- SVal X) {
+static const VarDecl*
+GetMostRecentVarDeclBinding(const ExplodedNode<GRState>* N,
+ GRStateManager& VMgr, SVal X) {
for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
@@ -328,16 +331,16 @@ class VISIBILITY_HIDDEN NotableSymbolHandler
SymbolRef Sym;
const GRState* PrevSt;
- Stmt* S;
+ const Stmt* S;
GRStateManager& VMgr;
- ExplodedNode<GRState>* Pred;
+ const ExplodedNode<GRState>* Pred;
PathDiagnostic& PD;
BugReporter& BR;
public:
- NotableSymbolHandler(SymbolRef sym, const GRState* prevst, Stmt* s,
- GRStateManager& vmgr, ExplodedNode<GRState>* pred,
+ NotableSymbolHandler(SymbolRef sym, const GRState* prevst, const Stmt* s,
+ GRStateManager& vmgr, const ExplodedNode<GRState>* pred,
PathDiagnostic& pd, BugReporter& br)
: Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {}
@@ -367,7 +370,7 @@ public:
VarDecl *VD = 0;
- if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+ if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
if (!B->isAssignmentOp())
return true;
@@ -379,7 +382,7 @@ public:
VD = dyn_cast<VarDecl>(DR->getDecl());
}
- else if (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 contruction in the CFG.
@@ -390,7 +393,7 @@ public:
return true;
// What is the most recently referenced variable with this binding?
- VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
+ const VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
if (!MostRecent)
return true;
@@ -411,11 +414,12 @@ public:
};
}
-static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
+static void HandleNotableSymbol(const ExplodedNode<GRState>* N,
+ const Stmt* S,
SymbolRef Sym, BugReporter& BR,
PathDiagnostic& PD) {
- ExplodedNode<GRState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
+ const ExplodedNode<GRState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
const GRState* PrevSt = Pred ? Pred->getState() : 0;
if (!PrevSt)
@@ -433,13 +437,13 @@ class VISIBILITY_HIDDEN ScanNotableSymbols
: public StoreManager::BindingsHandler {
llvm::SmallSet<SymbolRef, 10> AlreadyProcessed;
- ExplodedNode<GRState>* N;
+ const ExplodedNode<GRState>* N;
Stmt* S;
GRBugReporter& BR;
PathDiagnostic& PD;
public:
- ScanNotableSymbols(ExplodedNode<GRState>* n, Stmt* s, GRBugReporter& br,
+ ScanNotableSymbols(const ExplodedNode<GRState>* n, Stmt* s, GRBugReporter& br,
PathDiagnostic& pd)
: N(n), S(s), BR(br), PD(pd) {}
@@ -472,14 +476,14 @@ public:
void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
BugReport& R) {
- ExplodedNode<GRState>* N = R.getEndNode();
+ const ExplodedNode<GRState>* N = R.getEndNode();
if (!N) return;
// Construct a new graph that contains only a single path from the error
// node to a root.
- const std::pair<ExplodedGraph<GRState>*,ExplodedNode<GRState>*>
+ const std::pair<ExplodedGraph<GRState>*, ExplodedNode<GRState>*>
GPair = MakeReportGraph(&getGraph(), N);
llvm::OwningPtr<ExplodedGraph<GRState> > ReportGraph(GPair.first);
@@ -493,15 +497,15 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
else
return;
- ExplodedNode<GRState>* NextNode = N->pred_empty()
- ? NULL : *(N->pred_begin());
+ const ExplodedNode<GRState>* NextNode = N->pred_empty()
+ ? NULL : *(N->pred_begin());
ASTContext& Ctx = getContext();
SourceManager& SMgr = Ctx.getSourceManager();
while (NextNode) {
- ExplodedNode<GRState>* LastNode = N;
+ const ExplodedNode<GRState>* LastNode = N;
N = NextNode;
NextNode = GetNextNode(N);
@@ -697,7 +701,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
bool BugTypeCacheLocation::isCached(BugReport& R) {
- ExplodedNode<GRState>* N = R.getEndNode();
+ const ExplodedNode<GRState>* N = R.getEndNode();
if (!N)
return false;
@@ -727,73 +731,37 @@ void BugReporter::EmitWarning(BugReport& R) {
GeneratePathDiagnostic(*D.get(), R);
// Get the meta data.
-
std::pair<const char**, const char**> Meta = R.getExtraDescriptiveText();
-
- for (const char** s = Meta.first; s != Meta.second; ++s)
- D->addMeta(*s);
+ for (const char** s = Meta.first; s != Meta.second; ++s) D->addMeta(*s);
- // Emit a full diagnostic for the path if we have a PathDiagnosticClient.
-
+ // Emit a summary diagnostic to the regular Diagnostics engine.
PathDiagnosticClient* PD = getPathDiagnosticClient();
-
- if (PD && !D->empty()) {
- PD->HandlePathDiagnostic(D.take());
- // Output a diagnostic summarizing the report.
- Diagnostic& Diag = getDiagnostic();
- Diag.Report(R.getLocation(getSourceManager()),
- Diag.getCustomDiagID(Diagnostic::Warning,R.getDescription()));
- return;
- }
-
- // This isn't a bug with a path, but we can still emit a single
- // line diagnostic. Determine the location.
- FullSourceLoc L = D->empty() ? R.getLocation(getSourceManager())
- : D->back()->getLocation();
-
- // Determine the range.
- const SourceRange *Beg, *End;
-
- if (!D->empty()) {
- Beg = D->back()->ranges_begin();
- End = D->back()->ranges_end();
- }
- else
- R.getRanges(*this, Beg, End);
-
- if (PD) {
- PathDiagnosticPiece* piece = new PathDiagnosticPiece(L, R.getDescription());
-
- for ( ; Beg != End; ++Beg)
- piece->addRange(*Beg);
-
- D->push_back(piece);
- PD->HandlePathDiagnostic(D.take());
-
- // Output a diagnostic summarizing the report.
- Diagnostic& Diag = getDiagnostic();
- Diag.Report(L,Diag.getCustomDiagID(Diagnostic::Warning,R.getDescription()));
- return;
- }
- else {
- std::string str;
-
- if (D->empty())
- str = R.getDescription();
- else
- str = D->back()->getString();
-
- Diagnostic& Diag = getDiagnostic();
- unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, str.c_str());
+ const SourceRange *Beg = 0, *End = 0;
+ R.getRanges(*this, Beg, End);
+ Diagnostic& Diag = getDiagnostic();
+ FullSourceLoc L = R.getLocation(getSourceManager());
+ const char *msg = PD ? R.getBugType().getName() : R.getDescription();
+ unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
- switch (End-Beg) {
+ switch (End-Beg) {
default: assert(0 && "Don't handle this many ranges yet!");
case 0: Diag.Report(L, ErrorDiag); break;
case 1: Diag.Report(L, ErrorDiag) << Beg[0]; break;
case 2: Diag.Report(L, ErrorDiag) << Beg[0] << Beg[1]; break;
case 3: Diag.Report(L, ErrorDiag) << Beg[0] << Beg[1] << Beg[2]; break;
- }
}
+
+ // Emit a full diagnostic for the path if we have a PathDiagnosticClient.
+ if (!PD)
+ return;
+
+ if (D->empty()) {
+ PathDiagnosticPiece* piece = new PathDiagnosticPiece(L, R.getDescription());
+ for ( ; Beg != End; ++Beg) piece->addRange(*Beg);
+ D->push_back(piece);
+ }
+
+ PD->HandlePathDiagnostic(D.take());
}
void BugReporter::EmitBasicReport(const char* name, const char* str,