From: Ted Kremenek Date: Fri, 11 Apr 2008 22:03:04 +0000 (+0000) Subject: Added "GREndPathNodeBuilder", a new node builder that will be used for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=11062b118476368fa5b294954713e5df97d8599f;p=clang Added "GREndPathNodeBuilder", a new node builder that will be used for evaluating transfer functions at the end-of-path. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49561 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index 8db069639b..0d8f31fb82 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -30,12 +30,14 @@ namespace clang { class GRCoreEngineImpl; class ExplodedNodeImpl; +class CFG; +class ASTContext; + class GRStmtNodeBuilderImpl; class GRBranchNodeBuilderImpl; class GRIndirectGotoNodeBuilderImpl; class GRSwitchNodeBuilderImpl; -class CFG; -class ASTContext; +class GREndPathNodebuilderImpl; class ExplodedNodeImpl : public llvm::FoldingSetNode { protected: @@ -45,6 +47,7 @@ protected: friend class GRBranchNodeBuilderImpl; friend class GRIndirectGotoNodeBuilderImpl; friend class GRSwitchNodeBuilderImpl; + friend class GREndPathNodeBuilderImpl; class NodeGroup { enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 }; @@ -199,6 +202,7 @@ protected: friend class GRBranchNodeBuilderImpl; friend class GRIndirectGotoNodeBuilderImpl; friend class GRSwitchNodeBuilderImpl; + friend class GREndPathNodeBuilderImpl; // Type definitions. typedef llvm::SmallVector RootsTy; diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index 5b7aeb5975..ccb217ca0a 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -28,6 +28,7 @@ class GRStmtNodeBuilderImpl; class GRBranchNodeBuilderImpl; class GRIndirectGotoNodeBuilderImpl; class GRSwitchNodeBuilderImpl; +class GREndPathNodeBuilderImpl; class GRWorkList; //===----------------------------------------------------------------------===// @@ -45,6 +46,7 @@ protected: friend class GRBranchNodeBuilderImpl; friend class GRIndirectGotoNodeBuilderImpl; friend class GRSwitchNodeBuilderImpl; + friend class GREndPathNodeBuilderImpl; typedef llvm::DenseMap ParentMapTy; @@ -86,7 +88,7 @@ protected: void HandleBranch(Expr* Cond, Stmt* Term, CFGBlock* B, ExplodedNodeImpl* Pred); - virtual void* ProcessEOP(CFGBlock* Blk, void* State) = 0; + virtual void ProcessEndPath(GREndPathNodeBuilderImpl& Builder) = 0; virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State, GRBlockCounter BC) = 0; @@ -487,6 +489,65 @@ public: return static_cast(NB.getState()); } }; + + +class GREndPathNodeBuilderImpl { + GRCoreEngineImpl& Eng; + CFGBlock& B; + ExplodedNodeImpl* Pred; + bool HasGeneratedNode; + +public: + GREndPathNodeBuilderImpl(CFGBlock* b, ExplodedNodeImpl* N, + GRCoreEngineImpl* e) + : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {} + + ~GREndPathNodeBuilderImpl(); + + ExplodedNodeImpl* getPredecessor() const { return Pred; } + + GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} + + unsigned getCurrentBlockCount() const { + return getBlockCounter().getNumVisited(B.getBlockID()); + } + + ExplodedNodeImpl* generateNodeImpl(void* State); + + CFGBlock* getBlock() const { return &B; } +}; + + +template +class GREndPathNodeBuilder { + typedef STATE StateTy; + typedef ExplodedNode NodeTy; + + GREndPathNodeBuilderImpl& NB; + +public: + GREndPathNodeBuilder(GREndPathNodeBuilderImpl& nb) : NB(nb) {} + + NodeTy* getPredecessor() const { + return static_cast(NB.getPredecessor()); + } + + GRBlockCounter getBlockCounter() const { + return NB.getBlockCounter(); + } + + unsigned getCurrentBlockCount() const { + return NB.getCurrentBlockCount(); + } + + StateTy* getState() const { + return getPredecessor()->getState(); + } + + NodeTy* MakeNode(StateTy* St) { + return static_cast(NB.generateNodeImpl(St)); + } +}; template @@ -504,9 +565,9 @@ protected: return SubEngine.getInitialState(); } - virtual void* ProcessEOP(CFGBlock* Blk, void* State) { - // FIXME: Perform dispatch to adjust state. - return State; + virtual void ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl) { + GREndPathNodeBuilder Builder(BuilderImpl); + SubEngine.ProcessEndPath(Builder); } virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) { diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 473b658b67..1c813dfd89 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -39,6 +39,7 @@ public: typedef GRBranchNodeBuilder BranchNodeBuilder; typedef GRIndirectGotoNodeBuilder IndirectGotoNodeBuilder; typedef GRSwitchNodeBuilder SwitchNodeBuilder; + typedef GREndPathNodeBuilder EndPathNodeBuilder; typedef ExplodedNodeSet NodeSet; @@ -364,6 +365,9 @@ public: /// nodes by processing the 'effects' of a switch statement. void ProcessSwitch(SwitchNodeBuilder& builder); + /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path + /// nodes when the control reaches the end of a function. + void ProcessEndPath(EndPathNodeBuilder& builder) {} ValueStateManager& getStateManager() { return StateMgr; } const ValueStateManager& getStateManger() const { return StateMgr; } diff --git a/lib/Analysis/GRCoreEngine.cpp b/lib/Analysis/GRCoreEngine.cpp index 53831ed06d..42c89270f9 100644 --- a/lib/Analysis/GRCoreEngine.cpp +++ b/lib/Analysis/GRCoreEngine.cpp @@ -124,16 +124,10 @@ void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L, assert (getCFG().getExit().size() == 0 && "EXIT block cannot contain Stmts."); - // Process the final state transition. - void* State = ProcessEOP(Blk, Pred->State); + // Process the final state transition. + GREndPathNodeBuilderImpl Builder(Blk, Pred, this); + ProcessEndPath(Builder); - bool IsNew; - ExplodedNodeImpl* Node = G->getNodeImpl(BlockEntrance(Blk), State, &IsNew); - Node->addPredecessor(Pred); - - // If the node was freshly created, mark it as an "End-Of-Path" node. - if (IsNew) G->addEndOfPath(Node); - // This path is done. Don't enqueue any more nodes. return; } @@ -442,3 +436,27 @@ GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(void* St, bool isSink) { return NULL; } + +GREndPathNodeBuilderImpl::~GREndPathNodeBuilderImpl() { + // Auto-generate an EOP node if one has not been generated. + if (!HasGeneratedNode) generateNodeImpl(Pred->State); +} + +ExplodedNodeImpl* GREndPathNodeBuilderImpl::generateNodeImpl(void* State) { + HasGeneratedNode = true; + + bool IsNew; + + ExplodedNodeImpl* Node = + Eng.G->getNodeImpl(BlockEntrance(&B), Pred->State, &IsNew); + + + Node->addPredecessor(Pred); + + if (IsNew) { + Node->markAsSink(); + Eng.G->addEndOfPath(Node); + } + + return Node; +}