[analyzer] NodeBuilder Refactoring: Subclass BranchNodeBuilder from NodeBuilder.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142444 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index b860b34..8663893 100644
--- a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -61,9 +61,9 @@
const ProgramState *state = Builder.getState();
SVal X = state->getSVal(Condition);
if (X.isUndef()) {
- ExplodedNode *N = Builder.generateNode(Condition, state);
+ // Generate a sink node.
+ ExplodedNode *N = Builder.generateNode(Condition, state, 0, true);
if (N) {
- N->markAsSink();
if (!BT)
BT.reset(
new BuiltinBug("Branch condition evaluates to a garbage value"));
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 5f2f4ea..0078922 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -417,14 +417,15 @@
void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
const CFGBlock * B, ExplodedNode *Pred) {
assert(B->succ_size() == 2);
- BranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
- Pred, this);
- SubEng.processBranch(Cond, Term, Builder);
+ NodeBuilderContext Ctx(*this, Pred, B);
+ SubEng.processBranch(Cond, Term, Ctx,
+ *(B->succ_begin()), *(B->succ_begin()+1));
}
void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
ExplodedNode *Pred) {
- assert (!B->empty());
+ assert(B);
+ assert(!B->empty());
if (StmtIdx == B->size())
HandleBlockExit(B, Pred);
@@ -454,6 +455,13 @@
if (IsNew) WList->enqueue(Node);
}
+void CoreEngine::enqueue(NodeBuilder &NB) {
+ for (NodeBuilder::iterator I = NB.results_begin(),
+ E = NB.results_end(); I != E; ++I) {
+ WList->enqueue(*I);
+ }
+}
+
ExplodedNode *
GenericNodeBuilderImpl::generateNodeImpl(const ProgramState *state,
ExplodedNode *pred,
@@ -475,23 +483,17 @@
return 0;
}
-NodeBuilder::NodeBuilder(CoreEngine& e, ExplodedNode *N)
- : Eng(e), Pred(N), Finalized(false) {
- assert(!N->isSink());
- Deferred.insert(N);
-}
-
ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
- const ProgramState *State,
- ExplodedNode *Pred,
- bool MarkAsSink) {
+ const ProgramState *State,
+ ExplodedNode *FromN,
+ bool MarkAsSink) {
assert(Finalized == false &&
"We cannot create new nodes after the results have been finalized.");
-
+
bool IsNew;
- ExplodedNode *N = Eng.G->getNode(Loc, State, &IsNew);
- N->addPredecessor(Pred, *Eng.G);
- Deferred.erase(Pred);
+ ExplodedNode *N = C.Eng.G->getNode(Loc, State, &IsNew);
+ N->addPredecessor(FromN, *C.Eng.G);
+ Deferred.erase(FromN);
if (MarkAsSink)
N->markAsSink();
@@ -601,61 +603,41 @@
}
// This function generate a new ExplodedNode but not a new branch(block edge).
+// Creates a transition from the Builder's top predecessor.
ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition,
const ProgramState *State,
- const ProgramPointTag *Tag) {
- bool IsNew;
- ExplodedNode *Succ
- = Eng.G->getNode(PostCondition(Condition, Pred->getLocationContext(), Tag),
- State, &IsNew);
-
- Succ->addPredecessor(Pred, *Eng.G);
-
- Pred = Succ;
-
- if (IsNew)
- return Succ;
-
- return NULL;
+ const ProgramPointTag *Tag,
+ bool MarkAsSink) {
+ ProgramPoint PP = PostCondition(Condition, C.Pred->getLocationContext(), Tag);
+ ExplodedNode *N = generateNodeImpl(PP, State, C.Pred, MarkAsSink);
+ assert(N);
+ // TODO: This needs to go - we should not change Pred!!!
+ C.Pred = N;
+ return N;
}
ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
- bool branch) {
+ bool branch,
+ ExplodedNode *NodePred) {
// If the branch has been marked infeasible we should not generate a node.
if (!isFeasible(branch))
return NULL;
- bool IsNew;
-
- ExplodedNode *Succ =
- Eng.G->getNode(BlockEdge(Src,branch ? DstT:DstF,Pred->getLocationContext()),
- State, &IsNew);
-
- Succ->addPredecessor(Pred, *Eng.G);
+ if (!NodePred)
+ NodePred = C.Pred;
+ ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
+ NodePred->getLocationContext());
+ ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred);
if (branch)
GeneratedTrue = true;
else
GeneratedFalse = true;
- if (IsNew) {
- Deferred.push_back(Succ);
- return Succ;
- }
-
- return NULL;
+ return Succ;
}
-BranchNodeBuilder::~BranchNodeBuilder() {
- if (!GeneratedTrue) generateNode(Pred->State, true);
- if (!GeneratedFalse) generateNode(Pred->State, false);
-
- for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
- if (!(*I)->isSink()) Eng.WList->enqueue(*I);
-}
-
-
ExplodedNode*
IndirectGotoNodeBuilder::generateNode(const iterator &I,
const ProgramState *St,
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index ac9cf0b..cc170bc 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -940,11 +940,17 @@
}
void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
- BranchNodeBuilder& builder) {
+ NodeBuilderContext& BldCtx,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) {
+
+ BranchNodeBuilder builder(BldCtx, DstT, DstF);
// Check for NULL conditions; e.g. "for(;;)"
if (!Condition) {
- builder.markInfeasible(false);
+ BranchNodeBuilder NullCondBldr(BldCtx, DstT, DstF);
+ NullCondBldr.markInfeasible(false);
+ Engine.enqueue(NullCondBldr);
return;
}
@@ -952,11 +958,9 @@
Condition->getLocStart(),
"Error evaluating branch");
- getCheckerManager().runCheckersForBranchCondition(Condition, builder, *this);
-
- // If the branch condition is undefined, return;
- if (!builder.isFeasible(true) && !builder.isFeasible(false))
- return;
+ //TODO: This should take the NodeBuiolder.
+ getCheckerManager().runCheckersForBranchCondition(Condition, builder,
+ *this);
const ProgramState *PrevState = builder.getState();
SVal X = PrevState->getSVal(Condition);
@@ -982,6 +986,8 @@
if (X.isUnknownOrUndef()) {
builder.generateNode(MarkBranch(PrevState, Term, true), true);
builder.generateNode(MarkBranch(PrevState, Term, false), false);
+ // Enqueue the results into the work list.
+ Engine.enqueue(builder);
return;
}
}
@@ -1003,6 +1009,9 @@
else
builder.markInfeasible(false);
}
+
+ // Enqueue the results into the work list.
+ Engine.enqueue(builder);
}
/// processIndirectGoto - Called by CoreEngine. Used to generate successor