From: Ted Kremenek Date: Tue, 29 Jan 2008 22:56:11 +0000 (+0000) Subject: Added boilerplate logic in GREngine for processing branches. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7d7fe6d539b3bdb1701835223cca306c325614a7;p=clang Added boilerplate logic in GREngine for processing branches. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46532 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp index 6d89b29b61..2c6c7f7844 100644 --- a/Analysis/GRConstants.cpp +++ b/Analysis/GRConstants.cpp @@ -730,7 +730,8 @@ class VISIBILITY_HIDDEN GRConstants { public: typedef ValueMapTy StateTy; - typedef GRStmtNodeBuilder NodeBuilder; + typedef GRStmtNodeBuilder StmtNodeBuilder; + typedef GRBranchNodeBuilder BranchNodeBuilder; typedef ExplodedGraph 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(); diff --git a/Analysis/GREngine.cpp b/Analysis/GREngine.cpp index 6aaf0d89e1..35101a9dea 100644 --- a/Analysis/GREngine.cpp +++ b/Analysis/GREngine.cpp @@ -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(Term)->getCond(), Term, B, Pred); + break; + + case Stmt::ForStmtClass: + HandleBranch(cast(Term)->getCond(), Term, B, Pred); + break; + + case Stmt::WhileStmtClass: + HandleBranch(cast(Term)->getCond(), Term, B, Pred); + break; + + case Stmt::DoStmtClass: + HandleBranch(cast(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)); +} diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index a7f6c3c005..dc96c1c5a4 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -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 EdgeNodeSetMap; diff --git a/include/clang/Analysis/PathSensitive/GREngine.h b/include/clang/Analysis/PathSensitive/GREngine.h index e783d8e7d0..c3a9e209b8 100644 --- a/include/clang/Analysis/PathSensitive/GREngine.h +++ b/include/clang/Analysis/PathSensitive/GREngine.h @@ -22,11 +22,13 @@ namespace clang { class GRStmtNodeBuilderImpl; +class GRBranchNodeBuilderImpl; class GRWorkList; class GREngineImpl { protected: friend class GRStmtNodeBuilderImpl; + friend class GRBranchNodeBuilderImpl; typedef llvm::DenseMap 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 +class GRBranchNodeBuilder { + typedef CHECKER CheckerTy; + typedef typename CheckerTy::StateTy StateTy; + typedef ExplodedGraph GraphTy; + typedef typename GraphTy::NodeTy NodeTy; + + GRBranchNodeBuilderImpl& NB; + +public: + GRBranchNodeBuilder(GRBranchNodeBuilderImpl& nb) : NB(nb) {} + + const GraphTy& getGraph() const { + return static_cast(NB.getGraph()); + } + + void generateNode(StateTy State, bool branch) { + void *state = GRTrait::toPtr(State); + NB.generateNodeImpl(state, branch); + } +}; + template 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 Builder(BuilderImpl); + Checker->ProcessBranch(Condition, Terminator, Builder); }