aboutsummaryrefslogtreecommitdiff
path: root/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h')
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h74
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.