diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h')
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h | 74 |
1 files changed, 41 insertions, 33 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index 1052d9491a96..b112e66d30d3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -60,45 +60,50 @@ class ExplodedNode : public llvm::FoldingSetNode { friend class SwitchNodeBuilder; friend class EndOfFunctionNodeBuilder; + /// Efficiently stores a list of ExplodedNodes, or an optional flag. + /// + /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing + /// for the case when there is only one node in the group. This is a fairly + /// common case in an ExplodedGraph, where most nodes have only one + /// predecessor and many have only one successor. It can also be used to + /// store a flag rather than a node list, which ExplodedNode uses to mark + /// whether a node is a sink. If the flag is set, the group is implicitly + /// empty and no nodes may be added. 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. + // This is not a PointerIntPair in order to keep the storage type opaque. 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; } + /// Adds a node to the list. + /// + /// The group must not have been created with its flag set. void addNode(ExplodedNode *N, ExplodedGraph &G); + /// Replaces the single node in this group with a new node. + /// + /// Note that this should only be used when you know the group was not + /// created with its flag set, and that the group is empty or contains + /// only a single node. void replaceNode(ExplodedNode *node); - void setFlag() { - assert(P == 0); - P = AuxFlag; - } - + /// Returns whether this group was created with its flag set. bool getFlag() const { - return P & AuxFlag ? true : false; + return (P & 1); } }; @@ -119,9 +124,8 @@ public: 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 +194,9 @@ public: } // 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(); } @@ -278,11 +282,13 @@ protected: /// A list of nodes that can be reused. NodeVector FreeNodes; - /// A flag that indicates whether nodes should be recycled. - bool reclaimNodes; + /// Determines how often nodes are reclaimed. + /// + /// If this is 0, nodes will never be reclaimed. + unsigned ReclaimNodeInterval; /// Counter to determine when to reclaim nodes. - unsigned reclaimCounter; + unsigned ReclaimCounter; public: @@ -370,7 +376,9 @@ public: /// Enable tracking of recently allocated nodes for potential reclamation /// when calling reclaimRecentlyAllocatedNodes(). - void enableNodeReclamation() { reclaimNodes = true; } + void enableNodeReclamation(unsigned Interval) { + ReclaimCounter = ReclaimNodeInterval = Interval; + } /// Reclaim "uninteresting" nodes created since the last time this method /// was called. |