[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& operator=(const CoreEngine&);
void enqueueStmtNode(ExplodedNode *N,
const CFGBlock *Block, unsigned Idx);
public:
/// Construct a CoreEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
@ -163,8 +166,12 @@ public:
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);
/// \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.

View File

@ -454,13 +454,59 @@ void CoreEngine::generateNode(const ProgramPoint &Loc,
if (IsNew) WList->enqueue(Node);
}
void CoreEngine::enqueue(ExplodedNodeSet &S) {
for (ExplodedNodeSet::iterator I = S.begin(),
E = S.end(); I != E; ++I) {
void CoreEngine::enqueueStmtNode(ExplodedNode *N,
const CFGBlock *Block, unsigned Idx) {
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);
}
}
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,
const ProgramState *State,
ExplodedNode *FromN,

View File

@ -220,50 +220,6 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
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,
ExplodedNode *Pred) {
// TODO: Use RAII to remove the unnecessary, tagged nodes.
@ -346,19 +302,16 @@ void ExprEngine::ProcessStmt(const CFGStmt S,
}
}
ExplodedNodeSet AllDst;
ExplodedNodeSet Dst;
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
ExplodedNodeSet Dst;
ExplodedNodeSet DstI;
// Visit the statement.
Visit(currentStmt, *I, Dst);
AllDst.insert(Dst);
Visit(currentStmt, *I, DstI);
Dst.insert(DstI);
}
for (ExplodedNodeSet::iterator I = AllDst.begin(),
E = AllDst.end(); I != E; ++I) {
assert(!(*I)->isSink());
GenerateAutoTransition(*I);
}
// Enqueue the new nodes onto the work list.
Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
// NULL out these variables to cleanup.
CleanedState = NULL;
@ -418,10 +371,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
VisitCXXConstructExpr(ctorExpr, baseReg, Pred, Dst);
}
for (ExplodedNodeSet::iterator I = Dst.begin(),
E = Dst.end(); I != E; ++I) {
GenerateAutoTransition(*I);
}
// Enqueue the new nodes onto the work list.
Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
}
void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
@ -444,10 +396,8 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
llvm_unreachable("Unexpected dtor kind.");
}
for (ExplodedNodeSet::iterator I = Dst.begin(),
E = Dst.end(); I != E; ++I) {
GenerateAutoTransition(*I);
}
// Enqueue the new nodes onto the work list.
Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
}
void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,