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),
|
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()));
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue