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. llvm-svn: 78298
This commit is contained in:
parent
130e2c7aed
commit
82003da8d3
|
@ -29,7 +29,7 @@
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
class GRState;
|
class GRState;
|
||||||
class GRCoreEngineImpl;
|
class GRCoreEngine;
|
||||||
class ExplodedNode;
|
class ExplodedNode;
|
||||||
class CFG;
|
class CFG;
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
|
@ -49,7 +49,7 @@ class GREndPathNodebuilderImpl;
|
||||||
class ExplodedNode : public llvm::FoldingSetNode {
|
class ExplodedNode : public llvm::FoldingSetNode {
|
||||||
protected:
|
protected:
|
||||||
friend class ExplodedGraph;
|
friend class ExplodedGraph;
|
||||||
friend class GRCoreEngineImpl;
|
friend class GRCoreEngine;
|
||||||
friend class GRStmtNodeBuilderImpl;
|
friend class GRStmtNodeBuilderImpl;
|
||||||
friend class GRBranchNodeBuilderImpl;
|
friend class GRBranchNodeBuilderImpl;
|
||||||
friend class GRIndirectGotoNodeBuilderImpl;
|
friend class GRIndirectGotoNodeBuilderImpl;
|
||||||
|
@ -206,7 +206,7 @@ public:
|
||||||
|
|
||||||
class ExplodedGraph {
|
class ExplodedGraph {
|
||||||
protected:
|
protected:
|
||||||
friend class GRCoreEngineImpl;
|
friend class GRCoreEngine;
|
||||||
friend class GRStmtNodeBuilderImpl;
|
friend class GRStmtNodeBuilderImpl;
|
||||||
friend class GRBranchNodeBuilderImpl;
|
friend class GRBranchNodeBuilderImpl;
|
||||||
friend class GRIndirectGotoNodeBuilderImpl;
|
friend class GRIndirectGotoNodeBuilderImpl;
|
||||||
|
|
|
@ -20,34 +20,52 @@
|
||||||
#include "clang/Analysis/PathSensitive/GRWorkList.h"
|
#include "clang/Analysis/PathSensitive/GRWorkList.h"
|
||||||
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
|
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
|
||||||
#include "clang/Analysis/PathSensitive/GRAuditor.h"
|
#include "clang/Analysis/PathSensitive/GRAuditor.h"
|
||||||
|
#include "clang/Analysis/PathSensitive/GRSubEngine.h"
|
||||||
#include "llvm/ADT/OwningPtr.h"
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
|
|
||||||
namespace clang {
|
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.
|
/// analysis. It traverses the CFG and generates the ExplodedGraph.
|
||||||
/// Program "states" are treated as opaque void pointers.
|
/// 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
|
/// provides the matching component to the engine that knows the actual types
|
||||||
/// for states. Note that this engine only dispatches to transfer functions
|
/// for states. Note that this engine only dispatches to transfer functions
|
||||||
/// at the statement and block-level. The analyses themselves must implement
|
/// at the statement and block-level. The analyses themselves must implement
|
||||||
/// any transfer function logic and the sub-expression level (if any).
|
/// any transfer function logic and the sub-expression level (if any).
|
||||||
class GRCoreEngineImpl {
|
class GRCoreEngine {
|
||||||
protected:
|
public:
|
||||||
|
typedef GRState StateTy;
|
||||||
|
typedef GRStateManager StateManagerTy;
|
||||||
|
typedef ExplodedGraph GraphTy;
|
||||||
|
typedef GraphTy::NodeTy NodeTy;
|
||||||
|
|
||||||
|
private:
|
||||||
friend class GRStmtNodeBuilderImpl;
|
friend class GRStmtNodeBuilderImpl;
|
||||||
friend class GRBranchNodeBuilderImpl;
|
friend class GRBranchNodeBuilderImpl;
|
||||||
friend class GRIndirectGotoNodeBuilderImpl;
|
friend class GRIndirectGotoNodeBuilderImpl;
|
||||||
friend class GRSwitchNodeBuilderImpl;
|
friend class GRSwitchNodeBuilderImpl;
|
||||||
friend class GREndPathNodeBuilderImpl;
|
friend class GREndPathNodeBuilderImpl;
|
||||||
|
|
||||||
|
GRSubEngine& SubEngine;
|
||||||
|
|
||||||
/// G - The simulation graph. Each node is a (location,state) pair.
|
/// G - The simulation graph. Each node is a (location,state) pair.
|
||||||
llvm::OwningPtr<ExplodedGraph> G;
|
llvm::OwningPtr<ExplodedGraph> G;
|
||||||
|
|
||||||
|
@ -64,12 +82,6 @@ protected:
|
||||||
void GenerateNode(const ProgramPoint& Loc, const GRState* State,
|
void GenerateNode(const ProgramPoint& Loc, const GRState* State,
|
||||||
ExplodedNode* Pred);
|
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 HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
|
||||||
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
|
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
|
||||||
void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred);
|
void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred);
|
||||||
|
@ -78,41 +90,70 @@ protected:
|
||||||
|
|
||||||
void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B,
|
void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B,
|
||||||
ExplodedNode* Pred);
|
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,
|
void ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl);
|
||||||
GRBranchNodeBuilderImpl& Builder) = 0;
|
|
||||||
|
|
||||||
virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0;
|
|
||||||
|
|
||||||
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:
|
private:
|
||||||
GRCoreEngineImpl(const GRCoreEngineImpl&); // Do not implement.
|
GRCoreEngine(const GRCoreEngine&); // Do not implement.
|
||||||
GRCoreEngineImpl& operator=(const GRCoreEngineImpl&);
|
GRCoreEngine& operator=(const GRCoreEngine&);
|
||||||
|
|
||||||
protected:
|
|
||||||
GRCoreEngineImpl(ExplodedGraph* g, GRWorkList* wl)
|
|
||||||
: G(g), WList(wl), BCounterFactory(g->getAllocator()) {}
|
|
||||||
|
|
||||||
public:
|
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
|
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
|
||||||
/// steps. Returns true if there is still simulation state on the worklist.
|
/// steps. Returns true if there is still simulation state on the worklist.
|
||||||
bool ExecuteWorkList(unsigned Steps);
|
bool ExecuteWorkList(unsigned Steps);
|
||||||
|
|
||||||
virtual ~GRCoreEngineImpl();
|
|
||||||
|
|
||||||
CFG& getCFG() { return G->getCFG(); }
|
CFG& getCFG() { return G->getCFG(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class GRStmtNodeBuilderImpl {
|
class GRStmtNodeBuilderImpl {
|
||||||
GRCoreEngineImpl& Eng;
|
GRCoreEngine& Eng;
|
||||||
CFGBlock& B;
|
CFGBlock& B;
|
||||||
const unsigned Idx;
|
const unsigned Idx;
|
||||||
ExplodedNode* Pred;
|
ExplodedNode* Pred;
|
||||||
|
@ -125,7 +166,7 @@ class GRStmtNodeBuilderImpl {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
|
GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
|
||||||
ExplodedNode* N, GRCoreEngineImpl* e);
|
ExplodedNode* N, GRCoreEngine* e);
|
||||||
|
|
||||||
~GRStmtNodeBuilderImpl();
|
~GRStmtNodeBuilderImpl();
|
||||||
|
|
||||||
|
@ -301,7 +342,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class GRBranchNodeBuilderImpl {
|
class GRBranchNodeBuilderImpl {
|
||||||
GRCoreEngineImpl& Eng;
|
GRCoreEngine& Eng;
|
||||||
CFGBlock* Src;
|
CFGBlock* Src;
|
||||||
CFGBlock* DstT;
|
CFGBlock* DstT;
|
||||||
CFGBlock* DstF;
|
CFGBlock* DstF;
|
||||||
|
@ -317,7 +358,7 @@ class GRBranchNodeBuilderImpl {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GRBranchNodeBuilderImpl(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF,
|
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),
|
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
|
||||||
GeneratedTrue(false), GeneratedFalse(false),
|
GeneratedTrue(false), GeneratedFalse(false),
|
||||||
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
|
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
|
||||||
|
@ -391,7 +432,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class GRIndirectGotoNodeBuilderImpl {
|
class GRIndirectGotoNodeBuilderImpl {
|
||||||
GRCoreEngineImpl& Eng;
|
GRCoreEngine& Eng;
|
||||||
CFGBlock* Src;
|
CFGBlock* Src;
|
||||||
CFGBlock& DispatchBlock;
|
CFGBlock& DispatchBlock;
|
||||||
Expr* E;
|
Expr* E;
|
||||||
|
@ -399,7 +440,7 @@ class GRIndirectGotoNodeBuilderImpl {
|
||||||
public:
|
public:
|
||||||
GRIndirectGotoNodeBuilderImpl(ExplodedNode* pred, CFGBlock* src,
|
GRIndirectGotoNodeBuilderImpl(ExplodedNode* pred, CFGBlock* src,
|
||||||
Expr* e, CFGBlock* dispatch,
|
Expr* e, CFGBlock* dispatch,
|
||||||
GRCoreEngineImpl* eng)
|
GRCoreEngine* eng)
|
||||||
: Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
|
: Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
|
||||||
|
|
||||||
|
|
||||||
|
@ -460,13 +501,13 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class GRSwitchNodeBuilderImpl {
|
class GRSwitchNodeBuilderImpl {
|
||||||
GRCoreEngineImpl& Eng;
|
GRCoreEngine& Eng;
|
||||||
CFGBlock* Src;
|
CFGBlock* Src;
|
||||||
Expr* Condition;
|
Expr* Condition;
|
||||||
ExplodedNode* Pred;
|
ExplodedNode* Pred;
|
||||||
public:
|
public:
|
||||||
GRSwitchNodeBuilderImpl(ExplodedNode* pred, CFGBlock* src,
|
GRSwitchNodeBuilderImpl(ExplodedNode* pred, CFGBlock* src,
|
||||||
Expr* condition, GRCoreEngineImpl* eng)
|
Expr* condition, GRCoreEngine* eng)
|
||||||
: Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
|
: Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
|
||||||
|
|
||||||
class Iterator {
|
class Iterator {
|
||||||
|
@ -534,14 +575,14 @@ public:
|
||||||
|
|
||||||
|
|
||||||
class GREndPathNodeBuilderImpl {
|
class GREndPathNodeBuilderImpl {
|
||||||
GRCoreEngineImpl& Eng;
|
GRCoreEngine& Eng;
|
||||||
CFGBlock& B;
|
CFGBlock& B;
|
||||||
ExplodedNode* Pred;
|
ExplodedNode* Pred;
|
||||||
bool HasGeneratedNode;
|
bool HasGeneratedNode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GREndPathNodeBuilderImpl(CFGBlock* b, ExplodedNode* N,
|
GREndPathNodeBuilderImpl(CFGBlock* b, ExplodedNode* N,
|
||||||
GRCoreEngineImpl* e)
|
GRCoreEngine* e)
|
||||||
: Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
|
: Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
|
||||||
|
|
||||||
~GREndPathNodeBuilderImpl();
|
~GREndPathNodeBuilderImpl();
|
||||||
|
@ -597,86 +638,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
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
|
} // end clang namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE
|
#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE
|
||||||
#define 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/GRCoreEngine.h"
|
||||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||||
#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
|
#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
|
||||||
|
@ -31,7 +32,7 @@ namespace clang {
|
||||||
class ObjCForCollectionStmt;
|
class ObjCForCollectionStmt;
|
||||||
class Checker;
|
class Checker;
|
||||||
|
|
||||||
class GRExprEngine {
|
class GRExprEngine : public GRSubEngine {
|
||||||
public:
|
public:
|
||||||
typedef GRState StateTy;
|
typedef GRState StateTy;
|
||||||
typedef ExplodedGraph GraphTy;
|
typedef ExplodedGraph GraphTy;
|
||||||
|
@ -46,7 +47,7 @@ public:
|
||||||
typedef ExplodedNodeSet NodeSet;
|
typedef ExplodedNodeSet NodeSet;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GRCoreEngine<GRExprEngine> CoreEngine;
|
GRCoreEngine CoreEngine;
|
||||||
|
|
||||||
/// G - the simulation graph.
|
/// G - the simulation graph.
|
||||||
GraphTy& G;
|
GraphTy& G;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
|
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
|
||||||
|
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
|
||||||
#include "clang/AST/Expr.h"
|
#include "clang/AST/Expr.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
|
@ -118,9 +119,38 @@ GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Core analysis engine.
|
// 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.
|
/// 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
|
if (G->num_roots() == 0) { // Initialize the analysis by constructing
|
||||||
// the root if none exists.
|
// the root if none exists.
|
||||||
|
@ -182,8 +212,8 @@ bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) {
|
||||||
return WList->hasWork();
|
return WList->hasWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L,
|
|
||||||
ExplodedNode* Pred) {
|
void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
|
||||||
|
|
||||||
CFGBlock* Blk = L.getDst();
|
CFGBlock* Blk = L.getDst();
|
||||||
|
|
||||||
|
@ -207,7 +237,7 @@ void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L,
|
||||||
GenerateNode(BlockEntrance(Blk), Pred->State, Pred);
|
GenerateNode(BlockEntrance(Blk), Pred->State, Pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRCoreEngineImpl::HandleBlockEntrance(const BlockEntrance& L,
|
void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
|
||||||
ExplodedNode* Pred) {
|
ExplodedNode* Pred) {
|
||||||
|
|
||||||
// Increment the block counter.
|
// Increment the block counter.
|
||||||
|
@ -224,11 +254,7 @@ void GRCoreEngineImpl::HandleBlockEntrance(const BlockEntrance& L,
|
||||||
HandleBlockExit(L.getBlock(), Pred);
|
HandleBlockExit(L.getBlock(), Pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRCoreEngineImpl::~GRCoreEngineImpl() {
|
void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
|
||||||
delete WList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GRCoreEngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
|
|
||||||
|
|
||||||
if (Stmt* Term = B->getTerminator()) {
|
if (Stmt* Term = B->getTerminator()) {
|
||||||
switch (Term->getStmtClass()) {
|
switch (Term->getStmtClass()) {
|
||||||
|
@ -316,8 +342,8 @@ void GRCoreEngineImpl::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
|
||||||
GenerateNode(BlockEdge(B, *(B->succ_begin())), Pred->State, Pred);
|
GenerateNode(BlockEdge(B, *(B->succ_begin())), Pred->State, Pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRCoreEngineImpl::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
|
void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
|
||||||
ExplodedNode* Pred) {
|
ExplodedNode* Pred) {
|
||||||
assert (B->succ_size() == 2);
|
assert (B->succ_size() == 2);
|
||||||
|
|
||||||
GRBranchNodeBuilderImpl Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
|
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);
|
ProcessBranch(Cond, Term, Builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B,
|
void GRCoreEngine::HandlePostStmt(const PostStmt& L, CFGBlock* B,
|
||||||
unsigned StmtIdx, ExplodedNode* Pred) {
|
unsigned StmtIdx, ExplodedNode* Pred) {
|
||||||
|
|
||||||
assert (!B->empty());
|
assert (!B->empty());
|
||||||
|
@ -341,8 +367,8 @@ void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B,
|
||||||
|
|
||||||
/// GenerateNode - Utility method to generate nodes, hook up successors,
|
/// GenerateNode - Utility method to generate nodes, hook up successors,
|
||||||
/// and add nodes to the worklist.
|
/// and add nodes to the worklist.
|
||||||
void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc,
|
void GRCoreEngine::GenerateNode(const ProgramPoint& Loc,
|
||||||
const GRState* State, ExplodedNode* Pred) {
|
const GRState* State, ExplodedNode* Pred) {
|
||||||
|
|
||||||
bool IsNew;
|
bool IsNew;
|
||||||
ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
|
ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
|
||||||
|
@ -359,7 +385,7 @@ void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc,
|
||||||
}
|
}
|
||||||
|
|
||||||
GRStmtNodeBuilderImpl::GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
|
GRStmtNodeBuilderImpl::GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
|
||||||
ExplodedNode* N, GRCoreEngineImpl* e)
|
ExplodedNode* N, GRCoreEngine* e)
|
||||||
: Eng(*e), B(*b), Idx(idx), Pred(N), LastNode(N) {
|
: Eng(*e), B(*b), Idx(idx), Pred(N), LastNode(N) {
|
||||||
Deferred.insert(N);
|
Deferred.insert(N);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue