Added boilerplate logic in GREngine for processing branches.

llvm-svn: 46532
This commit is contained in:
Ted Kremenek 2008-01-29 22:56:11 +00:00
parent b2cad31aae
commit 9b4211d25d
4 changed files with 116 additions and 14 deletions

View File

@ -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();

View File

@ -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));
}

View File

@ -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;

View File

@ -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);
}