[analyzer] Make branch for condition callback use CheckerContext
Now, all the path sensitive checkers use CheckerContext!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142944 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index d030469..afb79b5 100644
--- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -49,27 +49,18 @@
};
public:
- void checkBranchCondition(const Stmt *Condition, NodeBuilder &Builder,
- ExplodedNode *Pred, ExprEngine &Eng) const;
+ void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const;
};
}
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
- NodeBuilder &Builder,
- ExplodedNode *Pred,
- ExprEngine &Eng) const {
- const ProgramState *state = Pred->getState();
- SVal X = state->getSVal(Condition);
+ CheckerContext &Ctx) const {
+ SVal X = Ctx.getState()->getSVal(Condition);
if (X.isUndef()) {
- // TODO: The PP will be generated with the correct tag by the CheckerManager
- // after we migrate the callback to CheckerContext.
- const ProgramPointTag *Tag = 0;
- ProgramPoint PP = PostCondition(Condition, Pred->getLocationContext(), Tag);
// Generate a sink node, which implicitly marks both outgoing branches as
// infeasible.
- ExplodedNode *N = Builder.generateNode(PP, state,
- Pred, true);
+ ExplodedNode *N = Ctx.generateSink();
if (N) {
if (!BT)
BT.reset(
@@ -107,7 +98,7 @@
R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
R->addRange(Ex->getSourceRange());
- Eng.getBugReporter().EmitReport(R);
+ Ctx.EmitReport(R);
}
}
}
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 67fe4d6..ecb1a7a 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -320,15 +320,39 @@
}
}
+namespace {
+ struct CheckBranchConditionContext {
+ typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
+ const CheckersTy &Checkers;
+ const Stmt *Condition;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckBranchConditionContext(const CheckersTy &checkers,
+ const Stmt *Cond, ExprEngine &eng)
+ : Checkers(checkers), Condition(Cond), Eng(eng) {}
+
+ void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
+ NodeBuilder &Bldr, ExplodedNode *Pred) {
+ ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
+ checkFn.Checker);
+ CheckerContext C(Bldr, Eng, Pred, L, 0);
+ checkFn(Condition, C);
+ }
+ };
+}
+
/// \brief Run checkers for branch condition.
-void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
- NodeBuilder &B,
+void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
+ ExplodedNodeSet &Dst,
ExplodedNode *Pred,
ExprEngine &Eng) {
- for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
- CheckBranchConditionFunc fn = BranchConditionCheckers[i];
- fn(condition, B, Pred, Eng);
- }
+ ExplodedNodeSet Src;
+ Src.insert(Pred);
+ CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
}
/// \brief Run checkers for live symbols.
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 3e5a31c..8ba2cd8 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -217,10 +217,13 @@
ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), Pred);
return;
}
+ currentStmtIdx = 0;
+ currentBuilderContext = 0;
}
const Stmt *ExprEngine::getStmt() const {
- const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx].getAs<CFGStmt>();
+ const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx]
+ .getAs<CFGStmt>();
return CS ? CS->getStmt() : 0;
}
@@ -1033,6 +1036,8 @@
ExplodedNodeSet &Dst,
const CFGBlock *DstT,
const CFGBlock *DstF) {
+ currentBuilderContext = &BldCtx;
+
// Check for NULL conditions; e.g. "for(;;)"
if (!Condition) {
BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
@@ -1045,17 +1050,16 @@
Condition->getLocStart(),
"Error evaluating branch");
- ExplodedNodeSet TmpCheckersOut;
- NodeBuilder CheckerBldr(Pred, TmpCheckersOut, BldCtx);
- getCheckerManager().runCheckersForBranchCondition(Condition, CheckerBldr,
+ ExplodedNodeSet CheckersOutSet;
+ getCheckerManager().runCheckersForBranchCondition(Condition, CheckersOutSet,
Pred, *this);
// We generated only sinks.
- if (TmpCheckersOut.empty())
+ if (CheckersOutSet.empty())
return;
- BranchNodeBuilder builder(CheckerBldr.getResults(), Dst, BldCtx, DstT, DstF);
- for (NodeBuilder::iterator I = CheckerBldr.begin(),
- E = CheckerBldr.end(); E != I; ++I) {
+ BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
+ for (NodeBuilder::iterator I = CheckersOutSet.begin(),
+ E = CheckersOutSet.end(); E != I; ++I) {
ExplodedNode *PredI = *I;
if (PredI->isSink())
@@ -1107,6 +1111,7 @@
builder.markInfeasible(false);
}
}
+ currentBuilderContext = 0;
}
/// processIndirectGoto - Called by CoreEngine. Used to generate successor