[analyzer] Subclassing StmtBuilder from the NodeBuilder

llvm-svn: 142451
This commit is contained in:
Anna Zaks 2011-10-18 23:06:33 +00:00
parent e83ddcc4ec
commit 88d9462b73
4 changed files with 38 additions and 98 deletions

View File

@ -50,7 +50,7 @@ public:
Location(loc),
ST(st),
size(Dst.size()),
Ctx(builder.Eng, builder.getBlock()),
Ctx(builder.C.Eng, builder.getBlock()),
NB(pred, Ctx),
respondsToCallback(respondsToCB) {
assert(!(ST && ST != Pred->getState()));

View File

@ -181,7 +181,12 @@ protected:
friend class StmtNodeBuilder;
ExplodedNode *BuilderPred;
// TODO: Context should become protected after refactoring is done.
public:
const NodeBuilderContext &C;
protected:
bool Finalized;
/// \brief The frontier set - a set of nodes which need to be propagated after
@ -254,6 +259,9 @@ public:
return Deferred.end();
}
/// \brief Return the CFGBlock associated with this builder.
const CFGBlock *getBlock() const { return C.Block; }
/// \brief Returns the number of times the current basic block has been
/// visited on the exploded graph path.
unsigned getCurrentBlockCount() const {
@ -272,8 +280,6 @@ public:
class CommonNodeBuilder {
protected:
ExplodedNode *Pred;
public:
// TODO: make protected.
CoreEngine& Eng;
CommonNodeBuilder(CoreEngine* E, ExplodedNode *P) : Pred(P), Eng(*E) {}
@ -281,49 +287,36 @@ public:
};
class StmtNodeBuilder: public CommonNodeBuilder {
const CFGBlock &B;
class StmtNodeBuilder: public NodeBuilder {
const unsigned Idx;
public:
bool PurgingDeadSymbols;
bool BuildSinks;
// TODO: Remove the flag. We should be able to use the method in the parent.
bool hasGeneratedNode;
ProgramPoint::Kind PointKind;
const ProgramPointTag *Tag;
typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy;
DeferredTy Deferred;
void GenerateAutoTransition(ExplodedNode *N);
public:
StmtNodeBuilder(const CFGBlock *b,
unsigned idx,
ExplodedNode *N,
CoreEngine* e);
StmtNodeBuilder(ExplodedNode *N, unsigned idx, NodeBuilderContext &Ctx);
~StmtNodeBuilder();
ExplodedNode *getPredecessor() const { return Pred; }
unsigned getCurrentBlockCount() const {
return getBlockCounter().getNumVisited(
Pred->getLocationContext()->getCurrentStackFrame(),
B.getBlockID());
}
ExplodedNode *generateNode(const Stmt *S,
const ProgramState *St,
ExplodedNode *Pred,
ProgramPoint::Kind K,
const ProgramPointTag *tag = 0) {
hasGeneratedNode = true;
const ProgramPointTag *tag = 0,
bool MarkAsSink = false) {
if (PurgingDeadSymbols)
K = ProgramPoint::PostPurgeDeadSymbolsKind;
return generateNodeInternal(S, St, Pred, K, tag ? tag : Tag);
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), tag ? tag : Tag);
return generateNodeImpl(L, St, Pred, MarkAsSink);
}
ExplodedNode *generateNode(const Stmt *S,
@ -336,33 +329,16 @@ public:
ExplodedNode *generateNode(const ProgramPoint &PP,
const ProgramState *State,
ExplodedNode *Pred) {
hasGeneratedNode = true;
return generateNodeInternal(PP, State, Pred);
return generateNodeImpl(PP, State, Pred, false);
}
ExplodedNode*
generateNodeInternal(const ProgramPoint &PP,
const ProgramState *State,
ExplodedNode *Pred);
ExplodedNode*
generateNodeInternal(const Stmt *S,
const ProgramState *State,
ExplodedNode *Pred,
ProgramPoint::Kind K,
const ProgramPointTag *tag = 0);
/// getStmt - Return the current block-level expression associated with
/// this builder.
const Stmt *getStmt() const {
const CFGStmt *CS = B[Idx].getAs<CFGStmt>();
const CFGStmt *CS = (*C.Block)[Idx].getAs<CFGStmt>();
return CS ? CS->getStmt() : 0;
}
/// getBlock - Return the CFGBlock associated with the block-level expression
/// of this builder.
const CFGBlock *getBlock() const { return &B; }
unsigned getIndex() const { return Idx; }
ExplodedNode *MakeNode(ExplodedNodeSet &Dst,
@ -394,7 +370,6 @@ public:
if (NB.hasGeneratedNodes()) {
Deferred.erase(NBPred);
Deferred.insert(NB.Deferred.begin(), NB.Deferred.end());
hasGeneratedNode = true;
}
}
};

View File

@ -314,7 +314,8 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
// Process the entrance of the block.
if (CFGElement E = L.getFirstElement()) {
StmtNodeBuilder Builder(L.getBlock(), 0, Pred, this);
NodeBuilderContext Ctx(*this, L.getBlock());
StmtNodeBuilder Builder(Pred, 0, Ctx);
SubEng.processCFGElement(E, Builder);
}
else
@ -430,7 +431,8 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
if (StmtIdx == B->size())
HandleBlockExit(B, Pred);
else {
StmtNodeBuilder Builder(B, StmtIdx, Pred, this);
NodeBuilderContext Ctx(*this, B);
StmtNodeBuilder Builder(Pred, StmtIdx, Ctx);
SubEng.processCFGElement((*B)[StmtIdx], Builder);
}
}
@ -484,9 +486,9 @@ GenericNodeBuilderImpl::generateNodeImpl(const ProgramState *state,
}
ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
const ProgramState *State,
ExplodedNode *FromN,
bool MarkAsSink) {
const ProgramState *State,
ExplodedNode *FromN,
bool MarkAsSink) {
assert(Finalized == false &&
"We cannot create new nodes after the results have been finalized.");
@ -505,11 +507,9 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
}
StmtNodeBuilder::StmtNodeBuilder(const CFGBlock *b,
unsigned idx,
ExplodedNode *N,
CoreEngine* e)
: CommonNodeBuilder(e, N), B(*b), Idx(idx),
StmtNodeBuilder::StmtNodeBuilder(ExplodedNode *N, unsigned idx,
NodeBuilderContext &Ctx)
: NodeBuilder(N, Ctx), Idx(idx),
PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
PointKind(ProgramPoint::PostStmtKind), Tag(0) {
Deferred.insert(N);
@ -528,13 +528,13 @@ void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
if (isa<CallEnter>(N->getLocation())) {
// Still use the index of the CallExpr. It's needed to create the callee
// StackFrameContext.
Eng.WList->enqueue(N, &B, Idx);
C.Eng.WList->enqueue(N, C.Block, Idx);
return;
}
// Do not create extra nodes. Move to the next CFG element.
if (isa<PostInitializer>(N->getLocation())) {
Eng.WList->enqueue(N, &B, Idx+1);
C.Eng.WList->enqueue(N, C.Block, Idx+1);
return;
}
@ -543,16 +543,16 @@ void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
if (Loc == N->getLocation()) {
// Note: 'N' should be a fresh node because otherwise it shouldn't be
// a member of Deferred.
Eng.WList->enqueue(N, &B, Idx+1);
C.Eng.WList->enqueue(N, C.Block, Idx+1);
return;
}
bool IsNew;
ExplodedNode *Succ = Eng.G->getNode(Loc, N->State, &IsNew);
Succ->addPredecessor(N, *Eng.G);
ExplodedNode *Succ = C.Eng.G->getNode(Loc, N->State, &IsNew);
Succ->addPredecessor(N, *C.Eng.G);
if (IsNew)
Eng.WList->enqueue(Succ, &B, Idx+1);
C.Eng.WList->enqueue(Succ, C.Block, Idx+1);
}
ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst,
@ -560,48 +560,13 @@ ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst,
ExplodedNode *Pred,
const ProgramState *St,
ProgramPoint::Kind K) {
ExplodedNode *N = generateNode(S, St, Pred, K);
if (N) {
if (BuildSinks)
N->markAsSink();
else
ExplodedNode *N = generateNode(S, St, Pred, K, 0, BuildSinks);
if (N && !BuildSinks){
Dst.Add(N);
}
return N;
}
ExplodedNode*
StmtNodeBuilder::generateNodeInternal(const Stmt *S,
const ProgramState *state,
ExplodedNode *Pred,
ProgramPoint::Kind K,
const ProgramPointTag *tag) {
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), tag);
return generateNodeInternal(L, state, Pred);
}
ExplodedNode*
StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
const ProgramState *State,
ExplodedNode *Pred) {
bool IsNew;
ExplodedNode *N = Eng.G->getNode(Loc, State, &IsNew);
N->addPredecessor(Pred, *Eng.G);
Deferred.erase(Pred);
if (IsNew) {
Deferred.insert(N);
return N;
}
return NULL;
}
ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
bool branch,
ExplodedNode *NodePred) {

View File

@ -226,7 +226,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
evalObjCMessage(dstEval, msg, Pred, Pred->getState());
}
assert(Builder->BuildSinks || Builder->hasGeneratedNode);
assert(Builder->BuildSinks || Builder->hasGeneratedNodes());
}
// Finally, perform the post-condition check of the ObjCMessageExpr and store