Added boilerplate logic in GREngine for processing branches.
llvm-svn: 46532
This commit is contained in:
parent
b2cad31aae
commit
9b4211d25d
|
@ -730,7 +730,8 @@ class VISIBILITY_HIDDEN GRConstants {
|
|||
|
||||
public:
|
||||
typedef ValueMapTy StateTy;
|
||||
typedef GRStmtNodeBuilder<GRConstants> NodeBuilder;
|
||||
typedef GRStmtNodeBuilder<GRConstants> StmtNodeBuilder;
|
||||
typedef GRBranchNodeBuilder<GRConstants> BranchNodeBuilder;
|
||||
typedef ExplodedGraph<GRConstants> GraphTy;
|
||||
typedef GraphTy::NodeTy NodeTy;
|
||||
|
||||
|
@ -767,8 +768,8 @@ protected:
|
|||
|
||||
/// Builder - The current GRStmtNodeBuilder which is used when building the nodes
|
||||
/// for a given statement.
|
||||
NodeBuilder* Builder;
|
||||
|
||||
StmtNodeBuilder* Builder;
|
||||
|
||||
/// StateMgr - Object that manages the data for all created states.
|
||||
ValueMapTy::Factory StateMgr;
|
||||
|
||||
|
@ -826,7 +827,12 @@ public:
|
|||
|
||||
/// ProcessStmt - Called by GREngine. Used to generate new successor
|
||||
/// nodes by processing the 'effects' of a block-level statement.
|
||||
void ProcessStmt(Stmt* S, NodeBuilder& builder);
|
||||
void ProcessStmt(Stmt* S, StmtNodeBuilder& builder);
|
||||
|
||||
/// ProcessBranch - Called by GREngine. Used to generate successor
|
||||
/// nodes by processing the 'effects' of a branch condition.
|
||||
void ProcessBranch(Stmt* Condition, Stmt* Term, BranchNodeBuilder& builder)
|
||||
{}
|
||||
|
||||
/// RemoveDeadBindings - Return a new state that is the same as 'M' except
|
||||
/// that all subexpression mappings are removed and that any
|
||||
|
@ -871,7 +877,7 @@ public:
|
|||
} // end anonymous namespace
|
||||
|
||||
|
||||
void GRConstants::ProcessStmt(Stmt* S, NodeBuilder& builder) {
|
||||
void GRConstants::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
|
||||
Builder = &builder;
|
||||
|
||||
StmtEntryNode = builder.getLastNode();
|
||||
|
|
|
@ -149,8 +149,29 @@ void GREngineImpl::HandleBlockEntrance(const BlockEntrance& L,
|
|||
|
||||
void GREngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNodeImpl* Pred) {
|
||||
|
||||
if (Stmt* Terminator = B->getTerminator())
|
||||
ProcessTerminator(Terminator, B, Pred);
|
||||
if (Stmt* Term = B->getTerminator()) {
|
||||
switch (Term->getStmtClass()) {
|
||||
default:
|
||||
assert(false && "Analysis for this terminator not implemented.");
|
||||
break;
|
||||
|
||||
case Stmt::IfStmtClass:
|
||||
HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
|
||||
break;
|
||||
|
||||
case Stmt::ForStmtClass:
|
||||
HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
|
||||
break;
|
||||
|
||||
case Stmt::WhileStmtClass:
|
||||
HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
|
||||
break;
|
||||
|
||||
case Stmt::DoStmtClass:
|
||||
HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert (B->succ_size() == 1 &&
|
||||
"Blocks with no terminator should have at most 1 successor.");
|
||||
|
@ -159,6 +180,16 @@ void GREngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNodeImpl* Pred) {
|
|||
}
|
||||
}
|
||||
|
||||
void GREngineImpl::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
|
||||
ExplodedNodeImpl* Pred) {
|
||||
assert (B->succ_size() == 2);
|
||||
|
||||
GRBranchNodeBuilderImpl Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
|
||||
Pred, this);
|
||||
|
||||
ProcessBranch(Cond, Term, Builder);
|
||||
}
|
||||
|
||||
void GREngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B,
|
||||
unsigned StmtIdx, ExplodedNodeImpl* Pred) {
|
||||
|
||||
|
@ -255,3 +286,16 @@ ExplodedNodeImpl* GRStmtNodeBuilderImpl::generateNodeImpl(Stmt* S, void* State,
|
|||
LastNode = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GRBranchNodeBuilderImpl::generateNodeImpl(void* State, bool branch) {
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNodeImpl* Succ =
|
||||
Eng.G->getNodeImpl(BlockEdge(Eng.getCFG(), Src, branch ? DstT : DstF),
|
||||
State, &IsNew);
|
||||
|
||||
Succ->addPredecessor(Pred);
|
||||
|
||||
if (IsNew)
|
||||
Eng.WList->Enqueue(GRWorkListUnit(Succ));
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace clang {
|
|||
class GREngineImpl;
|
||||
class ExplodedNodeImpl;
|
||||
class GRStmtNodeBuilderImpl;
|
||||
class GRBranchNodeBuilderImpl;
|
||||
class CFG;
|
||||
class ASTContext;
|
||||
class FunctionDecl;
|
||||
|
@ -39,6 +40,7 @@ protected:
|
|||
friend class ExplodedGraphImpl;
|
||||
friend class GREngineImpl;
|
||||
friend class GRStmtNodeBuilderImpl;
|
||||
friend class GRBranchNodeBuilderImpl;
|
||||
|
||||
class NodeGroup {
|
||||
enum { Size1 = 0x0, SizeOther = 0x1, Infeasible = 0x2, Flags = 0x3 };
|
||||
|
@ -193,6 +195,7 @@ class ExplodedGraphImpl {
|
|||
protected:
|
||||
friend class GREngineImpl;
|
||||
friend class GRStmtNodeBuilderImpl;
|
||||
friend class GRBranchNodeBuilderImpl;
|
||||
|
||||
// Type definitions.
|
||||
typedef llvm::DenseMap<ProgramPoint,void*> EdgeNodeSetMap;
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
namespace clang {
|
||||
|
||||
class GRStmtNodeBuilderImpl;
|
||||
class GRBranchNodeBuilderImpl;
|
||||
class GRWorkList;
|
||||
|
||||
class GREngineImpl {
|
||||
protected:
|
||||
friend class GRStmtNodeBuilderImpl;
|
||||
friend class GRBranchNodeBuilderImpl;
|
||||
|
||||
typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
|
||||
|
||||
|
@ -59,13 +61,17 @@ protected:
|
|||
void HandleBlockExit(CFGBlock* B, ExplodedNodeImpl* Pred);
|
||||
void HandlePostStmt(const PostStmt& S, CFGBlock* B,
|
||||
unsigned StmtIdx, ExplodedNodeImpl *Pred);
|
||||
|
||||
|
||||
void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B,
|
||||
ExplodedNodeImpl* Pred);
|
||||
|
||||
virtual void* ProcessEOP(CFGBlock* Blk, void* State) = 0;
|
||||
|
||||
virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& Builder) = 0;
|
||||
virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& Builder) = 0;
|
||||
|
||||
virtual void ProcessBranch(Stmt* Condition, Stmt* Terminator,
|
||||
GRBranchNodeBuilderImpl& Builder) = 0;
|
||||
|
||||
virtual void ProcessTerminator(Stmt* Terminator, CFGBlock* B,
|
||||
ExplodedNodeImpl* Pred) = 0;
|
||||
|
||||
private:
|
||||
GREngineImpl(const GREngineImpl&); // Do not implement.
|
||||
|
@ -154,6 +160,47 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class GRBranchNodeBuilderImpl {
|
||||
GREngineImpl& Eng;
|
||||
CFGBlock* Src;
|
||||
CFGBlock* DstT;
|
||||
CFGBlock* DstF;
|
||||
ExplodedNodeImpl* Pred;
|
||||
|
||||
public:
|
||||
GRBranchNodeBuilderImpl(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF,
|
||||
ExplodedNodeImpl* pred, GREngineImpl* e)
|
||||
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred) {}
|
||||
|
||||
~GRBranchNodeBuilderImpl() {}
|
||||
|
||||
const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
|
||||
|
||||
void generateNodeImpl(void* State, bool branch);
|
||||
};
|
||||
|
||||
template<typename CHECKER>
|
||||
class GRBranchNodeBuilder {
|
||||
typedef CHECKER CheckerTy;
|
||||
typedef typename CheckerTy::StateTy StateTy;
|
||||
typedef ExplodedGraph<CheckerTy> GraphTy;
|
||||
typedef typename GraphTy::NodeTy NodeTy;
|
||||
|
||||
GRBranchNodeBuilderImpl& NB;
|
||||
|
||||
public:
|
||||
GRBranchNodeBuilder(GRBranchNodeBuilderImpl& nb) : NB(nb) {}
|
||||
|
||||
const GraphTy& getGraph() const {
|
||||
return static_cast<const GraphTy&>(NB.getGraph());
|
||||
}
|
||||
|
||||
void generateNode(StateTy State, bool branch) {
|
||||
void *state = GRTrait<StateTy>::toPtr(State);
|
||||
NB.generateNodeImpl(state, branch);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename CHECKER>
|
||||
class GREngine : public GREngineImpl {
|
||||
|
@ -182,9 +229,11 @@ protected:
|
|||
Checker->ProcessStmt(S, Builder);
|
||||
}
|
||||
|
||||
virtual void ProcessTerminator(Stmt* Terminator, CFGBlock* B,
|
||||
ExplodedNodeImpl* Pred) {
|
||||
// FIXME: Dispatch.
|
||||
|
||||
virtual void ProcessBranch(Stmt* Condition, Stmt* Terminator,
|
||||
GRBranchNodeBuilderImpl& BuilderImpl) {
|
||||
GRBranchNodeBuilder<CHECKER> Builder(BuilderImpl);
|
||||
Checker->ProcessBranch(Condition, Terminator, Builder);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue