[cfe-commits] r162154 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h lib/StaticAnalyzer/Core/ExplodedGraph.cpp

Jordan Rose jordan_rose at apple.com
Fri Aug 17 17:30:11 PDT 2012


Author: jrose
Date: Fri Aug 17 19:30:10 2012
New Revision: 162154

URL: http://llvm.org/viewvc/llvm-project?rev=162154&view=rev
Log:
[analyzer] Use PointerUnion to implement ExplodedNode::NodeGroup.

We shouldn't be reinventing our own wheels. This also paves the way for
marking different kinds of sinks.

No functionality change.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
    cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h?rev=162154&r1=162153&r2=162154&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h Fri Aug 17 19:30:10 2012
@@ -61,44 +61,30 @@
   friend class EndOfFunctionNodeBuilder;
 
   class NodeGroup {
-    enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
+    // Conceptually a discriminated union. If the low bit is set, the node is
+    // a sink. If the low bit is not set, the pointer refers to the storage
+    // for the nodes in the group.
     uintptr_t P;
-
-    unsigned getKind() const {
-      return P & 0x1;
-    }
-
-    void *getPtr() const {
-      assert (!getFlag());
-      return reinterpret_cast<void*>(P & ~Mask);
-    }
-
-    ExplodedNode *getNode() const {
-      return reinterpret_cast<ExplodedNode*>(getPtr());
-    }
     
   public:
-    NodeGroup() : P(0) {}
+    NodeGroup(bool Flag = false) : P(Flag) {
+      assert(getFlag() == Flag);
+    }
 
-    ExplodedNode **begin() const;
+    ExplodedNode * const *begin() const;
 
-    ExplodedNode **end() const;
+    ExplodedNode * const *end() const;
 
     unsigned size() const;
 
-    bool empty() const { return (P & ~Mask) == 0; }
+    bool empty() const { return P == 0 || getFlag() != 0; }
 
     void addNode(ExplodedNode *N, ExplodedGraph &G);
 
     void replaceNode(ExplodedNode *node);
 
-    void setFlag() {
-      assert(P == 0);
-      P = AuxFlag;
-    }
-
     bool getFlag() const {
-      return P & AuxFlag ? true : false;
+      return (P & 1);
     }
   };
 
@@ -119,9 +105,8 @@
 
   explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
                         bool IsSink)
-    : Location(loc), State(state) {
-    if (IsSink)
-      Succs.setFlag();
+    : Location(loc), State(state), Succs(IsSink) {
+    assert(isSink() == IsSink);
   }
   
   ~ExplodedNode() {}
@@ -190,9 +175,9 @@
   }
 
   // Iterators over successor and predecessor vertices.
-  typedef ExplodedNode**       succ_iterator;
+  typedef ExplodedNode*       const *       succ_iterator;
   typedef const ExplodedNode* const * const_succ_iterator;
-  typedef ExplodedNode**       pred_iterator;
+  typedef ExplodedNode*       const *       pred_iterator;
   typedef const ExplodedNode* const * const_pred_iterator;
 
   pred_iterator pred_begin() { return Preds.begin(); }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp?rev=162154&r1=162153&r2=162154&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExplodedGraph.cpp Fri Aug 17 19:30:10 2012
@@ -162,9 +162,8 @@
 // ExplodedNode.
 //===----------------------------------------------------------------------===//
 
-static inline BumpVector<ExplodedNode*>& getVector(void *P) {
-  return *reinterpret_cast<BumpVector<ExplodedNode*>*>(P);
-}
+typedef BumpVector<ExplodedNode *> ExplodedNodeVector;
+typedef llvm::PointerUnion<ExplodedNode *, ExplodedNodeVector *> GroupStorage;
 
 void ExplodedNode::addPredecessor(ExplodedNode *V, ExplodedGraph &G) {
   assert (!V->isSink());
@@ -176,71 +175,75 @@
 }
 
 void ExplodedNode::NodeGroup::replaceNode(ExplodedNode *node) {
-  assert(getKind() == Size1);
-  P = reinterpret_cast<uintptr_t>(node);
-  assert(getKind() == Size1);
+  GroupStorage &Storage = reinterpret_cast<GroupStorage&>(P);
+  assert(Storage.is<ExplodedNode *>());
+  Storage = node;
+  assert(Storage.is<ExplodedNode *>());
 }
 
 void ExplodedNode::NodeGroup::addNode(ExplodedNode *N, ExplodedGraph &G) {
-  assert((reinterpret_cast<uintptr_t>(N) & Mask) == 0x0);
   assert(!getFlag());
 
-  if (getKind() == Size1) {
-    if (ExplodedNode *NOld = getNode()) {
-      BumpVectorContext &Ctx = G.getNodeAllocator();
-      BumpVector<ExplodedNode*> *V = 
-        G.getAllocator().Allocate<BumpVector<ExplodedNode*> >();
-      new (V) BumpVector<ExplodedNode*>(Ctx, 4);
-      
-      assert((reinterpret_cast<uintptr_t>(V) & Mask) == 0x0);
-      V->push_back(NOld, Ctx);
-      V->push_back(N, Ctx);
-      P = reinterpret_cast<uintptr_t>(V) | SizeOther;
-      assert(getPtr() == (void*) V);
-      assert(getKind() == SizeOther);
-    }
-    else {
-      P = reinterpret_cast<uintptr_t>(N);
-      assert(getKind() == Size1);
-    }
+  GroupStorage &Storage = reinterpret_cast<GroupStorage&>(P);
+  if (Storage.isNull()) {
+    Storage = N;
+    assert(Storage.is<ExplodedNode *>());
+    return;
   }
-  else {
-    assert(getKind() == SizeOther);
-    getVector(getPtr()).push_back(N, G.getNodeAllocator());
+
+  ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>();
+
+  if (!V) {
+    // Switch from single-node to multi-node representation.
+    ExplodedNode *Old = Storage.get<ExplodedNode *>();
+
+    BumpVectorContext &Ctx = G.getNodeAllocator();
+    V = G.getAllocator().Allocate<ExplodedNodeVector>();
+    new (V) ExplodedNodeVector(Ctx, 4);
+    V->push_back(Old, Ctx);
+
+    Storage = V;
+    assert(!getFlag());
+    assert(Storage.is<ExplodedNodeVector *>());
   }
+
+  V->push_back(N, G.getNodeAllocator());
 }
 
 unsigned ExplodedNode::NodeGroup::size() const {
   if (getFlag())
     return 0;
 
-  if (getKind() == Size1)
-    return getNode() ? 1 : 0;
-  else
-    return getVector(getPtr()).size();
+  const GroupStorage &Storage = reinterpret_cast<const GroupStorage &>(P);
+  if (Storage.isNull())
+    return 0;
+  if (ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>())
+    return V->size();
+  return 1;
 }
 
-ExplodedNode **ExplodedNode::NodeGroup::begin() const {
+ExplodedNode * const *ExplodedNode::NodeGroup::begin() const {
   if (getFlag())
-    return NULL;
+    return 0;
 
-  if (getKind() == Size1)
-    return (ExplodedNode**) (getPtr() ? &P : NULL);
-  else
-    return const_cast<ExplodedNode**>(&*(getVector(getPtr()).begin()));
+  const GroupStorage &Storage = reinterpret_cast<const GroupStorage &>(P);
+  if (Storage.isNull())
+    return 0;
+  if (ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>())
+    return V->begin();
+  return Storage.getAddrOfPtr1();
 }
 
-ExplodedNode** ExplodedNode::NodeGroup::end() const {
+ExplodedNode * const *ExplodedNode::NodeGroup::end() const {
   if (getFlag())
-    return NULL;
+    return 0;
 
-  if (getKind() == Size1)
-    return (ExplodedNode**) (getPtr() ? &P+1 : NULL);
-  else {
-    // Dereferencing end() is undefined behaviour. The vector is not empty, so
-    // we can dereference the last elem and then add 1 to the result.
-    return const_cast<ExplodedNode**>(getVector(getPtr()).end());
-  }
+  const GroupStorage &Storage = reinterpret_cast<const GroupStorage &>(P);
+  if (Storage.isNull())
+    return 0;
+  if (ExplodedNodeVector *V = Storage.dyn_cast<ExplodedNodeVector *>())
+    return V->end();
+  return Storage.getAddrOfPtr1() + 1;
 }
 
 ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L,
@@ -338,7 +341,8 @@
     }
 
     // Visit our predecessors and enqueue them.
-    for (ExplodedNode** I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I)
+    for (ExplodedNode::pred_iterator I = N->Preds.begin(), E = N->Preds.end();
+         I != E; ++I)
       WL1.push_back(*I);
   }
 
@@ -375,7 +379,8 @@
 
     // Walk through the predecessors of 'N' and hook up their corresponding
     // nodes in the new graph (if any) to the freshly created node.
-    for (ExplodedNode **I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I) {
+    for (ExplodedNode::pred_iterator I = N->Preds.begin(), E = N->Preds.end();
+         I != E; ++I) {
       Pass2Ty::iterator PI = Pass2.find(*I);
       if (PI == Pass2.end())
         continue;
@@ -387,7 +392,8 @@
     // been created, we should hook them up as successors.  Otherwise, enqueue
     // the new nodes from the original graph that should have nodes created
     // in the new graph.
-    for (ExplodedNode **I=N->Succs.begin(), **E=N->Succs.end(); I!=E; ++I) {
+    for (ExplodedNode::succ_iterator I = N->Succs.begin(), E = N->Succs.end();
+         I != E; ++I) {
       Pass2Ty::iterator PI = Pass2.find(*I);
       if (PI != Pass2.end()) {
         PI->second->addPredecessor(NewN, *G);





More information about the cfe-commits mailing list