[cfe-commits] r162154 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h lib/StaticAnalyzer/Core/ExplodedGraph.cpp
Anna Zaks
ganna at apple.com
Mon Aug 20 11:19:04 PDT 2012
On Aug 17, 2012, at 5:30 PM, Jordan Rose wrote:
> 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;
>
Great refactor!
Could you add some documentation of what the NodeGroup is. The comment below is doing that somewhat but it talks in terms of implementation (what P is) not definition. Also would be good to add comments for all the APIs inside the NodeGroup.
> 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);
> }
This is isSink, right?
> };
>
> @@ -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);
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list