[cfe-commits] r45711 - in /cfe/trunk: Analysis/GRConstantPropagation.cpp Analysis/ReachabilityEngine.cpp include/clang/Analysis/PathSensitive/ExplodedGraph.h include/clang/Analysis/PathSensitive/ExplodedNode.h include/clang/Analysis/PathSensitive/ReachabilityEngine.h include/clang/Analysis/PathSensitive/SimulEngine.h include/clang/Analysis/PathSensitive/SimulGraph.h include/clang/Analysis/PathSensitive/SimulVertex.h
Ted Kremenek
kremenek at apple.com
Mon Jan 7 11:08:43 PST 2008
Author: kremenek
Date: Mon Jan 7 13:08:42 2008
New Revision: 45711
URL: http://llvm.org/viewvc/llvm-project?rev=45711&view=rev
Log:
Renamed SimulVertex, SimulGraph, and SimulEngine to:
ExplodedNode, ExplodedGraph (to match the vocabulary in the RHS paper)
ReachabilityEngine
The implementation of the core of the path-sensitive dataflow solver has
been de-templatized and places in ReachabilityEngine.cpp.
The solver is still incomplete.
Added:
cfe/trunk/Analysis/ReachabilityEngine.cpp
cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h
cfe/trunk/include/clang/Analysis/PathSensitive/ReachabilityEngine.h
Removed:
cfe/trunk/include/clang/Analysis/PathSensitive/SimulEngine.h
cfe/trunk/include/clang/Analysis/PathSensitive/SimulGraph.h
cfe/trunk/include/clang/Analysis/PathSensitive/SimulVertex.h
Modified:
cfe/trunk/Analysis/GRConstantPropagation.cpp
Modified: cfe/trunk/Analysis/GRConstantPropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstantPropagation.cpp?rev=45711&r1=45710&r2=45711&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRConstantPropagation.cpp (original)
+++ cfe/trunk/Analysis/GRConstantPropagation.cpp Mon Jan 7 13:08:42 2008
@@ -15,7 +15,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/PathSensitive/SimulGraph.h"
+#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "clang/AST/Expr.h"
#include "clang/AST/CFG.h"
#include "llvm/Support/Casting.h"
@@ -93,236 +93,4 @@
} // end llvm namespace
-//===----------------------------------------------------------------------===//
-/// The checker.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-
-class GREngine {
-
- //==---------------------------------==//
- // Type definitions.
- //==---------------------------------==//
-
-public:
- typedef llvm::ImmutableMap<Decl*,ConstV> StateTy;
- typedef SimulVertex<StateTy> VertexTy;
- typedef SimulGraph<VertexTy> GraphTy;
- typedef llvm::SmallVector<Stmt*,20> StmtStackTy;
- typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
-
- /// DFSWorkList - A nested class that represents a worklist that processes
- /// vertices in LIFO order.
- class DFSWorkList {
- llvm::SmallVector<VertexTy*,20> Vertices;
- public:
- bool hasWork() const { return !Vertices.empty(); }
-
- /// Enqueue - Add a vertex to the worklist.
- void Enqueue(VertexTy* V) { Vertices.push_back(V); }
-
- /// Dequeue - Remove a vertex from the worklist.
- VertexTy* Dequeue() {
- assert (hasWork());
- VertexTy* V = Vertices.back();
- Vertices.pop_back();
- return V;
- }
- };
-
- //==---------------------------------==//
- // Data.
- //==---------------------------------==//
-
-private:
- CFG& cfg;
-
- /// StateFactory - States are simply maps from Decls to constants. This
- /// object is a collection of all the states (immutable maps) that are
- /// created by the analysis. This object owns the created maps.
- StateTy::Factory StateFactory;
-
- /// Graph - The simulation graph. Each vertex is a (location,state) pair.
- GraphTy Graph;
-
- /// ParentMap - A lazily populated map from a Stmt* to its parent Stmt*.
- ParentMapTy ParentMap;
-
- /// StmtStack - A stack of statements/expressions that records the
- /// statement hierarchy starting from the Stmt* of the last dequeued
- /// vertex. Used to lazily populate ParentMap.
- StmtStackTy StmtStack;
-
- /// WorkList - A set of queued vertices that need to be processed by the
- /// worklist algorithm.
- DFSWorkList WorkList;
-
- //==---------------------------------==//
- // Edge processing.
- //==---------------------------------==//
-
- void MakeVertex(const ProgramEdge& Loc, StateTy State, VertexTy* PredV) {
- std::pair<VertexTy*,bool> V = Graph.getVertex(Loc,State);
- V.first->addPredecessor(PredV);
- if (V.second) WorkList.Enqueue(V.first);
- }
-
- void MakeVertex(const ProgramEdge& Loc, VertexTy* PredV) {
- MakeVertex(Loc,PredV->getState(),PredV);
- }
-
- void VisitBlkBlk(const BlkBlkEdge& E, VertexTy* PredV);
- void VisitBlkStmt(const BlkStmtEdge& E, VertexTy* PredV);
- void VisitStmtBlk(const StmtBlkEdge& E, VertexTy* PredV);
-
- void ProcessEOP(CFGBlock* Blk, VertexTy* PredV);
- void ProcessStmt(Stmt* S, VertexTy* PredV);
- void ProcessTerminator(Stmt* Terminator ,VertexTy* PredV);
-
- //==---------------------------------==//
- // Disable copying.
- //==---------------------------------==//
-
- GREngine(const GREngine&); // Do not implement.
- GREngine& operator=(const GREngine&);
-
- //==--------------------------------==//
- // Public API.
- //==--------------------------------==//
-
-public:
- GREngine(CFG& c);
-
- /// getGraph - Returns the simulation graph.
- const GraphTy& getGraph() const { return Graph; }
-
- /// 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 = 1000000);
-};
-} // end anonymous namespace
-
-
-//==--------------------------------------------------------==//
-// Public API.
-//==--------------------------------------------------------==//
-
-GREngine::GREngine(CFG& c) : cfg(c) {
- // Get the entry block. Make sure that it has 1 (and only 1) successor.
- CFGBlock* Entry = &c.getEntry();
-
- assert (Entry->empty() && "Entry block must be empty.");
- assert (Entry->succ_size() == 1 && "Entry block must have 1 successor.");
-
- // Get the first (and only) successor of Entry.
- CFGBlock* Succ = *(Entry->succ_begin());
-
- // Construct an edge representing the starting location in the function.
- BlkBlkEdge StartLoc(Entry,Succ);
-
- // Get the vertex. Make it a root in the graph.
- VertexTy* Root = Graph.getVertex(StartLoc,StateFactory.GetEmptyMap()).first;
- Graph.addRoot(Root);
-
- // Enqueue the root so that it can be processed by the worklist.
- WorkList.Enqueue(Root);
-}
-
-
-bool GREngine::ExecuteWorkList(unsigned Steps) {
- while (Steps && WorkList.hasWork()) {
- --Steps;
- VertexTy* V = WorkList.Dequeue();
-
- // Dispatch on the location type.
- switch (V->getLocation().getKind()) {
- case ProgramEdge::BlkBlk:
- VisitBlkBlk(cast<BlkBlkEdge>(V->getLocation()),V);
- break;
-
- case ProgramEdge::BlkStmt:
- VisitBlkStmt(cast<BlkStmtEdge>(V->getLocation()),V);
- break;
-
- case ProgramEdge::StmtBlk:
- VisitStmtBlk(cast<StmtBlkEdge>(V->getLocation()),V);
- break;
-
- default:
- assert (false && "Unsupported edge type.");
- }
- }
-
- return WorkList.hasWork();
-}
-
-//==--------------------------------------------------------==//
-// Edge processing.
-//==--------------------------------------------------------==//
-
-void GREngine::VisitBlkBlk(const BlkBlkEdge& E, GREngine::VertexTy* PredV) {
-
- CFGBlock* Blk = E.Dst();
-
- // Check if we are entering the EXIT block.
- if (Blk == &cfg.getExit()) {
- assert (cfg.getExit().size() == 0 && "EXIT block cannot contain Stmts.");
- // Process the End-Of-Path.
- ProcessEOP(Blk, PredV);
- return;
- }
-
-
- // FIXME: we will dispatch to a function that manipulates the state
- // at the entrance to a block.
-
- if (!Blk->empty()) {
- // If 'Blk' has at least one statement, create a BlkStmtEdge and create
- // the appropriate vertex. This is the common case.
- MakeVertex(BlkStmtEdge(Blk,Blk->front()), PredV->getState(), PredV);
- }
- else {
- // Otherwise, create a vertex at the BlkStmtEdge right before the terminator
- // (if any) is evaluated.
- MakeVertex(StmtBlkEdge(NULL,Blk),PredV->getState(), PredV);
- }
-}
-
-void GREngine::VisitBlkStmt(const BlkStmtEdge& E, GREngine::VertexTy* PredV) {
-
- if (Stmt* S = E.Dst())
- ProcessStmt(S,PredV);
- else {
- // No statement. Create an edge right before the terminator is evaluated.
- MakeVertex(StmtBlkEdge(NULL,E.Src()), PredV->getState(), PredV);
- }
-}
-
-void GREngine::VisitStmtBlk(const StmtBlkEdge& E, GREngine::VertexTy* PredV) {
- CFGBlock* Blk = E.Dst();
-
- if (Stmt* Terminator = Blk->getTerminator())
- ProcessTerminator(Terminator,PredV);
- else {
- // No terminator. We should have only 1 successor.
- assert (Blk->succ_size() == 1);
- MakeVertex(BlkBlkEdge(Blk,*(Blk->succ_begin())), PredV);
- }
-}
-void GREngine::ProcessEOP(CFGBlock* Blk, GREngine::VertexTy* PredV) {
- // FIXME: Perform dispatch to adjust state.
- VertexTy* V = Graph.getVertex(BlkStmtEdge(Blk,NULL), PredV->getState()).first;
- V->addPredecessor(PredV);
- Graph.addEndOfPath(V);
-}
-
-void GREngine::ProcessStmt(Stmt* S, GREngine::VertexTy* PredV) {
- assert(false && "Not implemented.");
-}
-
-void GREngine::ProcessTerminator(Stmt* Terminator,GREngine::VertexTy* PredV) {
- assert(false && "Not implemented.");
-}
Added: cfe/trunk/Analysis/ReachabilityEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ReachabilityEngine.cpp?rev=45711&view=auto
==============================================================================
--- cfe/trunk/Analysis/ReachabilityEngine.cpp (added)
+++ cfe/trunk/Analysis/ReachabilityEngine.cpp Mon Jan 7 13:08:42 2008
@@ -0,0 +1,169 @@
+//= ReachabilityEngine.cpp - Path-Sens. Dataflow Engine ------------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a generic engine for intraprocedural, path-sensitive,
+// dataflow analysis via graph reachability engine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/ReachabilityEngine.h"
+#include "clang/AST/Stmt.h"
+#include "llvm/Support/Casting.h"
+
+using namespace clang;
+using clang::reng::WorkList;
+using llvm::isa;
+using llvm::cast;
+
+// Place dstor here so that all of the virtual functions in DFS have their
+// code placed in the object file of this translation unit.
+clang::reng::DFS::~DFS() {}
+
+ReachabilityEngineImpl::ReachabilityEngineImpl(CFG& c,
+ clang::reng::WorkList* wlist)
+ : cfg(c), WList(wlist) {
+
+ // Get the entry block. Make sure that it has 1 (and only 1) successor.
+ CFGBlock* Entry = &c.getEntry();
+ assert (Entry->empty() && "Entry block must be empty.");
+ assert (Entry->succ_size() == 1 && "Entry block must have 1 successor.");
+
+ // Get the first (and only) successor of Entry.
+ CFGBlock* Succ = *(Entry->succ_begin());
+
+ // Construct an edge representing the starting location in the function.
+ BlkBlkEdge StartLoc(Entry,Succ);
+
+ // Create the root node.
+ assert (false && "FIXME soon.");
+// WList->Enqueue(G->addRoot(getNode(StartLoc));
+}
+
+void ReachabilityEngineImpl::getNode(const ProgramEdge& Loc, void* State,
+ ExplodedNodeImpl* Pred) {
+
+ bool IsNew;
+ ExplodedNodeImpl* V = G->getNodeImpl(Loc,State,IsNew);
+
+ // Link the node with its predecessor.
+ V->addUntypedPredecessor(Pred);
+
+ if (IsNew) {
+ // Only add the node to the worklist if it was freshly generated.
+ WList->Enqueue(V);
+
+ // Check if the node's edge is a StmtStmtEdge where the destination
+ // statement is not a BlockLevelExpr. In this case, we must lazily
+ // populate ParentMap.
+ if (isa<StmtStmtEdge>(Loc)) {
+ Stmt* S = cast<StmtStmtEdge>(Loc).Dst();
+ assert (CurrentBlkExpr != NULL);
+
+ if (S != CurrentBlkExpr && ParentMap.find(S) == ParentMap.end()) {
+ // Populate ParentMap starting from CurrentBlkExpr.
+ PopulateParentMap(CurrentBlkExpr);
+ assert (ParentMap.find(S) != ParentMap.end());
+ }
+ }
+ }
+}
+
+void ReachabilityEngineImpl::PopulateParentMap(Stmt* Parent) {
+ for (Stmt::child_iterator I=Parent->child_begin(),
+ E=Parent->child_end(); I!=E; ++I) {
+
+ assert (ParentMap.find(*I) == ParentMap.end());
+ ParentMap[*I] = Parent;
+ PopulateParentMap(*I);
+ }
+}
+
+bool ReachabilityEngineImpl::ExecuteWorkList(unsigned Steps) {
+
+ while (Steps && WList->hasWork()) {
+ --Steps;
+ ExplodedNodeImpl* V = WList->Dequeue();
+
+ // Dispatch on the location type.
+ switch (V->getLocation().getKind()) {
+ case ProgramEdge::BlkBlk:
+ ProcessBlkBlk(cast<BlkBlkEdge>(V->getLocation()),V);
+ break;
+
+ case ProgramEdge::BlkStmt:
+ ProcessBlkStmt(cast<BlkStmtEdge>(V->getLocation()),V);
+ break;
+
+ case ProgramEdge::StmtBlk:
+ ProcessStmtBlk(cast<StmtBlkEdge>(V->getLocation()),V);
+ break;
+
+ case ProgramEdge::StmtStmt:
+ ProcessStmt(cast<StmtStmtEdge>(V->getLocation()).Dst(),V);
+ break;
+
+ default:
+ assert (false && "Unsupported edge type.");
+ }
+ }
+
+ return WList->hasWork();
+}
+
+
+void ReachabilityEngineImpl::ProcessBlkBlk(const BlkBlkEdge& E,
+ ExplodedNodeImpl* Pred) {
+
+ CFGBlock* Blk = E.Dst();
+
+ // Check if we are entering the EXIT block.
+ if (Blk == &cfg.getExit()) {
+ assert (cfg.getExit().size() == 0 && "EXIT block cannot contain Stmts.");
+ // Process the End-Of-Path.
+ ProcessEOP(Blk, Pred);
+ return;
+ }
+
+ // FIXME: we will dispatch to a function that manipulates the state
+ // at the entrance to a block.
+
+ if (!Blk->empty()) {
+ // If 'Blk' has at least one statement, create a BlkStmtEdge and create
+ // the appropriate node. This is the common case.
+ getNode(BlkStmtEdge(Blk,Blk->front()), Pred->State, Pred);
+ }
+ else {
+ // Otherwise, create a node at the BlkStmtEdge right before the terminator
+ // (if any) is evaluated.
+ getNode(StmtBlkEdge(NULL,Blk),Pred->State, Pred);
+ }
+}
+
+void ReachabilityEngineImpl::ProcessBlkStmt(const BlkStmtEdge& E,
+ ExplodedNodeImpl* Pred) {
+ if (Stmt* S = E.Dst())
+ ProcessStmt(S,Pred);
+ else {
+ // No statement. Create an edge right before the terminator is evaluated.
+ getNode(StmtBlkEdge(NULL,E.Src()), Pred->State, Pred);
+ }
+}
+
+void ReachabilityEngineImpl::ProcessStmtBlk(const StmtBlkEdge& E,
+ ExplodedNodeImpl* Pred) {
+ CFGBlock* Blk = E.Dst();
+
+ if (Stmt* Terminator = Blk->getTerminator())
+ ProcessTerminator(Terminator,Pred);
+ else {
+ // No terminator. We should have only 1 successor.
+ assert (Blk->succ_size() == 1);
+ getNode(BlkBlkEdge(Blk,*(Blk->succ_begin())), Pred);
+ }
+}
Added: cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h?rev=45711&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h (added)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h Mon Jan 7 13:08:42 2008
@@ -0,0 +1,178 @@
+//===-- ExplodedGraph.h - Local, Path-Sensitive Supergraph -*- C++ -*------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the template class ExplodedGraph, which represents a
+// path-sensitive, intra-procedural dataflow "exploded graph."
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
+#define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
+
+#include "clang/Analysis/PathSensitive/ExplodedNode.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+
+class ReachabilityEngineImpl;
+
+class ExplodedGraphImpl {
+protected:
+ friend class ReachabilityEngineImpl;
+
+ // Type definitions.
+ typedef llvm::DenseMap<ProgramEdge,void*> EdgeNodeSetMap;
+ typedef llvm::SmallVector<ExplodedNodeImpl*,2> RootsTy;
+ typedef llvm::SmallVector<ExplodedNodeImpl*,10> EndNodesTy;
+
+ /// NodeCounter - The number of nodes that have been created, although
+ /// this need not be the current number of nodes in the graph that
+ /// are reachable from the roots. This counter is used to assign a unique
+ /// number to each node (which is useful for debugging).
+ unsigned NodeCounter;
+
+ /// Roots - The roots of the simulation graph. Usually there will be only
+ /// one, but clients are free to establish multiple subgraphs within a single
+ /// SimulGraph. Moreover, these subgraphs can often merge when paths from
+ /// different roots reach the same state at the same program location.
+ RootsTy Roots;
+
+ /// EndNodes - The nodes in the simulation graph which have been
+ /// specially marked as the endpoint of an abstract simulation path.
+ EndNodesTy EndNodes;
+
+ /// Nodes - A mapping from edges to nodes.
+ EdgeNodeSetMap Nodes;
+
+ /// Allocator - BumpPtrAllocator to create nodes.
+ llvm::BumpPtrAllocator Allocator;
+
+ /// 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 ReachabilityEngineImpl.
+ virtual ExplodedNodeImpl* getNodeImpl(const ProgramEdge& L, void* State,
+ bool& IsNew) = 0;
+
+ /// addRoot - Add an untyped node to the set of roots.
+ void addRoot(ExplodedNodeImpl* V) { Roots.push_back(V); }
+
+ /// addEndOfPath - Add an untyped node to the set of EOP nodes.
+ void addEndOfPath(ExplodedNodeImpl* V) { EndNodes.push_back(V); }
+
+public:
+ virtual ~ExplodedGraphImpl() {};
+
+ unsigned num_roots() const { return Roots.size(); }
+ unsigned num_eops() const { return EndNodes.size(); }
+ unsigned getCounter() const { return NodeCounter; }
+};
+
+template <typename STATE>
+class ExplodedGraph : public ExplodedGraphImpl {
+public:
+ typedef STATE StateTy;
+ typedef ExplodedNode<StateTy> NodeTy;
+
+protected:
+ virtual ExplodedNodeImpl*
+ getNodeImpl(const ProgramEdge& L, void* State, bool& IsNew) {
+ return getNode(L,ReachabilityTrait<StateTy>::toState(State),&IsNew);
+ }
+
+public:
+ virtual ~ExplodedGraph() {
+ // Delete the FoldingSet's in Nodes. Note that the contents
+ // of the FoldingSets are nodes allocated from the BumpPtrAllocator,
+ // so all of those will get nuked when that object is destroyed.
+ for (EdgeNodeSetMap::iterator I=Nodes.begin(), E=Nodes.end(); I!=E; ++I)
+ delete reinterpret_cast<llvm::FoldingSet<NodeTy>*>(I->second);
+ }
+
+ /// getNode - Retrieve the node associated with a (Location,State) pair,
+ /// where the 'Location' is a ProgramEdge 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 ProgramEdge& L, StateTy State, bool* IsNew = NULL) {
+
+ // Retrieve the node set associated with Loc.
+ llvm::FoldingSet<NodeTy>*& VSet =
+ reinterpret_cast<llvm::FoldingSet<NodeTy>*&>(Nodes[L]);
+
+ // Create the FoldingSet for the nodes if it does not exist yet.
+ if (!VSet) VSet = new llvm::FoldingSet<NodeTy>();
+
+ // Profile 'State' to determine if we already have an existing node.
+ llvm::FoldingSetNodeID profile;
+ void* InsertPos = 0;
+
+ StateTy::Profile(profile, State);
+ NodeTy* V = VSet.FindNodeOrInsertPos(profile,InsertPos);
+
+ if (!V) {
+ // Allocate a new node.
+ V = (NodeTy*) Allocator.Allocate<NodeTy>();
+ new (V) NodeTy(NodeCounter++,L,State);
+
+ // Insert the node into the node set and return it.
+ VSet.InsertNode(V,InsertPos);
+
+ 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;
+
+
+ roots_iterator roots_begin() {
+ return static_cast<NodeTy*>(Roots.begin());
+ }
+
+ roots_iterator roots_end() {
+ return static_cast<NodeTy*>(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 static_cast<NodeTy*>(EndNodes.begin());
+ }
+
+ eop_iterator eop_end() {
+ return static_cast<NodeTy*>(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();
+ }
+};
+
+} // end clang namespace
+
+#endif
Added: cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h?rev=45711&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h (added)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedNode.h Mon Jan 7 13:08:42 2008
@@ -0,0 +1,156 @@
+//=-- ExplodedNode.h - Local, Path-Sensitive Supergraph Vertices -*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the template class ExplodedNode which is used to
+// represent a node in the location*state "exploded graph" of an
+// intra-procedural, path-sensitive dataflow analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_EXPLODEDNODE
+#define LLVM_CLANG_ANALYSIS_EXPLODEDNODE
+
+#include "clang/Analysis/ProgramEdge.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang {
+
+class ReachabilityEngineImpl;
+
+class ExplodedNodeImpl : public llvm::FoldingSetNode {
+protected:
+ friend class ReachabilityEngineImpl;
+
+ /// nodeID - A unique ID for the node. This number indicates the
+ /// creation order of vertices, with lower numbers being created first.
+ /// The first created node has nodeID == 0.
+ const unsigned nodeID;
+
+ /// Location - The program location (within a function body) associated
+ /// with this node. The location is a 'ProgramEdge' in the CFG.
+ const ProgramEdge Location;
+
+ /// State - The state associated with this node. Normally this value
+ /// is immutable, but we anticipate there will be times when algorithms
+ /// that directly manipulate the analysis graph will need to change it.
+ void* State;
+
+ /// Preds - The predecessors of this node.
+ llvm::SmallVector<ExplodedNodeImpl*,2> Preds;
+
+ /// Succs - The successors of this node.
+ llvm::SmallVector<ExplodedNodeImpl*,2> Succs;
+
+ // FIXME: Preds and Succs only grow, not shrink. It would be nice
+ // if these were allocated from the same BumpPtrAllocator as
+ // the nodes themselves.
+
+ /// Construct a ExplodedNodeImpl with the given node ID, program edge,
+ /// and state.
+ explicit ExplodedNodeImpl(unsigned ID, const ProgramEdge& loc, void* state)
+ : nodeID(ID), Location(loc), State(state) {}
+
+ /// addUntypedPredeccessor - Adds a predecessor to the current node, and
+ /// in tandem add this node as a successor of the other node. This
+ /// "untyped" version is intended to be used only by ReachabilityEngineImpl;
+ /// normal clients should use 'addPredecessor' in ExplodedNode<>.
+ void addUntypedPredecessor(ExplodedNodeImpl* V) {
+ Preds.push_back(V);
+ V->Succs.push_back(V);
+ }
+
+public:
+ /// getLocation - Returns the edge associated with the given node.
+ const ProgramEdge& getLocation() const { return Location; }
+
+ /// getnodeID - Returns the unique ID of the node. These IDs reflect
+ /// the order in which vertices were generated by ReachabilityEngineImpl.
+ unsigned getnodeID() const { return nodeID; }
+};
+
+
+template <typename StateTy>
+struct ReachabilityTrait {
+ static inline void* toPtr(StateTy S) {
+ return reinterpret_cast<void*>(S);
+ }
+
+ static inline StateTy toState(void* P) {
+ return reinterpret_cast<StateTy>(P);
+ }
+};
+
+
+template <typename StateTy>
+class ExplodedNode : public ExplodedNodeImpl {
+public:
+ /// Construct a ExplodedNodeImpl with the given node ID, program edge,
+ /// and state.
+ explicit ExplodedNode(unsigned ID, const ProgramEdge& loc, StateTy state)
+ : ExplodedNodeImpl(ID,loc,ReachabilityTrait<StateTy>::toPtr(state)) {}
+
+ /// getState - Returns the state associated with the node.
+ inline StateTy getState() const {
+ return ReachabilityTrait<StateTy>::toState(State);
+ }
+
+ // Profiling (for FoldingSet).
+ inline void Profile(llvm::FoldingSetNodeID& ID) const {
+ StateTy::Profile(ID,getState());
+ }
+
+ // Iterators over successor and predecessor vertices.
+ typedef ExplodedNode* succ_iterator;
+ typedef const ExplodedNode* const_succ_iterator;
+ typedef ExplodedNode* pred_iterator;
+ typedef const ExplodedNode* const_pred_iterator;
+
+ pred_iterator pred_begin() {
+ return static_cast<pred_iterator>(Preds.begin());
+ }
+
+ pred_iterator pred_end() {
+ return static_cast<pred_iterator>(Preds.end());
+ }
+
+ const_pred_iterator pred_begin() const {
+ return static_cast<const_pred_iterator>(Preds.begin());
+ }
+
+ const_pred_iterator pred_end() const {
+ return static_cast<const_pred_iterator>(Preds.end());
+ }
+
+ succ_iterator succ_begin() {
+ return static_cast<succ_iterator>(Succs.begin());
+ }
+
+ succ_iterator succ_end() {
+ return static_cast<succ_iterator>(Succs.end());
+ }
+
+ const_succ_iterator succ_begin() const {
+ return static_cast<const_succ_iterator>(Succs.begin());
+ }
+
+ const_succ_iterator succ_end() const {
+ return static_cast<const_succ_iterator>(Succs.end());
+ }
+
+ unsigned succ_size() const { return Succs.size(); }
+ bool succ_empty() const { return Succs.empty(); }
+
+ unsigned pred_size() const { return Preds.size(); }
+ unsigned pred_empty() const { return Preds.empty(); }
+};
+
+} // end namespace clang
+
+#endif
Added: cfe/trunk/include/clang/Analysis/PathSensitive/ReachabilityEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ReachabilityEngine.h?rev=45711&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ReachabilityEngine.h (added)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ReachabilityEngine.h Mon Jan 7 13:08:42 2008
@@ -0,0 +1,172 @@
+//==- ReachabilityEngine.h - Path-Sens. Dataflow Engine ------------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a generic engine for intraprocedural, path-sensitive,
+// dataflow analysis via graph reachability engine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_REACHABILITYENGINE
+#define LLVM_CLANG_ANALYSIS_REACHABILITYENGINE
+
+#include "clang/AST/CFG.h"
+#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+
+namespace reng {
+ class WorkList {
+ public:
+ virtual ~WorkList();
+ virtual bool hasWork() const = 0;
+ virtual void Enqueue(ExplodedNodeImpl* V) = 0;
+ virtual ExplodedNodeImpl* Dequeue() = 0;
+ };
+
+ class DFS : public WorkList {
+ llvm::SmallVector<ExplodedNodeImpl*,20> Stack;
+ public:
+ virtual ~DFS();
+
+ virtual bool hasWork() const {
+ return !Stack.empty();
+ }
+
+ virtual void Enqueue(ExplodedNodeImpl* V) {
+ Stack.push_back(V);
+ }
+
+ virtual ExplodedNodeImpl* Dequeue() {
+ ExplodedNodeImpl* V = Stack.back();
+ Stack.pop_back();
+ return V;
+ }
+ };
+}
+
+class ReachabilityEngineImpl {
+protected:
+ typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
+
+ /// cfg - The control-flow graph of the function being analyzed.
+ CFG& cfg;
+
+ /// G - The simulation graph. Each node is a (location,state) pair.
+ llvm::OwningPtr<ExplodedGraphImpl> G;
+
+ /// ParentMap - A lazily populated map from a Stmt* to its parent Stmt*.
+ ParentMapTy ParentMap;
+
+ /// CurrentBlkExpr - The current Block-level expression being processed.
+ /// This is used when lazily populating ParentMap.
+ Stmt* CurrentBlkExpr;
+
+ /// 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
+ /// the order that nodes are processed.
+ llvm::OwningPtr<reng::WorkList> WList;
+
+ //==----------------------------------------------------------------------==//
+ // Internal methods.
+
+ /// getNode - Implemented by ReachabilityEngine<> subclass.
+ /// Creates/fetches a node and inserts it into the graph.
+ virtual void getNode(const ProgramEdge& Loc, void* State,
+ ExplodedNodeImpl* Pred);
+
+ inline void getNode(const ProgramEdge& Loc, ExplodedNodeImpl* Pred) {
+ getNode(Loc,Pred->State,Pred);
+ }
+
+ /// PopulateParentMap - Populates ParentMap starting from the specified
+ /// expression.
+ void PopulateParentMap(Stmt* Parent);
+
+ void ProcessBlkBlk(const BlkBlkEdge& E, ExplodedNodeImpl* Pred);
+ void ProcessBlkStmt(const BlkStmtEdge& E, ExplodedNodeImpl* Pred);
+ void ProcessStmtBlk(const StmtBlkEdge& E, ExplodedNodeImpl* Pred);
+
+ virtual void ProcessEOP(CFGBlock* Blk, ExplodedNodeImpl* Pred);
+ virtual void ProcessStmt(Stmt* S, ExplodedNodeImpl* Pred);
+ virtual void ProcessTerminator(Stmt* Terminator, ExplodedNodeImpl* Pred);
+
+private:
+ ReachabilityEngineImpl(const ReachabilityEngineImpl&); // Do not implement.
+ ReachabilityEngineImpl& operator=(const ReachabilityEngineImpl&);
+
+protected:
+ ReachabilityEngineImpl(CFG& c, reng::WorkList* wl);
+
+public:
+ /// 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 = 1000000);
+
+ virtual ~ReachabilityEngineImpl() {}
+};
+
+
+template<typename CHECKER>
+class ReachabilityEngine : public ReachabilityEngineImpl {
+public:
+ typedef CHECKER CheckerTy;
+ typedef typename CheckerTy::StateTy StateTy;
+ typedef typename CheckerTy::StateManagerTy StateManagerTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
+ typedef typename GraphTy::NodeTy NodeTy;
+
+protected:
+ virtual void ProcessEOP(CFGBlock* Blk, ExplodedNodeImpl* Pred) {
+ assert (false && "Not implemented yet.");
+ // FIXME: Perform dispatch to adjust state.
+// ExplodedNodeImpl* V = G->getNodeImpl(BlkStmtEdge(Blk,NULL),
+// Pred->State).first;
+
+// V->addPredecessor(Pred);
+// Graph.addEndOfPath(V);
+ }
+
+
+ virtual void ProcessStmt(Stmt* S, ExplodedNodeImpl* Pred) {
+ CurrentBlkExpr = S;
+ assert(false && "Not implemented.");
+ CurrentBlkExpr = NULL;
+ }
+
+ virtual void ProcessTerminator(Stmt* Terminator, ExplodedNodeImpl* Pred) {
+ assert(false && "Not implemented.");
+ }
+
+
+public:
+ /// Construct a ReachabilityEngine object to analyze the provided CFG using
+ /// a DFS exploration of the exploded graph.
+ ReachabilityEngine(CFG& Cfg)
+ : ReachabilityEngineImpl(cfg,new reng::DFS()) {}
+
+ /// Construct a ReachabilityEngine object to analyze the provided CFG and to
+ /// use the provided worklist object to execute the worklist algorithm.
+ /// The ReachabilityEngine object assumes ownership of 'wlist'.
+ ReachabilityEngine(CFG& cfg, reng::WorkList* wlist)
+ : ReachabilityEngineImpl(cfg,wlist) {}
+
+ /// getGraph - Returns the exploded graph. Ownership of the graph remains
+ /// with the ReachabilityEngine object.
+ GraphTy* getGraph() const { return static_cast<GraphTy*>(G.get()); }
+
+ /// takeGraph - Returns the exploded graph. Ownership of the graph is
+ /// transferred to the caller.
+ GraphTy* takeGraph() { return static_cast<GraphTy*>(G.take()); }
+};
+
+} // end clang namespace
+
+#endif
Removed: cfe/trunk/include/clang/Analysis/PathSensitive/SimulEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/SimulEngine.h?rev=45710&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/SimulEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/SimulEngine.h (removed)
@@ -1,121 +0,0 @@
-//==-- SimulEngine.h - Local, Path-Sensitive Dataflow Engine ------*- C++ -*--//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the template class SimulEngine, a generic path-sensitive
-// dataflow engine for intra-procedural path-sensitive analyses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_PS_SIMULENGINE
-#define LLVM_CLANG_ANALYSIS_PS_SIMULENGINE
-
-#include "clang/Analysis/PathSensitive/SimulVertex.h"
-#include "clang/Analysis/PathSensitive/SimulGraph.h"
-#include "clang/AST/CFG.h"
-#include "llvm/ADT/OwningPtr.h"
-
-namespace clang {
- namespace simwlist {
- class DFS;
- class BFS;
- }
-
-
-template <typename VertexTy,
- typename TransferFuncs,
- typename WListTy = simwlist::DFS >
-class SimulEngine {
-public:
- typedef SimulGraph<VertexTy> SimulationGraph;
- typedef WListTy WorkList;
-
-protected:
- /// func - the FunctionDecl for the function being analyzed. SimulEngine
- /// does not own this object.
- FunctionDecl* func;
-
- /// cfg - The cfg for the function being analyzed. Note that SimulEngine
- /// only conditionally owns the CFG object. If no CFG is specified during
- /// the creation of the SimulEngine object, one is created from
- /// a provided FunctionDecl* representing the function body. This cfg
- /// is then owned by SimulEngine.
- CFG* cfg;
- bool OwnsCFG;
-
- /// SGraph - The simulation graph.
- llvm::OwningPtr<SimulationGraph> SGraph;
-
- /// WList - The simulation worklist.
- WorkList WList;
-
-public:
- /// Construct a SimulEngine object from the
- SimulEngine(FunctionDecl* fd, CFG* c = NULL)
- : func(fd),
- cfg(c ? c : CFG::buildCFG(fd)), OwnsCFG(c == NULL),
- SGraph(new SimulationGraph()) {
-
- assert (fd && "Cannot provide NULL FunctionDecl for analysis!")
- assert (fd->getBody() && "FunctionDecl must have a body!")
- }
-
- /// execute - Run the simulation. If the SimulationGraph contains no
- /// vertices, the simulation starts from the entrace of the function.
- /// If the worklist is not empty, the simulation resumes from where it
- /// left off. Steps specifies the maximum number of simulation steps
- /// to take, which is roughly the number of statements visited.
- bool execute(unsigned Steps = 100000) {
-
- if (SGraph->getCounter() == 0) {
- assert (WList.empty() &&
- "Simulation graph is empty but the worklist is not!");
-
- // Enqueue roots onto worklist.
- assert (false && "FIXME");
- }
- else if (WList.empty())
- return false; // Do nothing. Nothing left to do.
-
- while (Steps-- > 0 && !WList.empty()) {
- VertexTy* V = static_cast<VertexTy*>(WList.dequeue());
- const ProgramEdge& E = V->getEdge();
-
- switch(E.getKind()) {
- // FIXME: need to handle different edges.
-
- }
- }
-
- return !WList.empty();
- }
-
- /// getGraph - Return the simulation graph.
- SimulationGraph& getGraph() {
- assert (SGraph && "Cannot return NULL SimulationGraph.")
- return *SGraph;
- }
-
- const SimulationGraph& getGraph() const {
- assert (SGraph && "Cannot return NULL SimulationGraph.")
- return *SGraph;
- }
-
- /// takeGraph - Return the simulation graph. Ownership of the graph is
- /// transferred to the caller, and later calls to getSimGraph() and
- // takeSimGraph() will fail.
- SimulationGraph* takeGraph() { return SGraph.take(); }
-
- /// getWorkList - Returns the simulation worklist.
- WorkList& getWorkList() { return WList; }
- const WorkList& getWorkList() const { return WList; }
-};
-
-} // end clang namespace
-
-#endif
Removed: cfe/trunk/include/clang/Analysis/PathSensitive/SimulGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/SimulGraph.h?rev=45710&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/SimulGraph.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/SimulGraph.h (removed)
@@ -1,125 +0,0 @@
-//==-- SimulGraph.h - Local, Path-Sensitive Supergraph -*- C++ -*-----------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the template class SimulVGraph, which represents a
-// path-sensitive, intra-procedural dataflow supergraph.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_PS_LOCAL_SUPERGRAPH
-#define LLVM_CLANG_ANALYSIS_PS_LOCAL_SUPERGRAPH
-
-#include "clang/Analysis/PathSensitive/SimulVertex.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/Allocator.h"
-
-namespace clang {
-
-template <typename VertexTy>
-class SimulGraph {
- // Type definitions.
- typedef llvm::FoldingSet<VertexTy> VertexSet;
- typedef llvm::DenseMap<ProgramEdge,VertexSet> EdgeVertexSetMap;
- typedef llvm::SmallVector<VertexTy*,2> RootsTy;
- typedef llvm::SmallVector<VertexTy*,10> EndVerticesTy;
-
- /// VertexCounter - The number of vertices that have been created, although
- /// this need not be the current number of vertices in the graph that
- /// are reachable from the roots. This counter is used to assign a unique
- /// number to each vertex (which is useful for debugging).
- unsigned VertexCounter;
-
- /// Roots - The roots of the simulation graph. Usually there will be only
- /// one, but clients are free to establish multiple subgraphs within a single
- /// SimulGraph. Moreover, these subgraphs can often merge when paths from
- /// different roots reach the same state at the same program location.
- RootsTy Roots;
-
- /// EndVertices - The vertices in the simulation graph which have been
- /// specially marked as the endpoint of an abstract simulation path.
- EndVerticesTy EndVertices;
-
- /// VerticesOfEdge - A mapping from edges to vertices.
- EdgeVertexSetMap VerticesOfEdge;
-
- /// Allocator - BumpPtrAllocator to create vertices.
- llvm::BumpPtrAllocator Allocator;
-
-public:
- SimulGraph() : VertexCounter(0) {}
-
- /// getVertex - Retrieve the vertex associated with a (Location,State) pair,
- /// where the 'Location' is a ProgramEdge in the CFG. If no vertex for
- /// this pair exists, it is created. The bool returned in the pair
- /// is true if the vertex was freshly created.
- std::pair<VertexTy*,bool> getVertex(const ProgramEdge& L,
- typename VertexTy::StateTy State) {
-
- // Retrieve the vertex set associated with Loc.
- VertexSet& VSet = VerticesOfEdge[L];
-
- // Profile 'State' to determine if we already have an existing vertex.
- // Note: this assumes that a vertex's profile matches with its state,
- // which is the case when VertexTy == SimulVertex. (other implementations
- // must guarantee this invariant)
- llvm::FoldingSetNodeID profile;
- void* InsertPos = 0;
- VertexTy* V = 0;
-
- VertexTy::StateTy::Profile(profile, State);
-
- if ((V = VSet.FindNodeOrInsertPos(profile,InsertPos)))
- return std::make_pair(V,false);
-
- // No cache hit. Allocate a new vertex.
- V = (VertexTy*) Allocator.Allocate<VertexTy>();
- new (V) VertexTy(VertexCounter++,L,State);
-
- // Insert the vertex into the vertex set and return it.
- VSet.InsertNode(V,InsertPos);
-
- return std::make_pair(V,true);
- }
-
- /// addRoot - Add a vertex to the set of roots.
- void addRoot(VertexTy* V) {
- Roots.push_back(V);
- }
-
- void addEndOfPath(VertexTy* V) {
- EndVertices.push_back(V);
- }
-
- unsigned num_roots() const { return Roots.size(); }
- unsigned num_eops() const { return EndVertices.size(); }
- unsigned getCounter() const { return VertexCounter; }
-
- // Iterators.
- typedef typename RootsTy::iterator roots_iterator;
- typedef typename RootsTy::const_iterator const_roots_iterator;
-
- 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(); }
-
- typedef typename EndVerticesTy::iterator eop_iterator;
- typedef typename EndVerticesTy::const_iterator const_eop_iterator;
-
- eop_iterator eop_begin() { return EndVertices.begin(); }
- eop_iterator eop_end() { return EndVertices.end(); }
- const_eop_iterator eop_begin() const { return EndVertices.begin(); }
- const_eop_iterator eop_end() const { return EndVertices.end(); }
-};
-
-} // end clang namespace
-
-#endif
Removed: cfe/trunk/include/clang/Analysis/PathSensitive/SimulVertex.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/SimulVertex.h?rev=45710&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/SimulVertex.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/SimulVertex.h (removed)
@@ -1,104 +0,0 @@
-//=- SimulVertex.h - Local, Path-Sensitive Supergraph Vertices -*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the template class SimulVertex which is used to
-// represent a vertex in the location*state supergraph of an intra-procedural,
-// path-sensitive dataflow analysis.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_PS_ANALYSISVERTEX
-#define LLVM_CLANG_ANALYSIS_PS_ANALYSISVERTEX
-
-#include "clang/Analysis/ProgramEdge.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/FoldingSet.h"
-
-namespace clang {
-
-// *** NOTE ***
-// In the future we may not use a fully templated-implementation. We'll first
-// see how the needed functionality develops and then refactor later.
-
-template <typename StateType>
-class SimulVertex : public llvm::FoldingSetNode {
-public:
- typedef StateType StateTy;
-
-private:
- /// VertexID - A unique ID for the vertex. This number indicates the
- /// creation order of vertices, with lower numbers being created first.
- /// The first created vertex has VertexID == 0.
- const unsigned VertexID;
-
- /// Location - The program edge representing the location in the function body
- /// that this vertex corresponds to.
- const ProgramEdge Location;
-
- /// State - The state associated with this vertex. Normally this value
- /// is immutable, but we anticipate there will be times when algorithms
- /// that directly manipulate the analysis graph will need to change it.
- StateTy State;
-
- /// Predecessors/Successors - Keep track of the predecessor/successor
- /// vertices.
-
- // FIXME: Preds and Succs only grows, not shrinks. It would be nice
- // if these lists were allocated from the same BumpPtrAllocator as
- // the vertices themselves.
- typedef llvm::SmallVector<SimulVertex*,2> AdjacentVertices;
- AdjacentVertices Preds;
- AdjacentVertices Succs;
-
-public:
- explicit SimulVertex(unsigned ID, const ProgramEdge& loc, StateTy state)
- : VertexID(ID), Location(loc), State(state) {}
-
- // Accessors.
- const StateTy& getState() const { return State; }
- const ProgramEdge& getLocation() const { return Location; }
- unsigned getVertexID() const { return VertexID; }
-
- // Profiling (for FoldingSet).
- void Profile(llvm::FoldingSetNodeID& ID) const {
- StateTy::Profile(ID,getState());
- }
-
- // Iterators over successor and predecessor vertices.
- typedef typename AdjacentVertices::iterator succ_iterator;
- typedef typename AdjacentVertices::const_iterator const_succ_iterator;
- typedef typename AdjacentVertices::iterator pred_iterator;
- typedef typename AdjacentVertices::const_iterator const_pred_iterator;
-
- pred_iterator pred_begin() { return Preds.begin(); }
- pred_iterator pred_end() { return Preds.end(); }
- const_pred_iterator pred_begin() const { return Preds.begin(); }
- const_pred_iterator pred_end() const { return Preds.end(); }
-
- succ_iterator succ_begin() { return Succs.begin(); }
- succ_iterator succ_end() { return Succs.end(); }
- const_succ_iterator succ_begin() const { return Succs.begin(); }
- const_succ_iterator succ_end() const { return Succs.end(); }
-
- unsigned succ_size() const { return Succs.size(); }
- bool succ_empty() const { return Succs.empty(); }
-
- unsigned pred_size() const { return Preds.size(); }
- unsigned pred_empty() const { return Preds.empty(); }
-
- // Manipulation of successors/predecessors.
- void addPredecessor(SimulVertex* V) {
- Preds.push_back(V);
- V->Succs.push_back(V);
- }
-};
-
-} // end namespace clang
-
-#endif
More information about the cfe-commits
mailing list