Core analysis engine template cleanup step 2:
merge GRCoreEngineImpl and GRCoreEngine.
Introduce a new interface class GRSubEngine as the subengine of GRCoreEngine.
GRExprEngine subclasses GRSubEngine now.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78298 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
index 9f11cc9..d5e3586 100644
--- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h
+++ b/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 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 @@
class ExplodedGraph {
protected:
- friend class GRCoreEngineImpl;
+ friend class GRCoreEngine;
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
friend class GRIndirectGotoNodeBuilderImpl;
diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
index df49f9b..48613d1 100644
--- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h
+++ b/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<typename STATE> class GRStmtNodeBuilder;
+class GRBranchNodeBuilderImpl;
+template<typename STATE> class GRBranchNodeBuilder;
+class GRIndirectGotoNodeBuilderImpl;
+template<typename STATE> class GRIndirectGotoNodeBuilder;
+class GRSwitchNodeBuilderImpl;
+template<typename STATE> class GRSwitchNodeBuilder;
+class GREndPathNodeBuilderImpl;
+template<typename STATE> 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<ExplodedGraph> G;
@@ -64,12 +82,6 @@
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 @@
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 @@
public:
GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
- ExplodedNode* N, GRCoreEngineImpl* e);
+ ExplodedNode* N, GRCoreEngine* e);
~GRStmtNodeBuilderImpl();
@@ -301,7 +342,7 @@
};
class GRBranchNodeBuilderImpl {
- GRCoreEngineImpl& Eng;
+ GRCoreEngine& Eng;
CFGBlock* Src;
CFGBlock* DstT;
CFGBlock* DstF;
@@ -317,7 +358,7 @@
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 @@
};
class GRIndirectGotoNodeBuilderImpl {
- GRCoreEngineImpl& Eng;
+ GRCoreEngine& Eng;
CFGBlock* Src;
CFGBlock& DispatchBlock;
Expr* E;
@@ -399,7 +440,7 @@
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 @@
};
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 @@
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 @@
}
};
-
-template<typename SUBENGINE>
-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<StateTy> Builder(BuilderImpl);
- SubEngine.ProcessEndPath(Builder);
- }
-
- virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) {
- GRStmtNodeBuilder<StateTy> Builder(BuilderImpl,SubEngine.getStateManager());
- SubEngine.ProcessStmt(S, Builder);
- }
-
- virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State,
- GRBlockCounter BC) {
- return SubEngine.ProcessBlockEntrance(Blk,
- static_cast<const StateTy*>(State),
- BC);
- }
-
- virtual void ProcessBranch(Stmt* Condition, Stmt* Terminator,
- GRBranchNodeBuilderImpl& BuilderImpl) {
- GRBranchNodeBuilder<StateTy> Builder(BuilderImpl);
- SubEngine.ProcessBranch(Condition, Terminator, Builder);
- }
-
- virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
- GRIndirectGotoNodeBuilder<StateTy> Builder(BuilderImpl);
- SubEngine.ProcessIndirectGoto(Builder);
- }
-
- virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl) {
- GRSwitchNodeBuilder<StateTy> 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<GraphTy*>(G.get());
- }
-
- /// takeGraph - Returns the exploded graph. Ownership of the graph is
- /// transfered to the caller.
- GraphTy* takeGraph() {
- return static_cast<GraphTy*>(G.take());
- }
-};
-
} // end clang namespace
#endif
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index d3a50b0..12c6352 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/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 @@
class ObjCForCollectionStmt;
class Checker;
-class GRExprEngine {
+class GRExprEngine : public GRSubEngine {
public:
typedef GRState StateTy;
typedef ExplodedGraph GraphTy;
@@ -46,7 +47,7 @@
typedef ExplodedNodeSet NodeSet;
protected:
- GRCoreEngine<GRExprEngine> CoreEngine;
+ GRCoreEngine CoreEngine;
/// G - the simulation graph.
GraphTy& G;
diff --git a/lib/Analysis/GRCoreEngine.cpp b/lib/Analysis/GRCoreEngine.cpp
index 492b4fe..4f0179a 100644
--- a/lib/Analysis/GRCoreEngine.cpp
+++ b/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 @@
//===----------------------------------------------------------------------===//
// Core analysis engine.
//===----------------------------------------------------------------------===//
+void GRCoreEngine::ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl) {
+ GREndPathNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessEndPath(Builder);
+}
+void GRCoreEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) {
+ GRStmtNodeBuilder<StateTy> 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<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessBranch(Condition, Terminator, Builder);
+}
+
+void GRCoreEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
+ GRIndirectGotoNodeBuilder<GRState> Builder(BuilderImpl);
+ SubEngine.ProcessIndirectGoto(Builder);
+}
+
+void GRCoreEngine::ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl) {
+ GRSwitchNodeBuilder<GRState> 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/// 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 @@
}
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);
}