aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BugReporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/BugReporter.cpp')
-rw-r--r--lib/Analysis/BugReporter.cpp180
1 files changed, 102 insertions, 78 deletions
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index 6a1478a9cb..e56da7b872 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -322,32 +322,27 @@ static VarDecl* GetMostRecentVarDeclBinding(ExplodedNode<GRState>* N,
return 0;
}
+namespace {
+class VISIBILITY_HIDDEN NotableSymbolHandler
+ : public StoreManager::BindingsHandler {
+
+ SymbolID Sym;
+ const GRState* PrevSt;
+ Stmt* S;
+ GRStateManager& VMgr;
+ ExplodedNode<GRState>* Pred;
+ PathDiagnostic& PD;
+ BugReporter& BR;
+
+public:
+
+ NotableSymbolHandler(SymbolID sym, const GRState* prevst, Stmt* s,
+ GRStateManager& vmgr, ExplodedNode<GRState>* 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, MemRegion* R, RVal V) {
-static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
- SymbolID Sym, BugReporter& BR,
- PathDiagnostic& PD) {
-
- ExplodedNode<GRState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
- const GRState* PrevSt = Pred ? Pred->getState() : 0;
-
- if (!PrevSt)
- return;
-
- // Look at the variable bindings of the current state that map to the
- // specified symbol. Are any of them not in the previous state.
-
- const GRState* St = N->getState();
- GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
-
- // FIXME: Later generalize for a broader memory model.
-
- // FIXME: This is quadratic, since its nested in another loop. Probably
- // doesn't matter, but keep an eye out for performance issues. It's
- // also a bunch of copy-paste. Bad. Cleanup later.
-
- for (GRState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
-
- RVal V = I.getData();
SymbolID ScanSym;
if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
@@ -355,18 +350,17 @@ static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
ScanSym = SV->getSymbol();
else
- continue;
+ return true;
if (ScanSym != Sym)
- continue;
-
- // Check if the previous state has this binding.
+ return true;
- RVal X = VMgr.GetRVal(PrevSt, lval::DeclVal(I.getKey()));
+ // Check if the previous state has this binding.
+ RVal X = VMgr.GetRVal(PrevSt, lval::MemRegionVal(R));
if (X == V) // Same binding?
- continue;
-
+ return true;
+
// Different binding. Only handle assignments for now. We don't pull
// this check out of the loop because we will eventually handle other
// cases.
@@ -375,41 +369,102 @@ static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
if (!B->isAssignmentOp())
- continue;
+ return true;
// What variable did we assign to?
DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
if (!DR)
- continue;
+ return true;
VD = dyn_cast<VarDecl>(DR->getDecl());
}
else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
VD = dyn_cast<VarDecl>(DS->getDecl());
-
+
if (!VD)
- continue;
-
+ return true;
+
// What is the most recently referenced variable with this binding?
VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
-
+
if (!MostRecent)
- continue;
-
+ return true;
+
// Create the diagnostic.
FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
-
+
if (VD->getType()->isPointerLikeType()) {
std::string msg = "'" + std::string(VD->getName()) +
- "' now aliases '" + MostRecent->getName() + "'";
+ "' now aliases '" + MostRecent->getName() + "'";
PD.push_front(new PathDiagnosticPiece(L, msg));
}
- }
+
+ return true;
+ }
+};
}
+static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
+ SymbolID Sym, BugReporter& BR,
+ PathDiagnostic& PD) {
+
+ ExplodedNode<GRState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
+ const GRState* 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();
+ NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
+ cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
+}
+
+namespace {
+class VISIBILITY_HIDDEN ScanNotableSymbols
+ : public StoreManager::BindingsHandler {
+
+ llvm::SmallSet<SymbolID, 10> AlreadyProcessed;
+ ExplodedNode<GRState>* N;
+ Stmt* S;
+ GRBugReporter& BR;
+ PathDiagnostic& PD;
+
+public:
+ ScanNotableSymbols(ExplodedNode<GRState>* n, Stmt* s, GRBugReporter& br,
+ PathDiagnostic& pd)
+ : N(n), S(s), BR(br), PD(pd) {}
+
+ bool HandleBinding(StoreManager& SMgr, Store store, MemRegion* R, RVal V) {
+ SymbolID ScanSym;
+
+ if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
+ ScanSym = SV->getSymbol();
+ else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
+ ScanSym = SV->getSymbol();
+ else
+ return true;
+
+ assert (ScanSym.isInitialized());
+
+ if (!BR.isNotable(ScanSym))
+ return true;
+
+ if (AlreadyProcessed.count(ScanSym))
+ return true;
+
+ AlreadyProcessed.insert(ScanSym);
+
+ HandleNotableSymbol(N, S, ScanSym, BR, PD);
+ return true;
+ }
+};
+} // end anonymous namespace
+
void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
BugReport& R) {
@@ -633,42 +688,11 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
if (PathDiagnosticPiece* p = R.VisitNode(N, NextNode, *ReportGraph, *this))
PD.push_front(p);
- if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
-
- const GRState* St = N->getState();
-
- // Scan the lval bindings, and see if a "notable" symbol has a new
+ if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
+ // Scan the region bindings, and see if a "notable" symbol has a new
// lval binding.
-
- // FIXME: In the future, when we generalize the memory model, we'll
- // need a way to iterate over binded locations.
-
- llvm::SmallSet<SymbolID, 10> AlreadyProcessed;
-
- for (GRState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
-
- RVal V = I.getData();
- SymbolID ScanSym;
-
- if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
- ScanSym = SV->getSymbol();
- else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
- ScanSym = SV->getSymbol();
- else
- continue;
-
- assert (ScanSym.isInitialized());
-
- if (!isNotable(ScanSym))
- continue;
-
- if (AlreadyProcessed.count(ScanSym))
- continue;
-
- AlreadyProcessed.insert(ScanSym);
-
- HandleNotableSymbol(N, PS->getStmt(), ScanSym, *this, PD);
- }
+ ScanNotableSymbols SNS(N, PS->getStmt(), *this, PD);
+ getStateManager().iterBindings(N->getState(), SNS);
}
}
}