forked from OSchip/llvm-project
[analyzer] Subclassing StmtBuilder from the NodeBuilder
llvm-svn: 142451
This commit is contained in:
parent
e83ddcc4ec
commit
88d9462b73
|
@ -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()));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue