[analyzer] Make CoreEngine responsible for enqueueing Stmt Nodes.

Enqueue the nodes generated as the result of processing a statement
inside the Core Engine. This makes sure ExpEngine does not access
CoreEngine's private members and is more concise.

llvm-svn: 143089
This commit is contained in:
Anna Zaks 2011-10-27 00:59:23 +00:00
parent 67f914dc97
commit b1d3d96872
3 changed files with 68 additions and 65 deletions

View File

@ -100,6 +100,9 @@ private:
CoreEngine(const CoreEngine&); // Do not implement. CoreEngine(const CoreEngine&); // Do not implement.
CoreEngine& operator=(const CoreEngine&); CoreEngine& operator=(const CoreEngine&);
void enqueueStmtNode(ExplodedNode *N,
const CFGBlock *Block, unsigned Idx);
public: public:
/// Construct a CoreEngine object to analyze the provided CFG using /// Construct a CoreEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph. /// a DFS exploration of the exploded graph.
@ -163,8 +166,12 @@ public:
return blocksAborted.end(); return blocksAborted.end();
} }
/// Enqueue the results of the node builder onto the work list. /// \brief Enqueue the given set of nodes onto the work list.
void enqueue(ExplodedNodeSet &NB); void enqueue(ExplodedNodeSet &NB);
/// \brief Enqueue nodes that were created as a result of processing
/// a statement onto the work list.
void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx);
}; };
// TODO: Turn into a calss. // TODO: Turn into a calss.

View File

@ -454,13 +454,59 @@ void CoreEngine::generateNode(const ProgramPoint &Loc,
if (IsNew) WList->enqueue(Node); if (IsNew) WList->enqueue(Node);
} }
void CoreEngine::enqueue(ExplodedNodeSet &S) { void CoreEngine::enqueueStmtNode(ExplodedNode *N,
for (ExplodedNodeSet::iterator I = S.begin(), const CFGBlock *Block, unsigned Idx) {
E = S.end(); I != E; ++I) { assert (!N->isSink());
// Check if this node entered a callee.
if (isa<CallEnter>(N->getLocation())) {
// Still use the index of the CallExpr. It's needed to create the callee
// StackFrameContext.
WList->enqueue(N, Block, Idx);
return;
}
// Do not create extra nodes. Move to the next CFG element.
if (isa<PostInitializer>(N->getLocation())) {
WList->enqueue(N, Block, Idx+1);
return;
}
const CFGStmt *CS = (*Block)[Idx].getAs<CFGStmt>();
const Stmt *St = CS ? CS->getStmt() : 0;
PostStmt Loc(St, N->getLocationContext());
if (Loc == N->getLocation()) {
// Note: 'N' should be a fresh node because otherwise it shouldn't be
// a member of Deferred.
WList->enqueue(N, Block, Idx+1);
return;
}
bool IsNew;
ExplodedNode *Succ = G->getNode(Loc, N->getState(), &IsNew);
Succ->addPredecessor(N, *G);
if (IsNew)
WList->enqueue(Succ, Block, Idx+1);
}
void CoreEngine::enqueue(ExplodedNodeSet &Set) {
for (ExplodedNodeSet::iterator I = Set.begin(),
E = Set.end(); I != E; ++I) {
WList->enqueue(*I); WList->enqueue(*I);
} }
} }
void CoreEngine::enqueue(ExplodedNodeSet &Set,
const CFGBlock *Block, unsigned Idx) {
for (ExplodedNodeSet::iterator I = Set.begin(),
E = Set.end(); I != E; ++I) {
enqueueStmtNode(*I, Block, Idx);
}
}
ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
const ProgramState *State, const ProgramState *State,
ExplodedNode *FromN, ExplodedNode *FromN,

View File

@ -220,50 +220,6 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
currentBuilderContext = 0; currentBuilderContext = 0;
} }
const Stmt *ExprEngine::getStmt() const {
const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx]
.getAs<CFGStmt>();
return CS ? CS->getStmt() : 0;
}
// TODO: Adding nodes to the worklist shoudl be a function inside CoreEngine.
void ExprEngine::GenerateAutoTransition(ExplodedNode *N) {
assert (!N->isSink());
const CFGBlock *Block = currentBuilderContext->getBlock();
unsigned Idx = currentStmtIdx;
// Check if this node entered a callee.
if (isa<CallEnter>(N->getLocation())) {
// Still use the index of the CallExpr. It's needed to create the callee
// StackFrameContext.
Engine.WList->enqueue(N, Block, Idx);
return;
}
// Do not create extra nodes. Move to the next CFG element.
if (isa<PostInitializer>(N->getLocation())) {
Engine.WList->enqueue(N, Block, Idx+1);
return;
}
PostStmt Loc(getStmt(), N->getLocationContext());
if (Loc == N->getLocation()) {
// Note: 'N' should be a fresh node because otherwise it shouldn't be
// a member of Deferred.
Engine.WList->enqueue(N, Block, Idx+1);
return;
}
bool IsNew;
ExplodedNode *Succ = Engine.G->getNode(Loc, N->getState(), &IsNew);
Succ->addPredecessor(N, *Engine.G);
if (IsNew)
Engine.WList->enqueue(Succ, Block, Idx+1);
}
void ExprEngine::ProcessStmt(const CFGStmt S, void ExprEngine::ProcessStmt(const CFGStmt S,
ExplodedNode *Pred) { ExplodedNode *Pred) {
// TODO: Use RAII to remove the unnecessary, tagged nodes. // TODO: Use RAII to remove the unnecessary, tagged nodes.
@ -346,19 +302,16 @@ void ExprEngine::ProcessStmt(const CFGStmt S,
} }
} }
ExplodedNodeSet AllDst;
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
ExplodedNodeSet Dst; ExplodedNodeSet Dst;
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
ExplodedNodeSet DstI;
// Visit the statement. // Visit the statement.
Visit(currentStmt, *I, Dst); Visit(currentStmt, *I, DstI);
AllDst.insert(Dst); Dst.insert(DstI);
} }
for (ExplodedNodeSet::iterator I = AllDst.begin(), // Enqueue the new nodes onto the work list.
E = AllDst.end(); I != E; ++I) { Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
assert(!(*I)->isSink());
GenerateAutoTransition(*I);
}
// NULL out these variables to cleanup. // NULL out these variables to cleanup.
CleanedState = NULL; CleanedState = NULL;
@ -418,10 +371,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
VisitCXXConstructExpr(ctorExpr, baseReg, Pred, Dst); VisitCXXConstructExpr(ctorExpr, baseReg, Pred, Dst);
} }
for (ExplodedNodeSet::iterator I = Dst.begin(),
E = Dst.end(); I != E; ++I) { // Enqueue the new nodes onto the work list.
GenerateAutoTransition(*I); Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
}
} }
void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
@ -444,10 +396,8 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
llvm_unreachable("Unexpected dtor kind."); llvm_unreachable("Unexpected dtor kind.");
} }
for (ExplodedNodeSet::iterator I = Dst.begin(), // Enqueue the new nodes onto the work list.
E = Dst.end(); I != E; ++I) { Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
GenerateAutoTransition(*I);
}
} }
void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor, void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,