mirror of
https://github.com/intel/llvm.git
synced 2026-02-04 20:00:11 +08:00
Core analysis engine template cleanup step 2:
merge ExplodedGraphImpl and ExplodedGraph. llvm-svn: 78291
This commit is contained in:
@@ -358,15 +358,15 @@ public:
|
||||
|
||||
/// getEngine - Return the analysis engine used to analyze a given
|
||||
/// function or method.
|
||||
GRExprEngine& getEngine() { return Eng; }
|
||||
GRExprEngine &getEngine() { return Eng; }
|
||||
|
||||
/// getGraph - Get the exploded graph created by the analysis engine
|
||||
/// for the analyzed method or function.
|
||||
ExplodedGraph<GRState>& getGraph();
|
||||
ExplodedGraph &getGraph();
|
||||
|
||||
/// getStateManager - Return the state manager used by the analysis
|
||||
/// engine.
|
||||
GRStateManager& getStateManager();
|
||||
GRStateManager &getStateManager();
|
||||
|
||||
virtual void GeneratePathDiagnostic(PathDiagnostic& PD,
|
||||
BugReportEquivClass& R);
|
||||
@@ -402,7 +402,7 @@ public:
|
||||
|
||||
GRBugReporter& getBugReporter() { return BR; }
|
||||
|
||||
ExplodedGraph<GRState>& getGraph() { return BR.getGraph(); }
|
||||
ExplodedGraph &getGraph() { return BR.getGraph(); }
|
||||
|
||||
void addNotableSymbol(SymbolRef Sym) {
|
||||
// FIXME: For now forward to GRBugReporter.
|
||||
|
||||
@@ -48,7 +48,7 @@ class GREndPathNodebuilderImpl;
|
||||
|
||||
class ExplodedNode : public llvm::FoldingSetNode {
|
||||
protected:
|
||||
friend class ExplodedGraphImpl;
|
||||
friend class ExplodedGraph;
|
||||
friend class GRCoreEngineImpl;
|
||||
friend class GRStmtNodeBuilderImpl;
|
||||
friend class GRBranchNodeBuilderImpl;
|
||||
@@ -192,17 +192,19 @@ public:
|
||||
static void SetAuditor(Auditor* A);
|
||||
};
|
||||
|
||||
// FIXME: Is this class necessary?
|
||||
class InterExplodedGraphMap {
|
||||
llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M;
|
||||
friend class ExplodedGraph;
|
||||
|
||||
template <typename StateTy>
|
||||
struct GRTrait {
|
||||
static inline void Profile(llvm::FoldingSetNodeID& ID, const StateTy* St) {
|
||||
St->Profile(ID);
|
||||
}
|
||||
public:
|
||||
ExplodedNode* getMappedNode(const ExplodedNode* N) const;
|
||||
|
||||
InterExplodedGraphMap() {};
|
||||
virtual ~InterExplodedGraphMap() {}
|
||||
};
|
||||
|
||||
class InterExplodedGraphMapImpl;
|
||||
|
||||
class ExplodedGraphImpl {
|
||||
class ExplodedGraph {
|
||||
protected:
|
||||
friend class GRCoreEngineImpl;
|
||||
friend class GRStmtNodeBuilderImpl;
|
||||
@@ -224,7 +226,10 @@ protected:
|
||||
/// EndNodes - The nodes in the simulation graph which have been
|
||||
/// specially marked as the endpoint of an abstract simulation path.
|
||||
EndNodesTy EndNodes;
|
||||
|
||||
|
||||
/// Nodes - The nodes in the graph.
|
||||
llvm::FoldingSet<ExplodedNode> Nodes;
|
||||
|
||||
/// Allocator - BumpPtrAllocator to create nodes.
|
||||
llvm::BumpPtrAllocator Allocator;
|
||||
|
||||
@@ -241,14 +246,18 @@ protected:
|
||||
/// NumNodes - The number of nodes in the graph.
|
||||
unsigned NumNodes;
|
||||
|
||||
/// getNodeImpl - Retrieve the node associated with a (Location,State)
|
||||
/// pair, where 'State' is represented as an opaque void*. This method
|
||||
/// is intended to be used only by GRCoreEngineImpl.
|
||||
virtual ExplodedNode* getNodeImpl(const ProgramPoint& L,
|
||||
const void* State,
|
||||
bool* IsNew) = 0;
|
||||
public:
|
||||
/// getNode - Retrieve the node associated with a (Location,State) pair,
|
||||
/// where the 'Location' is a ProgramPoint in the CFG. If no node for
|
||||
/// this pair exists, it is created. IsNew is set to true if
|
||||
/// the node was freshly created.
|
||||
|
||||
ExplodedNode* getNode(const ProgramPoint& L, const GRState *State,
|
||||
bool* IsNew = 0);
|
||||
|
||||
virtual ExplodedGraphImpl* MakeEmptyGraph() const = 0;
|
||||
ExplodedGraph* MakeEmptyGraph() const {
|
||||
return new ExplodedGraph(cfg, CodeDecl, Ctx);
|
||||
}
|
||||
|
||||
/// addRoot - Add an untyped node to the set of roots.
|
||||
ExplodedNode* addRoot(ExplodedNode* V) {
|
||||
@@ -261,20 +270,52 @@ protected:
|
||||
EndNodes.push_back(V);
|
||||
return V;
|
||||
}
|
||||
|
||||
// ctor.
|
||||
ExplodedGraphImpl(CFG& c, Decl& cd, ASTContext& ctx)
|
||||
|
||||
ExplodedGraph(CFG& c, Decl& cd, ASTContext& ctx)
|
||||
: cfg(c), CodeDecl(cd), Ctx(ctx), NumNodes(0) {}
|
||||
|
||||
public:
|
||||
virtual ~ExplodedGraphImpl() {}
|
||||
virtual ~ExplodedGraph() {}
|
||||
|
||||
unsigned num_roots() const { return Roots.size(); }
|
||||
unsigned num_eops() const { return EndNodes.size(); }
|
||||
|
||||
bool empty() const { return NumNodes == 0; }
|
||||
unsigned size() const { return NumNodes; }
|
||||
|
||||
// Iterators.
|
||||
typedef ExplodedNode NodeTy;
|
||||
typedef llvm::FoldingSet<ExplodedNode> AllNodesTy;
|
||||
typedef NodeTy** roots_iterator;
|
||||
typedef NodeTy* const * const_roots_iterator;
|
||||
typedef NodeTy** eop_iterator;
|
||||
typedef NodeTy* const * const_eop_iterator;
|
||||
typedef AllNodesTy::iterator node_iterator;
|
||||
typedef AllNodesTy::const_iterator const_node_iterator;
|
||||
|
||||
node_iterator nodes_begin() { return Nodes.begin(); }
|
||||
|
||||
node_iterator nodes_end() { return Nodes.end(); }
|
||||
|
||||
const_node_iterator nodes_begin() const { return Nodes.begin(); }
|
||||
|
||||
const_node_iterator nodes_end() const { return Nodes.end(); }
|
||||
|
||||
roots_iterator roots_begin() { return Roots.begin(); }
|
||||
|
||||
roots_iterator roots_end() { return Roots.end(); }
|
||||
|
||||
const_roots_iterator roots_begin() const { return Roots.begin(); }
|
||||
|
||||
const_roots_iterator roots_end() const { return Roots.end(); }
|
||||
|
||||
eop_iterator eop_begin() { return EndNodes.begin(); }
|
||||
|
||||
eop_iterator eop_end() { return EndNodes.end(); }
|
||||
|
||||
const_eop_iterator eop_begin() const { return EndNodes.begin(); }
|
||||
|
||||
const_eop_iterator eop_end() const { return EndNodes.end(); }
|
||||
|
||||
llvm::BumpPtrAllocator& getAllocator() { return Allocator; }
|
||||
CFG& getCFG() { return cfg; }
|
||||
ASTContext& getContext() { return Ctx; }
|
||||
@@ -288,176 +329,14 @@ public:
|
||||
|
||||
typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
|
||||
|
||||
ExplodedGraphImpl* Trim(const ExplodedNode* const * NBeg,
|
||||
const ExplodedNode* const * NEnd,
|
||||
InterExplodedGraphMapImpl *M,
|
||||
llvm::DenseMap<const void*, const void*> *InverseMap) const;
|
||||
};
|
||||
|
||||
class InterExplodedGraphMapImpl {
|
||||
llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M;
|
||||
friend class ExplodedGraphImpl;
|
||||
void add(const ExplodedNode* From, ExplodedNode* To);
|
||||
|
||||
protected:
|
||||
ExplodedNode* getMappedImplNode(const ExplodedNode* N) const;
|
||||
|
||||
InterExplodedGraphMapImpl();
|
||||
public:
|
||||
virtual ~InterExplodedGraphMapImpl() {}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type-specialized ExplodedGraph classes.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class InterExplodedGraphMap : public InterExplodedGraphMapImpl {
|
||||
public:
|
||||
InterExplodedGraphMap() {};
|
||||
~InterExplodedGraphMap() {};
|
||||
|
||||
ExplodedNode* getMappedNode(const ExplodedNode* N) const {
|
||||
return static_cast<ExplodedNode*>(getMappedImplNode(N));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename STATE>
|
||||
class ExplodedGraph : public ExplodedGraphImpl {
|
||||
public:
|
||||
typedef STATE StateTy;
|
||||
typedef ExplodedNode NodeTy;
|
||||
typedef llvm::FoldingSet<NodeTy> AllNodesTy;
|
||||
|
||||
protected:
|
||||
virtual ExplodedNode* getNodeImpl(const ProgramPoint& L,
|
||||
const void* State,
|
||||
bool* IsNew) {
|
||||
|
||||
return getNode(L, static_cast<const StateTy*>(State), IsNew);
|
||||
}
|
||||
|
||||
/// Nodes - The nodes in the graph.
|
||||
AllNodesTy Nodes;
|
||||
|
||||
protected:
|
||||
virtual ExplodedGraphImpl* MakeEmptyGraph() const {
|
||||
return new ExplodedGraph(cfg, CodeDecl, Ctx);
|
||||
}
|
||||
|
||||
public:
|
||||
ExplodedGraph(CFG& c, Decl& cd, ASTContext& ctx)
|
||||
: ExplodedGraphImpl(c, cd, ctx) {}
|
||||
|
||||
/// getNode - Retrieve the node associated with a (Location,State) pair,
|
||||
/// where the 'Location' is a ProgramPoint in the CFG. If no node for
|
||||
/// this pair exists, it is created. IsNew is set to true if
|
||||
/// the node was freshly created.
|
||||
NodeTy* getNode(const ProgramPoint& L, const GRState* State,
|
||||
bool* IsNew = NULL) {
|
||||
|
||||
// Profile 'State' to determine if we already have an existing node.
|
||||
llvm::FoldingSetNodeID profile;
|
||||
void* InsertPos = 0;
|
||||
|
||||
NodeTy::Profile(profile, L, State);
|
||||
NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
|
||||
|
||||
if (!V) {
|
||||
// Allocate a new node.
|
||||
V = (NodeTy*) Allocator.Allocate<NodeTy>();
|
||||
new (V) NodeTy(L, State);
|
||||
|
||||
// Insert the node into the node set and return it.
|
||||
Nodes.InsertNode(V, InsertPos);
|
||||
|
||||
++NumNodes;
|
||||
|
||||
if (IsNew) *IsNew = true;
|
||||
}
|
||||
else
|
||||
if (IsNew) *IsNew = false;
|
||||
|
||||
return V;
|
||||
}
|
||||
|
||||
// Iterators.
|
||||
typedef NodeTy** roots_iterator;
|
||||
typedef const NodeTy** const_roots_iterator;
|
||||
typedef NodeTy** eop_iterator;
|
||||
typedef const NodeTy** const_eop_iterator;
|
||||
typedef typename AllNodesTy::iterator node_iterator;
|
||||
typedef typename AllNodesTy::const_iterator const_node_iterator;
|
||||
|
||||
node_iterator nodes_begin() {
|
||||
return Nodes.begin();
|
||||
}
|
||||
|
||||
node_iterator nodes_end() {
|
||||
return Nodes.end();
|
||||
}
|
||||
|
||||
const_node_iterator nodes_begin() const {
|
||||
return Nodes.begin();
|
||||
}
|
||||
|
||||
const_node_iterator nodes_end() const {
|
||||
return Nodes.end();
|
||||
}
|
||||
|
||||
roots_iterator roots_begin() {
|
||||
return reinterpret_cast<roots_iterator>(Roots.begin());
|
||||
}
|
||||
|
||||
roots_iterator roots_end() {
|
||||
return reinterpret_cast<roots_iterator>(Roots.end());
|
||||
}
|
||||
|
||||
const_roots_iterator roots_begin() const {
|
||||
return const_cast<ExplodedGraph>(this)->roots_begin();
|
||||
}
|
||||
|
||||
const_roots_iterator roots_end() const {
|
||||
return const_cast<ExplodedGraph>(this)->roots_end();
|
||||
}
|
||||
|
||||
eop_iterator eop_begin() {
|
||||
return reinterpret_cast<eop_iterator>(EndNodes.begin());
|
||||
}
|
||||
|
||||
eop_iterator eop_end() {
|
||||
return reinterpret_cast<eop_iterator>(EndNodes.end());
|
||||
}
|
||||
|
||||
const_eop_iterator eop_begin() const {
|
||||
return const_cast<ExplodedGraph>(this)->eop_begin();
|
||||
}
|
||||
|
||||
const_eop_iterator eop_end() const {
|
||||
return const_cast<ExplodedGraph>(this)->eop_end();
|
||||
}
|
||||
|
||||
std::pair<ExplodedGraph*, InterExplodedGraphMap*>
|
||||
Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
|
||||
llvm::DenseMap<const void*, const void*> *InverseMap = 0) const {
|
||||
|
||||
if (NBeg == NEnd)
|
||||
return std::make_pair((ExplodedGraph*) 0,
|
||||
(InterExplodedGraphMap*) 0);
|
||||
|
||||
assert (NBeg < NEnd);
|
||||
|
||||
const ExplodedNode* const* NBegImpl =
|
||||
(const ExplodedNode* const*) NBeg;
|
||||
const ExplodedNode* const* NEndImpl =
|
||||
(const ExplodedNode* const*) NEnd;
|
||||
|
||||
llvm::OwningPtr<InterExplodedGraphMap> M(new InterExplodedGraphMap());
|
||||
llvm::DenseMap<const void*, const void*> *InverseMap = 0) const;
|
||||
|
||||
ExplodedGraphImpl* G = ExplodedGraphImpl::Trim(NBegImpl, NEndImpl, M.get(),
|
||||
InverseMap);
|
||||
|
||||
return std::make_pair(static_cast<ExplodedGraph*>(G), M.take());
|
||||
}
|
||||
ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg,
|
||||
const ExplodedNode* const * NEnd,
|
||||
InterExplodedGraphMap *M,
|
||||
llvm::DenseMap<const void*, const void*> *InverseMap) const;
|
||||
};
|
||||
|
||||
class ExplodedNodeSet {
|
||||
|
||||
@@ -49,7 +49,7 @@ protected:
|
||||
friend class GREndPathNodeBuilderImpl;
|
||||
|
||||
/// G - The simulation graph. Each node is a (location,state) pair.
|
||||
llvm::OwningPtr<ExplodedGraphImpl> G;
|
||||
llvm::OwningPtr<ExplodedGraph> G;
|
||||
|
||||
/// WList - A set of queued nodes that need to be processed by the
|
||||
/// worklist algorithm. It is up to the implementation of WList to decide
|
||||
@@ -61,14 +61,14 @@ protected:
|
||||
/// number of times different CFGBlocks have been visited along a path.
|
||||
GRBlockCounter::Factory BCounterFactory;
|
||||
|
||||
void GenerateNode(const ProgramPoint& Loc, const void* State,
|
||||
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 void* getInitialState() = 0;
|
||||
virtual const GRState* getInitialState() = 0;
|
||||
|
||||
void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
|
||||
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
|
||||
@@ -98,7 +98,7 @@ private:
|
||||
GRCoreEngineImpl& operator=(const GRCoreEngineImpl&);
|
||||
|
||||
protected:
|
||||
GRCoreEngineImpl(ExplodedGraphImpl* g, GRWorkList* wl)
|
||||
GRCoreEngineImpl(ExplodedGraph* g, GRWorkList* wl)
|
||||
: G(g), WList(wl), BCounterFactory(g->getAllocator()) {}
|
||||
|
||||
public:
|
||||
@@ -142,16 +142,16 @@ public:
|
||||
}
|
||||
|
||||
ExplodedNode*
|
||||
generateNodeImpl(const ProgramPoint &PP, const void* State,
|
||||
generateNodeImpl(const ProgramPoint &PP, const GRState* State,
|
||||
ExplodedNode* Pred);
|
||||
|
||||
ExplodedNode*
|
||||
generateNodeImpl(const Stmt* S, const void* State, ExplodedNode* Pred,
|
||||
generateNodeImpl(const Stmt* S, const GRState* State, ExplodedNode* Pred,
|
||||
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
|
||||
const void *tag = 0);
|
||||
|
||||
ExplodedNode*
|
||||
generateNodeImpl(const Stmt* S, const void* State,
|
||||
generateNodeImpl(const Stmt* S, const GRState* State,
|
||||
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
|
||||
const void *tag = 0) {
|
||||
ExplodedNode* N = getLastNode();
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
}
|
||||
|
||||
ExplodedNode*
|
||||
generateNodeImpl(const Stmt* S, const void* State, const void *tag = 0) {
|
||||
generateNodeImpl(const Stmt* S, const GRState* State, const void *tag = 0) {
|
||||
ExplodedNode* N = getLastNode();
|
||||
assert (N && "Predecessor of new node is infeasible.");
|
||||
return generateNodeImpl(S, State, N, ProgramPoint::PostStmtKind, tag);
|
||||
@@ -325,10 +325,10 @@ public:
|
||||
~GRBranchNodeBuilderImpl();
|
||||
|
||||
ExplodedNode* getPredecessor() const { return Pred; }
|
||||
const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
|
||||
const ExplodedGraph& getGraph() const { return *Eng.G; }
|
||||
GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
|
||||
|
||||
ExplodedNode* generateNodeImpl(const void* State, bool branch);
|
||||
ExplodedNode* generateNodeImpl(const GRState* State, bool branch);
|
||||
|
||||
CFGBlock* getTargetBlock(bool branch) const {
|
||||
return branch ? DstT : DstF;
|
||||
@@ -349,7 +349,7 @@ public:
|
||||
template<typename STATE>
|
||||
class GRBranchNodeBuilder {
|
||||
typedef STATE StateTy;
|
||||
typedef ExplodedGraph<StateTy> GraphTy;
|
||||
typedef ExplodedGraph GraphTy;
|
||||
typedef typename GraphTy::NodeTy NodeTy;
|
||||
|
||||
GRBranchNodeBuilderImpl& NB;
|
||||
@@ -425,7 +425,7 @@ public:
|
||||
Iterator begin() { return Iterator(DispatchBlock.succ_begin()); }
|
||||
Iterator end() { return Iterator(DispatchBlock.succ_end()); }
|
||||
|
||||
ExplodedNode* generateNodeImpl(const Iterator& I, const void* State,
|
||||
ExplodedNode* generateNodeImpl(const Iterator& I, const GRState* State,
|
||||
bool isSink);
|
||||
|
||||
Expr* getTarget() const { return E; }
|
||||
@@ -435,7 +435,7 @@ public:
|
||||
template<typename STATE>
|
||||
class GRIndirectGotoNodeBuilder {
|
||||
typedef STATE StateTy;
|
||||
typedef ExplodedGraph<StateTy> GraphTy;
|
||||
typedef ExplodedGraph GraphTy;
|
||||
typedef typename GraphTy::NodeTy NodeTy;
|
||||
|
||||
GRIndirectGotoNodeBuilderImpl& NB;
|
||||
@@ -492,9 +492,9 @@ public:
|
||||
Iterator end() { return Iterator(Src->succ_rend()); }
|
||||
|
||||
ExplodedNode* generateCaseStmtNodeImpl(const Iterator& I,
|
||||
const void* State);
|
||||
const GRState* State);
|
||||
|
||||
ExplodedNode* generateDefaultCaseNodeImpl(const void* State,
|
||||
ExplodedNode* generateDefaultCaseNodeImpl(const GRState* State,
|
||||
bool isSink);
|
||||
|
||||
Expr* getCondition() const { return Condition; }
|
||||
@@ -504,7 +504,7 @@ public:
|
||||
template<typename STATE>
|
||||
class GRSwitchNodeBuilder {
|
||||
typedef STATE StateTy;
|
||||
typedef ExplodedGraph<StateTy> GraphTy;
|
||||
typedef ExplodedGraph GraphTy;
|
||||
typedef typename GraphTy::NodeTy NodeTy;
|
||||
|
||||
GRSwitchNodeBuilderImpl& NB;
|
||||
@@ -554,7 +554,7 @@ public:
|
||||
return getBlockCounter().getNumVisited(B.getBlockID());
|
||||
}
|
||||
|
||||
ExplodedNode* generateNodeImpl(const void* State,
|
||||
ExplodedNode* generateNodeImpl(const GRState* State,
|
||||
const void *tag = 0,
|
||||
ExplodedNode *P = 0);
|
||||
|
||||
@@ -604,13 +604,13 @@ public:
|
||||
typedef SUBENGINE SubEngineTy;
|
||||
typedef typename SubEngineTy::StateTy StateTy;
|
||||
typedef typename StateTy::ManagerTy StateManagerTy;
|
||||
typedef ExplodedGraph<StateTy> GraphTy;
|
||||
typedef ExplodedGraph GraphTy;
|
||||
typedef typename GraphTy::NodeTy NodeTy;
|
||||
|
||||
protected:
|
||||
SubEngineTy& SubEngine;
|
||||
|
||||
virtual const void* getInitialState() {
|
||||
virtual const GRState* getInitialState() {
|
||||
return SubEngine.getInitialState();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace clang {
|
||||
class GRExprEngine {
|
||||
public:
|
||||
typedef GRState StateTy;
|
||||
typedef ExplodedGraph<StateTy> GraphTy;
|
||||
typedef GraphTy::NodeTy NodeTy;
|
||||
typedef ExplodedGraph GraphTy;
|
||||
typedef GraphTy::NodeTy NodeTy;
|
||||
|
||||
// Builders.
|
||||
typedef GRStmtNodeBuilder<StateTy> StmtNodeBuilder;
|
||||
|
||||
@@ -26,7 +26,7 @@ class BugReporter;
|
||||
class ASTContext;
|
||||
class GRExprEngine;
|
||||
class PathDiagnosticClient;
|
||||
template <typename T> class ExplodedGraph;
|
||||
class ExplodedGraph;
|
||||
|
||||
|
||||
class GRSimpleAPICheck : public GRAuditor<GRState> {
|
||||
|
||||
@@ -349,17 +349,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct GRTrait<GRState*> {
|
||||
static inline void* toPtr(GRState* St) { return (void*) St; }
|
||||
static inline GRState* toState(void* P) { return (GRState*) P; }
|
||||
static inline void Profile(llvm::FoldingSetNodeID& profile, GRState* St) {
|
||||
// At this point states have already been uniqued. Just
|
||||
// add the pointer.
|
||||
profile.AddPointer(St);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class GRStateSet {
|
||||
typedef llvm::SmallPtrSet<const GRState*,5> ImplTy;
|
||||
ImplTy Impl;
|
||||
@@ -468,7 +457,7 @@ public:
|
||||
const GRState *getInitialState();
|
||||
|
||||
ASTContext &getContext() { return ValueMgr.getContext(); }
|
||||
const ASTContext &getContext() const { return ValueMgr.getContext(); }
|
||||
const ASTContext &getContext() const { return ValueMgr.getContext(); }
|
||||
|
||||
const Decl &getCodeDecl() { return codedecl; }
|
||||
GRTransferFuncs& getTransferFuncs() { return *TF; }
|
||||
|
||||
@@ -1286,8 +1286,7 @@ BugReportEquivClass::~BugReportEquivClass() {
|
||||
GRBugReporter::~GRBugReporter() { FlushReports(); }
|
||||
BugReporterData::~BugReporterData() {}
|
||||
|
||||
ExplodedGraph<GRState>&
|
||||
GRBugReporter::getGraph() { return Eng.getGraph(); }
|
||||
ExplodedGraph &GRBugReporter::getGraph() { return Eng.getGraph(); }
|
||||
|
||||
GRStateManager&
|
||||
GRBugReporter::getStateManager() { return Eng.getStateManager(); }
|
||||
@@ -1332,9 +1331,9 @@ void BugReporter::FlushReports() {
|
||||
// PathDiagnostics generation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static std::pair<std::pair<ExplodedGraph<GRState>*, NodeBackMap*>,
|
||||
static std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
|
||||
std::pair<ExplodedNode*, unsigned> >
|
||||
MakeReportGraph(const ExplodedGraph<GRState>* G,
|
||||
MakeReportGraph(const ExplodedGraph* G,
|
||||
const ExplodedNode** NStart,
|
||||
const ExplodedNode** NEnd) {
|
||||
|
||||
@@ -1342,7 +1341,7 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
|
||||
// error nodes to the root. In the new graph we should only have one
|
||||
// error node unless there are two or more error nodes with the same minimum
|
||||
// path length.
|
||||
ExplodedGraph<GRState>* GTrim;
|
||||
ExplodedGraph* GTrim;
|
||||
InterExplodedGraphMap* NMap;
|
||||
|
||||
llvm::DenseMap<const void*, const void*> InverseMap;
|
||||
@@ -1350,7 +1349,7 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
|
||||
|
||||
// Create owning pointers for GTrim and NMap just to ensure that they are
|
||||
// released when this function exists.
|
||||
llvm::OwningPtr<ExplodedGraph<GRState> > AutoReleaseGTrim(GTrim);
|
||||
llvm::OwningPtr<ExplodedGraph> AutoReleaseGTrim(GTrim);
|
||||
llvm::OwningPtr<InterExplodedGraphMap> AutoReleaseNMap(NMap);
|
||||
|
||||
// Find the (first) error node in the trimmed graph. We just need to consult
|
||||
@@ -1358,7 +1357,7 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
|
||||
// in the new graph.
|
||||
|
||||
std::queue<const ExplodedNode*> WS;
|
||||
typedef llvm::DenseMap<const ExplodedNode*,unsigned> IndexMapTy;
|
||||
typedef llvm::DenseMap<const ExplodedNode*, unsigned> IndexMapTy;
|
||||
IndexMapTy IndexMap;
|
||||
|
||||
for (const ExplodedNode** I = NStart; I != NEnd; ++I)
|
||||
@@ -1372,9 +1371,8 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
|
||||
|
||||
// Create a new (third!) graph with a single path. This is the graph
|
||||
// that will be returned to the caller.
|
||||
ExplodedGraph<GRState> *GNew =
|
||||
new ExplodedGraph<GRState>(GTrim->getCFG(), GTrim->getCodeDecl(),
|
||||
GTrim->getContext());
|
||||
ExplodedGraph *GNew = new ExplodedGraph(GTrim->getCFG(), GTrim->getCodeDecl(),
|
||||
GTrim->getContext());
|
||||
|
||||
// Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS
|
||||
// to the root node, and then construct a new graph that contains only
|
||||
@@ -1418,8 +1416,7 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
|
||||
|
||||
// Create the equivalent node in the new graph with the same state
|
||||
// and location.
|
||||
ExplodedNode* NewN =
|
||||
GNew->getNode(N->getLocation(), N->getState());
|
||||
ExplodedNode* NewN = GNew->getNode(N->getLocation(), N->getState());
|
||||
|
||||
// Store the mapping to the original node.
|
||||
llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N);
|
||||
@@ -1576,7 +1573,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
||||
|
||||
// Construct a new graph that contains only a single path from the error
|
||||
// node to a root.
|
||||
const std::pair<std::pair<ExplodedGraph<GRState>*, NodeBackMap*>,
|
||||
const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>,
|
||||
std::pair<ExplodedNode*, unsigned> >&
|
||||
GPair = MakeReportGraph(&getGraph(), &Nodes[0], &Nodes[0] + Nodes.size());
|
||||
|
||||
@@ -1588,7 +1585,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
||||
|
||||
assert(R && "No original report found for sliced graph.");
|
||||
|
||||
llvm::OwningPtr<ExplodedGraph<GRState> > ReportGraph(GPair.first.first);
|
||||
llvm::OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first);
|
||||
llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second);
|
||||
const ExplodedNode *N = GPair.second.first;
|
||||
|
||||
|
||||
@@ -127,13 +127,56 @@ ExplodedNode::NodeGroup::~NodeGroup() {
|
||||
if (getKind() == SizeOther) delete &getVector(getPtr());
|
||||
}
|
||||
|
||||
ExplodedGraphImpl*
|
||||
ExplodedGraphImpl::Trim(const ExplodedNode* const* BeginSources,
|
||||
const ExplodedNode* const* EndSources,
|
||||
InterExplodedGraphMapImpl* M,
|
||||
llvm::DenseMap<const void*, const void*> *InverseMap)
|
||||
const {
|
||||
ExplodedNode *ExplodedGraph::getNode(const ProgramPoint& L,
|
||||
const GRState* State, bool* IsNew) {
|
||||
// Profile 'State' to determine if we already have an existing node.
|
||||
llvm::FoldingSetNodeID profile;
|
||||
void* InsertPos = 0;
|
||||
|
||||
NodeTy::Profile(profile, L, State);
|
||||
NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
|
||||
|
||||
if (!V) {
|
||||
// Allocate a new node.
|
||||
V = (NodeTy*) Allocator.Allocate<NodeTy>();
|
||||
new (V) NodeTy(L, State);
|
||||
|
||||
// Insert the node into the node set and return it.
|
||||
Nodes.InsertNode(V, InsertPos);
|
||||
|
||||
++NumNodes;
|
||||
|
||||
if (IsNew) *IsNew = true;
|
||||
}
|
||||
else
|
||||
if (IsNew) *IsNew = false;
|
||||
|
||||
return V;
|
||||
}
|
||||
|
||||
std::pair<ExplodedGraph*, InterExplodedGraphMap*>
|
||||
ExplodedGraph::Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
|
||||
llvm::DenseMap<const void*, const void*> *InverseMap) const {
|
||||
|
||||
if (NBeg == NEnd)
|
||||
return std::make_pair((ExplodedGraph*) 0,
|
||||
(InterExplodedGraphMap*) 0);
|
||||
|
||||
assert (NBeg < NEnd);
|
||||
|
||||
llvm::OwningPtr<InterExplodedGraphMap> M(new InterExplodedGraphMap());
|
||||
|
||||
ExplodedGraph* G = TrimInternal(NBeg, NEnd, M.get(), InverseMap);
|
||||
|
||||
return std::make_pair(static_cast<ExplodedGraph*>(G), M.take());
|
||||
}
|
||||
|
||||
ExplodedGraph*
|
||||
ExplodedGraph::TrimInternal(const ExplodedNode* const* BeginSources,
|
||||
const ExplodedNode* const* EndSources,
|
||||
InterExplodedGraphMap* M,
|
||||
llvm::DenseMap<const void*, const void*> *InverseMap) const {
|
||||
|
||||
typedef llvm::DenseSet<const ExplodedNode*> Pass1Ty;
|
||||
Pass1Ty Pass1;
|
||||
|
||||
@@ -177,7 +220,7 @@ const {
|
||||
return 0;
|
||||
|
||||
// Create an empty graph.
|
||||
ExplodedGraphImpl* G = MakeEmptyGraph();
|
||||
ExplodedGraph* G = MakeEmptyGraph();
|
||||
|
||||
// ===- Pass 2 (forward DFS to construct the new graph) -===
|
||||
while (!WL2.empty()) {
|
||||
@@ -190,7 +233,7 @@ const {
|
||||
|
||||
// Create the corresponding node in the new graph and record the mapping
|
||||
// from the old node to the new node.
|
||||
ExplodedNode* NewN = G->getNodeImpl(N->getLocation(), N->State, NULL);
|
||||
ExplodedNode* NewN = G->getNode(N->getLocation(), N->State, NULL);
|
||||
Pass2[N] = NewN;
|
||||
|
||||
// Also record the reverse mapping from the new node to the old node.
|
||||
@@ -238,12 +281,10 @@ const {
|
||||
}
|
||||
|
||||
ExplodedNode*
|
||||
InterExplodedGraphMapImpl::getMappedImplNode(const ExplodedNode* N) const {
|
||||
InterExplodedGraphMap::getMappedNode(const ExplodedNode* N) const {
|
||||
llvm::DenseMap<const ExplodedNode*, ExplodedNode*>::iterator I =
|
||||
M.find(N);
|
||||
|
||||
return I == M.end() ? 0 : I->second;
|
||||
}
|
||||
|
||||
InterExplodedGraphMapImpl::InterExplodedGraphMapImpl() {}
|
||||
|
||||
|
||||
@@ -341,11 +341,11 @@ 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 void* State,
|
||||
ExplodedNode* Pred) {
|
||||
void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc,
|
||||
const GRState* State, ExplodedNode* Pred) {
|
||||
|
||||
bool IsNew;
|
||||
ExplodedNode* Node = G->getNodeImpl(Loc, State, &IsNew);
|
||||
ExplodedNode* Node = G->getNode(Loc, State, &IsNew);
|
||||
|
||||
if (Pred)
|
||||
Node->addPredecessor(Pred); // Link 'Node' with its predecessor.
|
||||
@@ -383,7 +383,7 @@ void GRStmtNodeBuilderImpl::GenerateAutoTransition(ExplodedNode* N) {
|
||||
}
|
||||
|
||||
bool IsNew;
|
||||
ExplodedNode* Succ = Eng.G->getNodeImpl(Loc, N->State, &IsNew);
|
||||
ExplodedNode* Succ = Eng.G->getNode(Loc, N->State, &IsNew);
|
||||
Succ->addPredecessor(N);
|
||||
|
||||
if (IsNew)
|
||||
@@ -426,7 +426,7 @@ static inline PostStmt GetPostLoc(const Stmt* S, ProgramPoint::Kind K,
|
||||
}
|
||||
|
||||
ExplodedNode*
|
||||
GRStmtNodeBuilderImpl::generateNodeImpl(const Stmt* S, const void* State,
|
||||
GRStmtNodeBuilderImpl::generateNodeImpl(const Stmt* S, const GRState* State,
|
||||
ExplodedNode* Pred,
|
||||
ProgramPoint::Kind K,
|
||||
const void *tag) {
|
||||
@@ -437,10 +437,10 @@ GRStmtNodeBuilderImpl::generateNodeImpl(const Stmt* S, const void* State,
|
||||
|
||||
ExplodedNode*
|
||||
GRStmtNodeBuilderImpl::generateNodeImpl(const ProgramPoint &Loc,
|
||||
const void* State,
|
||||
const GRState* State,
|
||||
ExplodedNode* Pred) {
|
||||
bool IsNew;
|
||||
ExplodedNode* N = Eng.G->getNodeImpl(Loc, State, &IsNew);
|
||||
ExplodedNode* N = Eng.G->getNode(Loc, State, &IsNew);
|
||||
N->addPredecessor(Pred);
|
||||
Deferred.erase(Pred);
|
||||
|
||||
@@ -454,8 +454,8 @@ GRStmtNodeBuilderImpl::generateNodeImpl(const ProgramPoint &Loc,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExplodedNode* GRBranchNodeBuilderImpl::generateNodeImpl(const void* State,
|
||||
bool branch) {
|
||||
ExplodedNode* GRBranchNodeBuilderImpl::generateNodeImpl(const GRState* State,
|
||||
bool branch) {
|
||||
|
||||
// If the branch has been marked infeasible we should not generate a node.
|
||||
if (!isFeasible(branch))
|
||||
@@ -464,7 +464,7 @@ ExplodedNode* GRBranchNodeBuilderImpl::generateNodeImpl(const void* State,
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode* Succ =
|
||||
Eng.G->getNodeImpl(BlockEdge(Src, branch ? DstT : DstF), State, &IsNew);
|
||||
Eng.G->getNode(BlockEdge(Src, branch ? DstT : DstF), State, &IsNew);
|
||||
|
||||
Succ->addPredecessor(Pred);
|
||||
|
||||
@@ -492,12 +492,12 @@ GRBranchNodeBuilderImpl::~GRBranchNodeBuilderImpl() {
|
||||
|
||||
ExplodedNode*
|
||||
GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Iterator& I,
|
||||
const void* St,
|
||||
const GRState* St,
|
||||
bool isSink) {
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode* Succ =
|
||||
Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()), St, &IsNew);
|
||||
Eng.G->getNode(BlockEdge(Src, I.getBlock()), St, &IsNew);
|
||||
|
||||
Succ->addPredecessor(Pred);
|
||||
|
||||
@@ -517,11 +517,11 @@ GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Iterator& I,
|
||||
|
||||
ExplodedNode*
|
||||
GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I,
|
||||
const void* St) {
|
||||
const GRState* St) {
|
||||
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode* Succ = Eng.G->getNodeImpl(BlockEdge(Src, I.getBlock()),
|
||||
ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock()),
|
||||
St, &IsNew);
|
||||
Succ->addPredecessor(Pred);
|
||||
|
||||
@@ -535,7 +535,7 @@ GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I,
|
||||
|
||||
|
||||
ExplodedNode*
|
||||
GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(const void* St,
|
||||
GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(const GRState* St,
|
||||
bool isSink) {
|
||||
|
||||
// Get the block for the default case.
|
||||
@@ -544,7 +544,7 @@ GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(const void* St,
|
||||
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode* Succ = Eng.G->getNodeImpl(BlockEdge(Src, DefaultBlock),
|
||||
ExplodedNode* Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock),
|
||||
St, &IsNew);
|
||||
Succ->addPredecessor(Pred);
|
||||
|
||||
@@ -566,14 +566,14 @@ GREndPathNodeBuilderImpl::~GREndPathNodeBuilderImpl() {
|
||||
}
|
||||
|
||||
ExplodedNode*
|
||||
GREndPathNodeBuilderImpl::generateNodeImpl(const void* State,
|
||||
GREndPathNodeBuilderImpl::generateNodeImpl(const GRState* State,
|
||||
const void *tag,
|
||||
ExplodedNode* P) {
|
||||
HasGeneratedNode = true;
|
||||
bool IsNew;
|
||||
|
||||
ExplodedNode* Node =
|
||||
Eng.G->getNodeImpl(BlockEntrance(&B, tag), State, &IsNew);
|
||||
Eng.G->getNode(BlockEntrance(&B, tag), State, &IsNew);
|
||||
|
||||
Node->addPredecessor(P ? P : Pred);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user