diff --git a/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h index 9f11cc9a0af4..d5e3586a2439 100644 --- a/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -29,7 +29,7 @@ namespace clang { class GRState; -class GRCoreEngineImpl; +class GRCoreEngine; class ExplodedNode; class CFG; class ASTContext; @@ -49,7 +49,7 @@ class GREndPathNodebuilderImpl; class ExplodedNode : public llvm::FoldingSetNode { protected: friend class ExplodedGraph; - friend class GRCoreEngineImpl; + friend class GRCoreEngine; friend class GRStmtNodeBuilderImpl; friend class GRBranchNodeBuilderImpl; friend class GRIndirectGotoNodeBuilderImpl; @@ -206,7 +206,7 @@ public: class ExplodedGraph { protected: - friend class GRCoreEngineImpl; + friend class GRCoreEngine; friend class GRStmtNodeBuilderImpl; friend class GRBranchNodeBuilderImpl; friend class GRIndirectGotoNodeBuilderImpl; diff --git a/clang/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/clang/include/clang/Analysis/PathSensitive/GRCoreEngine.h index df49f9b91455..48613d1eb84b 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -20,34 +20,52 @@ #include "clang/Analysis/PathSensitive/GRWorkList.h" #include "clang/Analysis/PathSensitive/GRBlockCounter.h" #include "clang/Analysis/PathSensitive/GRAuditor.h" +#include "clang/Analysis/PathSensitive/GRSubEngine.h" #include "llvm/ADT/OwningPtr.h" namespace clang { - -class GRStmtNodeBuilderImpl; -class GRBranchNodeBuilderImpl; -class GRIndirectGotoNodeBuilderImpl; -class GRSwitchNodeBuilderImpl; -class GREndPathNodeBuilderImpl; -class GRWorkList; +class GRState; +class GRStateManager; + +class GRStmtNodeBuilderImpl; +template class GRStmtNodeBuilder; +class GRBranchNodeBuilderImpl; +template class GRBranchNodeBuilder; +class GRIndirectGotoNodeBuilderImpl; +template class GRIndirectGotoNodeBuilder; +class GRSwitchNodeBuilderImpl; +template class GRSwitchNodeBuilder; +class GREndPathNodeBuilderImpl; +template class GREndPathNodeBuilder; + +class GRWorkList; +class GRCoreEngine; //===----------------------------------------------------------------------===// -/// GRCoreEngineImpl - Implements the core logic of the graph-reachability +/// GRCoreEngine - Implements the core logic of the graph-reachability /// analysis. It traverses the CFG and generates the ExplodedGraph. /// Program "states" are treated as opaque void pointers. -/// The template class GRCoreEngine (which subclasses GRCoreEngineImpl) +/// The template class GRCoreEngine (which subclasses GRCoreEngine) /// provides the matching component to the engine that knows the actual types /// for states. Note that this engine only dispatches to transfer functions /// at the statement and block-level. The analyses themselves must implement /// any transfer function logic and the sub-expression level (if any). -class GRCoreEngineImpl { -protected: +class GRCoreEngine { +public: + typedef GRState StateTy; + typedef GRStateManager StateManagerTy; + typedef ExplodedGraph GraphTy; + typedef GraphTy::NodeTy NodeTy; + +private: friend class GRStmtNodeBuilderImpl; friend class GRBranchNodeBuilderImpl; friend class GRIndirectGotoNodeBuilderImpl; friend class GRSwitchNodeBuilderImpl; friend class GREndPathNodeBuilderImpl; - + + GRSubEngine& SubEngine; + /// G - The simulation graph. Each node is a (location,state) pair. llvm::OwningPtr G; @@ -64,12 +82,6 @@ protected: void GenerateNode(const ProgramPoint& Loc, const GRState* State, ExplodedNode* Pred); - /// getInitialState - Gets the void* representing the initial 'state' - /// of the analysis. This is simply a wrapper (implemented - /// in GRCoreEngine) that performs type erasure on the initial - /// state returned by the checker object. - virtual const GRState* getInitialState() = 0; - void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred); void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred); void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred); @@ -78,41 +90,70 @@ protected: void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B, ExplodedNode* Pred); - - virtual void ProcessEndPath(GREndPathNodeBuilderImpl& Builder) = 0; - - virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State, - GRBlockCounter BC) = 0; - virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& Builder) = 0; + /// Get the initial state from the subengine. + const GRState* getInitialState() { + return SubEngine.getInitialState(); + } - virtual void ProcessBranch(Stmt* Condition, Stmt* Terminator, - GRBranchNodeBuilderImpl& Builder) = 0; - - virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0; + void ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl); - virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& Builder) = 0; + void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl); + + + bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, + GRBlockCounter BC); + + + void ProcessBranch(Stmt* Condition, Stmt* Terminator, + GRBranchNodeBuilderImpl& BuilderImpl); + + + void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl); + + + void ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl); private: - GRCoreEngineImpl(const GRCoreEngineImpl&); // Do not implement. - GRCoreEngineImpl& operator=(const GRCoreEngineImpl&); - -protected: - GRCoreEngineImpl(ExplodedGraph* g, GRWorkList* wl) - : G(g), WList(wl), BCounterFactory(g->getAllocator()) {} + GRCoreEngine(const GRCoreEngine&); // Do not implement. + GRCoreEngine& operator=(const GRCoreEngine&); public: + /// Construct a GRCoreEngine object to analyze the provided CFG using + /// a DFS exploration of the exploded graph. + GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRSubEngine& subengine) + : SubEngine(subengine), G(new GraphTy(cfg, cd, ctx)), + WList(GRWorkList::MakeBFS()), + BCounterFactory(G->getAllocator()) {} + + /// Construct a GRCoreEngine object to analyze the provided CFG and to + /// use the provided worklist object to execute the worklist algorithm. + /// The GRCoreEngine object assumes ownership of 'wlist'. + GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRWorkList* wlist, + GRSubEngine& subengine) + : SubEngine(subengine), G(new GraphTy(cfg, cd, ctx)), WList(wlist), + BCounterFactory(G->getAllocator()) {} + + ~GRCoreEngine() { + delete WList; + } + + /// getGraph - Returns the exploded graph. + GraphTy& getGraph() { return *G.get(); } + + /// takeGraph - Returns the exploded graph. Ownership of the graph is + /// transfered to the caller. + GraphTy* takeGraph() { return G.take(); } + /// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// steps. Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(unsigned Steps); - virtual ~GRCoreEngineImpl(); - CFG& getCFG() { return G->getCFG(); } }; class GRStmtNodeBuilderImpl { - GRCoreEngineImpl& Eng; + GRCoreEngine& Eng; CFGBlock& B; const unsigned Idx; ExplodedNode* Pred; @@ -125,7 +166,7 @@ class GRStmtNodeBuilderImpl { public: GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx, - ExplodedNode* N, GRCoreEngineImpl* e); + ExplodedNode* N, GRCoreEngine* e); ~GRStmtNodeBuilderImpl(); @@ -301,7 +342,7 @@ public: }; class GRBranchNodeBuilderImpl { - GRCoreEngineImpl& Eng; + GRCoreEngine& Eng; CFGBlock* Src; CFGBlock* DstT; CFGBlock* DstF; @@ -317,7 +358,7 @@ class GRBranchNodeBuilderImpl { public: GRBranchNodeBuilderImpl(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF, - ExplodedNode* pred, GRCoreEngineImpl* e) + ExplodedNode* pred, GRCoreEngine* e) : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred), GeneratedTrue(false), GeneratedFalse(false), InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {} @@ -391,7 +432,7 @@ public: }; class GRIndirectGotoNodeBuilderImpl { - GRCoreEngineImpl& Eng; + GRCoreEngine& Eng; CFGBlock* Src; CFGBlock& DispatchBlock; Expr* E; @@ -399,7 +440,7 @@ class GRIndirectGotoNodeBuilderImpl { public: GRIndirectGotoNodeBuilderImpl(ExplodedNode* pred, CFGBlock* src, Expr* e, CFGBlock* dispatch, - GRCoreEngineImpl* eng) + GRCoreEngine* eng) : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} @@ -460,13 +501,13 @@ public: }; class GRSwitchNodeBuilderImpl { - GRCoreEngineImpl& Eng; + GRCoreEngine& Eng; CFGBlock* Src; Expr* Condition; ExplodedNode* Pred; public: GRSwitchNodeBuilderImpl(ExplodedNode* pred, CFGBlock* src, - Expr* condition, GRCoreEngineImpl* eng) + Expr* condition, GRCoreEngine* eng) : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} class Iterator { @@ -534,14 +575,14 @@ public: class GREndPathNodeBuilderImpl { - GRCoreEngineImpl& Eng; + GRCoreEngine& Eng; CFGBlock& B; ExplodedNode* Pred; bool HasGeneratedNode; public: GREndPathNodeBuilderImpl(CFGBlock* b, ExplodedNode* N, - GRCoreEngineImpl* e) + GRCoreEngine* e) : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {} ~GREndPathNodeBuilderImpl(); @@ -597,86 +638,6 @@ public: } }; - -template -class GRCoreEngine : public GRCoreEngineImpl { -public: - typedef SUBENGINE SubEngineTy; - typedef typename SubEngineTy::StateTy StateTy; - typedef typename StateTy::ManagerTy StateManagerTy; - typedef ExplodedGraph GraphTy; - typedef typename GraphTy::NodeTy NodeTy; - -protected: - SubEngineTy& SubEngine; - - virtual const GRState* getInitialState() { - return SubEngine.getInitialState(); - } - - virtual void ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl) { - GREndPathNodeBuilder Builder(BuilderImpl); - SubEngine.ProcessEndPath(Builder); - } - - virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) { - GRStmtNodeBuilder Builder(BuilderImpl,SubEngine.getStateManager()); - SubEngine.ProcessStmt(S, Builder); - } - - virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State, - GRBlockCounter BC) { - return SubEngine.ProcessBlockEntrance(Blk, - static_cast(State), - BC); - } - - virtual void ProcessBranch(Stmt* Condition, Stmt* Terminator, - GRBranchNodeBuilderImpl& BuilderImpl) { - GRBranchNodeBuilder Builder(BuilderImpl); - SubEngine.ProcessBranch(Condition, Terminator, Builder); - } - - virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) { - GRIndirectGotoNodeBuilder Builder(BuilderImpl); - SubEngine.ProcessIndirectGoto(Builder); - } - - virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl) { - GRSwitchNodeBuilder Builder(BuilderImpl); - SubEngine.ProcessSwitch(Builder); - } - -public: - /// Construct a GRCoreEngine object to analyze the provided CFG using - /// a DFS exploration of the exploded graph. - GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, SubEngineTy& subengine) - : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), - GRWorkList::MakeBFS()), - SubEngine(subengine) {} - - /// Construct a GRCoreEngine object to analyze the provided CFG and to - /// use the provided worklist object to execute the worklist algorithm. - /// The GRCoreEngine object assumes ownership of 'wlist'. - GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRWorkList* wlist, - SubEngineTy& subengine) - : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), wlist), - SubEngine(subengine) {} - - virtual ~GRCoreEngine() {} - - /// getGraph - Returns the exploded graph. - GraphTy& getGraph() { - return *static_cast(G.get()); - } - - /// takeGraph - Returns the exploded graph. Ownership of the graph is - /// transfered to the caller. - GraphTy* takeGraph() { - return static_cast(G.take()); - } -}; - } // end clang namespace #endif diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index d3a50b0d363b..12c63525f310 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE #define LLVM_CLANG_ANALYSIS_GREXPRENGINE +#include "clang/Analysis/PathSensitive/GRSubEngine.h" #include "clang/Analysis/PathSensitive/GRCoreEngine.h" #include "clang/Analysis/PathSensitive/GRState.h" #include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h" @@ -31,7 +32,7 @@ namespace clang { class ObjCForCollectionStmt; class Checker; -class GRExprEngine { +class GRExprEngine : public GRSubEngine { public: typedef GRState StateTy; typedef ExplodedGraph GraphTy; @@ -46,7 +47,7 @@ public: typedef ExplodedNodeSet NodeSet; protected: - GRCoreEngine CoreEngine; + GRCoreEngine CoreEngine; /// G - the simulation graph. GraphTy& G; diff --git a/clang/lib/Analysis/GRCoreEngine.cpp b/clang/lib/Analysis/GRCoreEngine.cpp index 492b4fe336ff..4f0179ab59cc 100644 --- a/clang/lib/Analysis/GRCoreEngine.cpp +++ b/clang/lib/Analysis/GRCoreEngine.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/PathSensitive/GRCoreEngine.h" +#include "clang/Analysis/PathSensitive/GRExprEngine.h" #include "clang/AST/Expr.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Casting.h" @@ -118,9 +119,38 @@ GRWorkList* GRWorkList::MakeBFSBlockDFSContents() { //===----------------------------------------------------------------------===// // Core analysis engine. //===----------------------------------------------------------------------===// +void GRCoreEngine::ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl) { + GREndPathNodeBuilder Builder(BuilderImpl); + SubEngine.ProcessEndPath(Builder); +} +void GRCoreEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) { + GRStmtNodeBuilder Builder(BuilderImpl,SubEngine.getStateManager()); + SubEngine.ProcessStmt(S, Builder); +} + +bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, + GRBlockCounter BC) { + return SubEngine.ProcessBlockEntrance(Blk, State, BC); +} + +void GRCoreEngine::ProcessBranch(Stmt* Condition, Stmt* Terminator, + GRBranchNodeBuilderImpl& BuilderImpl) { + GRBranchNodeBuilder Builder(BuilderImpl); + SubEngine.ProcessBranch(Condition, Terminator, Builder); +} + +void GRCoreEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) { + GRIndirectGotoNodeBuilder Builder(BuilderImpl); + SubEngine.ProcessIndirectGoto(Builder); +} + +void GRCoreEngine::ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl) { + GRSwitchNodeBuilder Builder(BuilderImpl); + SubEngine.ProcessSwitch(Builder); +} /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps. -bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) { +bool GRCoreEngine::ExecuteWorkList(unsigned Steps) { if (G->num_roots() == 0) { // Initialize the analysis by constructing // the root if none exists. @@ -182,8 +212,8 @@ bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) { return WList->hasWork(); } -void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L, - ExplodedNode* Pred) { + +void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) { CFGBlock* Blk = L.getDst(); @@ -207,7 +237,7 @@ void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L, GenerateNode(BlockEntrance(Blk), Pred->State, Pred); } -void GRCoreEngineImpl::HandleBlockEntrance(const BlockEntrance& L, +void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L, ExplodedNode* Pred) { // Increment the block counter. @@ -224,11 +254,7 @@ void GRCoreEngineImpl::HandleBlockEntrance(const BlockEntrance& L, HandleBlockExit(L.getBlock(), Pred); } -GRCoreEngineImpl::~GRCoreEngineImpl() { - delete WList; -} - -void GRCoreEngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) { +void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) { if (Stmt* Term = B->getTerminator()) { switch (Term->getStmtClass()) { @@ -316,8 +342,8 @@ void GRCoreEngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) { GenerateNode(BlockEdge(B, *(B->succ_begin())), Pred->State, Pred); } -void GRCoreEngineImpl::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B, - ExplodedNode* Pred) { +void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B, + ExplodedNode* Pred) { assert (B->succ_size() == 2); GRBranchNodeBuilderImpl Builder(B, *(B->succ_begin()), *(B->succ_begin()+1), @@ -326,7 +352,7 @@ void GRCoreEngineImpl::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B, ProcessBranch(Cond, Term, Builder); } -void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B, +void GRCoreEngine::HandlePostStmt(const PostStmt& L, CFGBlock* B, unsigned StmtIdx, ExplodedNode* Pred) { assert (!B->empty()); @@ -341,8 +367,8 @@ void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B, /// GenerateNode - Utility method to generate nodes, hook up successors, /// and add nodes to the worklist. -void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc, - const GRState* State, ExplodedNode* Pred) { +void GRCoreEngine::GenerateNode(const ProgramPoint& Loc, + const GRState* State, ExplodedNode* Pred) { bool IsNew; ExplodedNode* Node = G->getNode(Loc, State, &IsNew); @@ -359,7 +385,7 @@ void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc, } GRStmtNodeBuilderImpl::GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx, - ExplodedNode* N, GRCoreEngineImpl* e) + ExplodedNode* N, GRCoreEngine* e) : Eng(*e), B(*b), Idx(idx), Pred(N), LastNode(N) { Deferred.insert(N); }