forked from OSchip/llvm-project
[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:
parent
67f914dc97
commit
b1d3d96872
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue