[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), Location(loc),
ST(st), ST(st),
size(Dst.size()), size(Dst.size()),
Ctx(builder.Eng, builder.getBlock()), Ctx(builder.C.Eng, builder.getBlock()),
NB(pred, Ctx), NB(pred, Ctx),
respondsToCallback(respondsToCB) { respondsToCallback(respondsToCB) {
assert(!(ST && ST != Pred->getState())); assert(!(ST && ST != Pred->getState()));

View File

@ -181,7 +181,12 @@ protected:
friend class StmtNodeBuilder; friend class StmtNodeBuilder;
ExplodedNode *BuilderPred; ExplodedNode *BuilderPred;
// TODO: Context should become protected after refactoring is done.
public:
const NodeBuilderContext &C; const NodeBuilderContext &C;
protected:
bool Finalized; bool Finalized;
/// \brief The frontier set - a set of nodes which need to be propagated after /// \brief The frontier set - a set of nodes which need to be propagated after
@ -254,6 +259,9 @@ public:
return Deferred.end(); 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 /// \brief Returns the number of times the current basic block has been
/// visited on the exploded graph path. /// visited on the exploded graph path.
unsigned getCurrentBlockCount() const { unsigned getCurrentBlockCount() const {
@ -272,8 +280,6 @@ public:
class CommonNodeBuilder { class CommonNodeBuilder {
protected: protected:
ExplodedNode *Pred; ExplodedNode *Pred;
public:
// TODO: make protected.
CoreEngine& Eng; CoreEngine& Eng;
CommonNodeBuilder(CoreEngine* E, ExplodedNode *P) : Pred(P), Eng(*E) {} CommonNodeBuilder(CoreEngine* E, ExplodedNode *P) : Pred(P), Eng(*E) {}
@ -281,49 +287,36 @@ public:
}; };
class StmtNodeBuilder: public CommonNodeBuilder { class StmtNodeBuilder: public NodeBuilder {
const CFGBlock &B;
const unsigned Idx; const unsigned Idx;
public: public:
bool PurgingDeadSymbols; bool PurgingDeadSymbols;
bool BuildSinks; bool BuildSinks;
// TODO: Remove the flag. We should be able to use the method in the parent.
bool hasGeneratedNode; bool hasGeneratedNode;
ProgramPoint::Kind PointKind; ProgramPoint::Kind PointKind;
const ProgramPointTag *Tag; const ProgramPointTag *Tag;
typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy;
DeferredTy Deferred;
void GenerateAutoTransition(ExplodedNode *N); void GenerateAutoTransition(ExplodedNode *N);
public: public:
StmtNodeBuilder(const CFGBlock *b, StmtNodeBuilder(ExplodedNode *N, unsigned idx, NodeBuilderContext &Ctx);
unsigned idx,
ExplodedNode *N,
CoreEngine* e);
~StmtNodeBuilder(); ~StmtNodeBuilder();
ExplodedNode *getPredecessor() const { return Pred; }
unsigned getCurrentBlockCount() const {
return getBlockCounter().getNumVisited(
Pred->getLocationContext()->getCurrentStackFrame(),
B.getBlockID());
}
ExplodedNode *generateNode(const Stmt *S, ExplodedNode *generateNode(const Stmt *S,
const ProgramState *St, const ProgramState *St,
ExplodedNode *Pred, ExplodedNode *Pred,
ProgramPoint::Kind K, ProgramPoint::Kind K,
const ProgramPointTag *tag = 0) { const ProgramPointTag *tag = 0,
hasGeneratedNode = true; bool MarkAsSink = false) {
if (PurgingDeadSymbols) if (PurgingDeadSymbols)
K = ProgramPoint::PostPurgeDeadSymbolsKind; 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, ExplodedNode *generateNode(const Stmt *S,
@ -336,33 +329,16 @@ public:
ExplodedNode *generateNode(const ProgramPoint &PP, ExplodedNode *generateNode(const ProgramPoint &PP,
const ProgramState *State, const ProgramState *State,
ExplodedNode *Pred) { ExplodedNode *Pred) {
hasGeneratedNode = true; return generateNodeImpl(PP, State, Pred, false);
return generateNodeInternal(PP, State, Pred);
} }
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 /// getStmt - Return the current block-level expression associated with
/// this builder. /// this builder.
const Stmt *getStmt() const { const Stmt *getStmt() const {
const CFGStmt *CS = B[Idx].getAs<CFGStmt>(); const CFGStmt *CS = (*C.Block)[Idx].getAs<CFGStmt>();
return CS ? CS->getStmt() : 0; 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; } unsigned getIndex() const { return Idx; }
ExplodedNode *MakeNode(ExplodedNodeSet &Dst, ExplodedNode *MakeNode(ExplodedNodeSet &Dst,
@ -394,7 +370,6 @@ public:
if (NB.hasGeneratedNodes()) { if (NB.hasGeneratedNodes()) {
Deferred.erase(NBPred); Deferred.erase(NBPred);
Deferred.insert(NB.Deferred.begin(), NB.Deferred.end()); 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. // Process the entrance of the block.
if (CFGElement E = L.getFirstElement()) { 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); SubEng.processCFGElement(E, Builder);
} }
else else
@ -430,7 +431,8 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
if (StmtIdx == B->size()) if (StmtIdx == B->size())
HandleBlockExit(B, Pred); HandleBlockExit(B, Pred);
else { else {
StmtNodeBuilder Builder(B, StmtIdx, Pred, this); NodeBuilderContext Ctx(*this, B);
StmtNodeBuilder Builder(Pred, StmtIdx, Ctx);
SubEng.processCFGElement((*B)[StmtIdx], Builder); SubEng.processCFGElement((*B)[StmtIdx], Builder);
} }
} }
@ -505,11 +507,9 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
} }
StmtNodeBuilder::StmtNodeBuilder(const CFGBlock *b, StmtNodeBuilder::StmtNodeBuilder(ExplodedNode *N, unsigned idx,
unsigned idx, NodeBuilderContext &Ctx)
ExplodedNode *N, : NodeBuilder(N, Ctx), Idx(idx),
CoreEngine* e)
: CommonNodeBuilder(e, N), B(*b), Idx(idx),
PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false), PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
PointKind(ProgramPoint::PostStmtKind), Tag(0) { PointKind(ProgramPoint::PostStmtKind), Tag(0) {
Deferred.insert(N); Deferred.insert(N);
@ -528,13 +528,13 @@ void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
if (isa<CallEnter>(N->getLocation())) { if (isa<CallEnter>(N->getLocation())) {
// Still use the index of the CallExpr. It's needed to create the callee // Still use the index of the CallExpr. It's needed to create the callee
// StackFrameContext. // StackFrameContext.
Eng.WList->enqueue(N, &B, Idx); C.Eng.WList->enqueue(N, C.Block, Idx);
return; return;
} }
// Do not create extra nodes. Move to the next CFG element. // Do not create extra nodes. Move to the next CFG element.
if (isa<PostInitializer>(N->getLocation())) { if (isa<PostInitializer>(N->getLocation())) {
Eng.WList->enqueue(N, &B, Idx+1); C.Eng.WList->enqueue(N, C.Block, Idx+1);
return; return;
} }
@ -543,16 +543,16 @@ void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
if (Loc == N->getLocation()) { if (Loc == N->getLocation()) {
// Note: 'N' should be a fresh node because otherwise it shouldn't be // Note: 'N' should be a fresh node because otherwise it shouldn't be
// a member of Deferred. // a member of Deferred.
Eng.WList->enqueue(N, &B, Idx+1); C.Eng.WList->enqueue(N, C.Block, Idx+1);
return; return;
} }
bool IsNew; bool IsNew;
ExplodedNode *Succ = Eng.G->getNode(Loc, N->State, &IsNew); ExplodedNode *Succ = C.Eng.G->getNode(Loc, N->State, &IsNew);
Succ->addPredecessor(N, *Eng.G); Succ->addPredecessor(N, *C.Eng.G);
if (IsNew) if (IsNew)
Eng.WList->enqueue(Succ, &B, Idx+1); C.Eng.WList->enqueue(Succ, C.Block, Idx+1);
} }
ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst, ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst,
@ -560,48 +560,13 @@ ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst,
ExplodedNode *Pred, ExplodedNode *Pred,
const ProgramState *St, const ProgramState *St,
ProgramPoint::Kind K) { ProgramPoint::Kind K) {
ExplodedNode *N = generateNode(S, St, Pred, K, 0, BuildSinks);
ExplodedNode *N = generateNode(S, St, Pred, K); if (N && !BuildSinks){
if (N) {
if (BuildSinks)
N->markAsSink();
else
Dst.Add(N); Dst.Add(N);
} }
return 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, ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
bool branch, bool branch,
ExplodedNode *NodePred) { ExplodedNode *NodePred) {

View File

@ -226,7 +226,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
evalObjCMessage(dstEval, msg, Pred, Pred->getState()); 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 // Finally, perform the post-condition check of the ObjCMessageExpr and store