clang 19.0.0git
ExplodedGraph.h
Go to the documentation of this file.
1//===- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the template classes ExplodedNode and ExplodedGraph,
10// which represent a path-sensitive, intra-procedural "exploded graph."
11// See "Precise interprocedural dataflow analysis via graph reachability"
12// by Reps, Horwitz, and Sagiv
13// (http://portal.acm.org/citation.cfm?id=199462) for the definition of an
14// exploded graph.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
19#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
20
24#include "clang/Basic/LLVM.h"
28#include "llvm/ADT/ArrayRef.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/DepthFirstIterator.h"
31#include "llvm/ADT/FoldingSet.h"
32#include "llvm/ADT/GraphTraits.h"
33#include "llvm/ADT/STLExtras.h"
34#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/iterator_range.h"
36#include "llvm/Support/Allocator.h"
37#include "llvm/Support/Compiler.h"
38#include <cassert>
39#include <cstdint>
40#include <memory>
41#include <optional>
42#include <utility>
43#include <vector>
44
45namespace clang {
46
47class CFG;
48class Decl;
49class Expr;
50class ParentMap;
51class Stmt;
52
53namespace ento {
54
55class ExplodedGraph;
56
57//===----------------------------------------------------------------------===//
58// ExplodedGraph "implementation" classes. These classes are not typed to
59// contain a specific kind of state. Typed-specialized versions are defined
60// on top of these classes.
61//===----------------------------------------------------------------------===//
62
63// ExplodedNode is not constified all over the engine because we need to add
64// successors to it at any time after creating it.
65
66class ExplodedNode : public llvm::FoldingSetNode {
67 friend class BranchNodeBuilder;
68 friend class CoreEngine;
70 friend class ExplodedGraph;
72 friend class NodeBuilder;
73 friend class SwitchNodeBuilder;
74
75 /// Efficiently stores a list of ExplodedNodes, or an optional flag.
76 ///
77 /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing
78 /// for the case when there is only one node in the group. This is a fairly
79 /// common case in an ExplodedGraph, where most nodes have only one
80 /// predecessor and many have only one successor. It can also be used to
81 /// store a flag rather than a node list, which ExplodedNode uses to mark
82 /// whether a node is a sink. If the flag is set, the group is implicitly
83 /// empty and no nodes may be added.
84 class NodeGroup {
85 // Conceptually a discriminated union. If the low bit is set, the node is
86 // a sink. If the low bit is not set, the pointer refers to the storage
87 // for the nodes in the group.
88 // This is not a PointerIntPair in order to keep the storage type opaque.
90
91 public:
92 NodeGroup(bool Flag = false) : P(Flag) {
93 assert(getFlag() == Flag);
94 }
95
96 ExplodedNode * const *begin() const;
97
98 ExplodedNode * const *end() const;
99
100 unsigned size() const;
101
102 bool empty() const { return P == 0 || getFlag() != 0; }
103
104 /// Adds a node to the list.
105 ///
106 /// The group must not have been created with its flag set.
107 void addNode(ExplodedNode *N, ExplodedGraph &G);
108
109 /// Replaces the single node in this group with a new node.
110 ///
111 /// Note that this should only be used when you know the group was not
112 /// created with its flag set, and that the group is empty or contains
113 /// only a single node.
114 void replaceNode(ExplodedNode *node);
115
116 /// Returns whether this group was created with its flag set.
117 bool getFlag() const {
118 return (P & 1);
119 }
120 };
121
122 /// Location - The program location (within a function body) associated
123 /// with this node.
124 const ProgramPoint Location;
125
126 /// State - The state associated with this node.
127 ProgramStateRef State;
128
129 /// Preds - The predecessors of this node.
130 NodeGroup Preds;
131
132 /// Succs - The successors of this node.
133 NodeGroup Succs;
134
135 int64_t Id;
136
137public:
138 explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
139 int64_t Id, bool IsSink)
140 : Location(loc), State(std::move(state)), Succs(IsSink), Id(Id) {
141 assert(isSink() == IsSink);
142 }
143
144 /// getLocation - Returns the edge associated with the given node.
145 ProgramPoint getLocation() const { return Location; }
146
149 }
150
152 return getLocation().getStackFrame();
153 }
154
155 const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
156
157 CFG &getCFG() const { return *getLocationContext()->getCFG(); }
158
159 const CFGBlock *getCFGBlock() const;
160
161 const ParentMap &getParentMap() const {
163 }
164
165 template <typename T> T &getAnalysis() const {
166 return *getLocationContext()->getAnalysis<T>();
167 }
168
169 const ProgramStateRef &getState() const { return State; }
170
171 template <typename T> std::optional<T> getLocationAs() const & {
172 return Location.getAs<T>();
173 }
174
175 /// Get the value of an arbitrary expression at this node.
176 SVal getSVal(const Stmt *S) const {
177 return getState()->getSVal(S, getLocationContext());
178 }
179
180 static void Profile(llvm::FoldingSetNodeID &ID,
181 const ProgramPoint &Loc,
182 const ProgramStateRef &state,
183 bool IsSink) {
184 ID.Add(Loc);
185 ID.AddPointer(state.get());
186 ID.AddBoolean(IsSink);
187 }
188
189 void Profile(llvm::FoldingSetNodeID& ID) const {
190 // We avoid copy constructors by not using accessors.
191 Profile(ID, Location, State, isSink());
192 }
193
194 /// addPredeccessor - Adds a predecessor to the current node, and
195 /// in tandem add this node as a successor of the other node.
197
198 unsigned succ_size() const { return Succs.size(); }
199 unsigned pred_size() const { return Preds.size(); }
200 bool succ_empty() const { return Succs.empty(); }
201 bool pred_empty() const { return Preds.empty(); }
202
203 bool isSink() const { return Succs.getFlag(); }
204
205 bool hasSinglePred() const {
206 return (pred_size() == 1);
207 }
208
210 return pred_empty() ? nullptr : *(pred_begin());
211 }
212
213 const ExplodedNode *getFirstPred() const {
214 return const_cast<ExplodedNode*>(this)->getFirstPred();
215 }
216
218 return succ_empty() ? nullptr : *(succ_begin());
219 }
220
221 const ExplodedNode *getFirstSucc() const {
222 return const_cast<ExplodedNode*>(this)->getFirstSucc();
223 }
224
225 // Iterators over successor and predecessor vertices.
226 using succ_iterator = ExplodedNode * const *;
227 using succ_range = llvm::iterator_range<succ_iterator>;
228
229 using const_succ_iterator = const ExplodedNode * const *;
230 using const_succ_range = llvm::iterator_range<const_succ_iterator>;
231
232 using pred_iterator = ExplodedNode * const *;
233 using pred_range = llvm::iterator_range<pred_iterator>;
234
235 using const_pred_iterator = const ExplodedNode * const *;
236 using const_pred_range = llvm::iterator_range<const_pred_iterator>;
237
238 pred_iterator pred_begin() { return Preds.begin(); }
239 pred_iterator pred_end() { return Preds.end(); }
240 pred_range preds() { return {Preds.begin(), Preds.end()}; }
241
243 return const_cast<ExplodedNode*>(this)->pred_begin();
244 }
246 return const_cast<ExplodedNode*>(this)->pred_end();
247 }
248 const_pred_range preds() const { return {Preds.begin(), Preds.end()}; }
249
250 succ_iterator succ_begin() { return Succs.begin(); }
251 succ_iterator succ_end() { return Succs.end(); }
252 succ_range succs() { return {Succs.begin(), Succs.end()}; }
253
255 return const_cast<ExplodedNode*>(this)->succ_begin();
256 }
258 return const_cast<ExplodedNode*>(this)->succ_end();
259 }
260 const_succ_range succs() const { return {Succs.begin(), Succs.end()}; }
261
262 int64_t getID() const { return Id; }
263
264 /// The node is trivial if it has only one successor, only one predecessor,
265 /// it's predecessor has only one successor,
266 /// and its program state is the same as the program state of the previous
267 /// node.
268 /// Trivial nodes may be skipped while printing exploded graph.
269 bool isTrivial() const;
270
271 /// If the node's program point corresponds to a statement, retrieve that
272 /// statement. Useful for figuring out where to put a warning or a note.
273 /// If the statement belongs to a body-farmed definition,
274 /// retrieve the call site for that definition.
275 const Stmt *getStmtForDiagnostics() const;
276
277 /// Find the next statement that was executed on this node's execution path.
278 /// Useful for explaining control flow that follows the current node.
279 /// If the statement belongs to a body-farmed definition, retrieve the
280 /// call site for that definition.
281 const Stmt *getNextStmtForDiagnostics() const;
282
283 /// Find the statement that was executed immediately before this node.
284 /// Useful when the node corresponds to a CFG block entrance.
285 /// If the statement belongs to a body-farmed definition, retrieve the
286 /// call site for that definition.
287 const Stmt *getPreviousStmtForDiagnostics() const;
288
289 /// Find the statement that was executed at or immediately before this node.
290 /// Useful when any nearby statement will do.
291 /// If the statement belongs to a body-farmed definition, retrieve the
292 /// call site for that definition.
294
295private:
296 void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
297 void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
298};
299
301 llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>;
302
304protected:
305 friend class CoreEngine;
306
307 // Type definitions.
308 using NodeVector = std::vector<ExplodedNode *>;
309
310 /// The roots of the simulation graph. Usually there will be only
311 /// one, but clients are free to establish multiple subgraphs within a single
312 /// SimulGraph. Moreover, these subgraphs can often merge when paths from
313 /// different roots reach the same state at the same program location.
315
316 /// The nodes in the simulation graph which have been
317 /// specially marked as the endpoint of an abstract simulation path.
319
320 /// Nodes - The nodes in the graph.
321 llvm::FoldingSet<ExplodedNode> Nodes;
322
323 /// BVC - Allocator and context for allocating nodes and their predecessor
324 /// and successor groups.
326
327 /// NumNodes - The number of nodes in the graph.
328 int64_t NumNodes = 0;
329
330 /// A list of recently allocated nodes that can potentially be recycled.
332
333 /// A list of nodes that can be reused.
335
336 /// Determines how often nodes are reclaimed.
337 ///
338 /// If this is 0, nodes will never be reclaimed.
340
341 /// Counter to determine when to reclaim nodes.
343
344public:
347
348 /// Retrieve the node associated with a (Location,State) pair,
349 /// where the 'Location' is a ProgramPoint in the CFG. If no node for
350 /// this pair exists, it is created. IsNew is set to true if
351 /// the node was freshly created.
353 bool IsSink = false,
354 bool* IsNew = nullptr);
355
356 /// Create a node for a (Location, State) pair,
357 /// but don't store it for deduplication later. This
358 /// is useful when copying an already completed
359 /// ExplodedGraph for further processing.
361 ProgramStateRef State,
362 int64_t Id,
363 bool IsSink = false);
364
365 std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
366 return std::make_unique<ExplodedGraph>();
367 }
368
369 /// addRoot - Add an untyped node to the set of roots.
371 Roots.push_back(V);
372 return V;
373 }
374
375 /// addEndOfPath - Add an untyped node to the set of EOP nodes.
377 EndNodes.push_back(V);
378 return V;
379 }
380
381 unsigned num_roots() const { return Roots.size(); }
382 unsigned num_eops() const { return EndNodes.size(); }
383
384 bool empty() const { return NumNodes == 0; }
385 unsigned size() const { return NumNodes; }
386
387 void reserve(unsigned NodeCount) { Nodes.reserve(NodeCount); }
388
389 // Iterators.
391 using AllNodesTy = llvm::FoldingSet<ExplodedNode>;
392 using roots_iterator = NodeVector::iterator;
393 using const_roots_iterator = NodeVector::const_iterator;
394 using eop_iterator = NodeVector::iterator;
395 using const_eop_iterator = NodeVector::const_iterator;
396 using node_iterator = AllNodesTy::iterator;
397 using const_node_iterator = AllNodesTy::const_iterator;
398
399 llvm::iterator_range<node_iterator> nodes() { return Nodes; }
400
401 llvm::iterator_range<const_node_iterator> nodes() const { return Nodes; }
402
403 roots_iterator roots_begin() { return Roots.begin(); }
404
405 roots_iterator roots_end() { return Roots.end(); }
406
407 const_roots_iterator roots_begin() const { return Roots.begin(); }
408
409 const_roots_iterator roots_end() const { return Roots.end(); }
410
411 eop_iterator eop_begin() { return EndNodes.begin(); }
412
413 eop_iterator eop_end() { return EndNodes.end(); }
414
415 const_eop_iterator eop_begin() const { return EndNodes.begin(); }
416
417 const_eop_iterator eop_end() const { return EndNodes.end(); }
418
419 llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
421
422 using NodeMap = llvm::DenseMap<const ExplodedNode *, ExplodedNode *>;
423
424 /// Creates a trimmed version of the graph that only contains paths leading
425 /// to the given nodes.
426 ///
427 /// \param Nodes The nodes which must appear in the final graph. Presumably
428 /// these are end-of-path nodes (i.e. they have no successors).
429 /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in
430 /// the returned graph.
431 /// \param[out] InverseMap An optional map from nodes in the returned graph to
432 /// nodes in this graph.
433 /// \returns The trimmed graph
434 std::unique_ptr<ExplodedGraph>
436 InterExplodedGraphMap *ForwardMap = nullptr,
437 InterExplodedGraphMap *InverseMap = nullptr) const;
438
439 /// Enable tracking of recently allocated nodes for potential reclamation
440 /// when calling reclaimRecentlyAllocatedNodes().
441 void enableNodeReclamation(unsigned Interval) {
443 }
444
445 /// Reclaim "uninteresting" nodes created since the last time this method
446 /// was called.
448
449 /// Returns true if nodes for the given expression kind are always
450 /// kept around.
451 static bool isInterestingLValueExpr(const Expr *Ex);
452
453private:
454 bool shouldCollect(const ExplodedNode *node);
455 void collectNode(ExplodedNode *node);
456};
457
460 ImplTy Impl;
461
462public:
464 assert(N && !static_cast<ExplodedNode*>(N)->isSink());
465 Impl.insert(N);
466 }
467
468 ExplodedNodeSet() = default;
469
470 void Add(ExplodedNode *N) {
471 if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
472 }
473
474 using iterator = ImplTy::iterator;
475 using const_iterator = ImplTy::const_iterator;
476
477 unsigned size() const { return Impl.size(); }
478 bool empty() const { return Impl.empty(); }
479 bool erase(ExplodedNode *N) { return Impl.remove(N); }
480
481 void clear() { Impl.clear(); }
482
483 void insert(const ExplodedNodeSet &S) {
484 assert(&S != this);
485 if (empty())
486 Impl = S.Impl;
487 else
488 Impl.insert(S.begin(), S.end());
489 }
490
491 iterator begin() { return Impl.begin(); }
492 iterator end() { return Impl.end(); }
493
494 const_iterator begin() const { return Impl.begin(); }
495 const_iterator end() const { return Impl.end(); }
496};
497
498} // namespace ento
499
500} // namespace clang
501
502// GraphTraits
503
504namespace llvm {
505 template <> struct GraphTraits<clang::ento::ExplodedGraph *> {
509 using nodes_iterator = llvm::df_iterator<GraphTy>;
510
511 static NodeRef getEntryNode(const GraphTy G) {
512 return *G->roots_begin();
513 }
514
516 return N->succ_size() == 1 && N->getFirstSucc()->isTrivial();
517 }
518
520 if (predecessorOfTrivial(N))
521 return child_begin(*N->succ_begin());
522 return N->succ_begin();
523 }
524
526 if (predecessorOfTrivial(N))
527 return child_end(N->getFirstSucc());
528 return N->succ_end();
529 }
530
532 return df_begin(G);
533 }
534
536 return df_end(G);
537 }
538 };
539} // namespace llvm
540
541#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
#define V(N, I)
Definition: ASTContext.h:3284
int Id
Definition: ASTDiff.cpp:190
StringRef P
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static char ID
Definition: Arena.cpp:183
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::BumpPtrAllocator & getAllocator()
Definition: BumpVector.h:64
Represents a single basic block in a source-level CFG.
Definition: CFG.h:604
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1214
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
This represents one expression.
Definition: Expr.h:110
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
const ParentMap & getParentMap() const
const StackFrameContext * getStackFrame() const
Definition: ProgramPoint.h:179
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:175
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
Definition: Stmt.h:84
BranchNodeBuilder is responsible for constructing the nodes corresponding to the two branches of the ...
Definition: CoreEngine.h:434
CoreEngine - Implements the core logic of the graph-reachability analysis.
Definition: CoreEngine.h:56
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
Creates a trimmed version of the graph that only contains paths leading to the given nodes.
const_roots_iterator roots_begin() const
unsigned num_eops() const
ExplodedNode * addRoot(ExplodedNode *V)
addRoot - Add an untyped node to the set of roots.
roots_iterator roots_end()
BumpVectorContext & getNodeAllocator()
std::vector< ExplodedNode * > NodeVector
unsigned ReclaimCounter
Counter to determine when to reclaim nodes.
void reserve(unsigned NodeCount)
NodeVector ChangedNodes
A list of recently allocated nodes that can potentially be recycled.
int64_t NumNodes
NumNodes - The number of nodes in the graph.
NodeVector Roots
The roots of the simulation graph.
void enableNodeReclamation(unsigned Interval)
Enable tracking of recently allocated nodes for potential reclamation when calling reclaimRecentlyAll...
NodeVector::const_iterator const_roots_iterator
unsigned ReclaimNodeInterval
Determines how often nodes are reclaimed.
NodeVector EndNodes
The nodes in the simulation graph which have been specially marked as the endpoint of an abstract sim...
NodeVector::iterator eop_iterator
const_roots_iterator roots_end() const
llvm::iterator_range< const_node_iterator > nodes() const
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called.
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.
AllNodesTy::const_iterator const_node_iterator
unsigned num_roots() const
llvm::BumpPtrAllocator & getAllocator()
std::unique_ptr< ExplodedGraph > MakeEmptyGraph() const
AllNodesTy::iterator node_iterator
llvm::FoldingSet< ExplodedNode > AllNodesTy
ExplodedNode * getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false, bool *IsNew=nullptr)
Retrieve the node associated with a (Location,State) pair, where the 'Location' is a ProgramPoint in ...
const_eop_iterator eop_begin() const
NodeVector::const_iterator const_eop_iterator
BumpVectorContext BVC
BVC - Allocator and context for allocating nodes and their predecessor and successor groups.
llvm::iterator_range< node_iterator > nodes()
roots_iterator roots_begin()
ExplodedNode * createUncachedNode(const ProgramPoint &L, ProgramStateRef State, int64_t Id, bool IsSink=false)
Create a node for a (Location, State) pair, but don't store it for deduplication later.
llvm::FoldingSet< ExplodedNode > Nodes
Nodes - The nodes in the graph.
llvm::DenseMap< const ExplodedNode *, ExplodedNode * > NodeMap
ExplodedNode * addEndOfPath(ExplodedNode *V)
addEndOfPath - Add an untyped node to the set of EOP nodes.
NodeVector::iterator roots_iterator
NodeVector FreeNodes
A list of nodes that can be reused.
const_eop_iterator eop_end() const
bool erase(ExplodedNode *N)
ExplodedNodeSet(ExplodedNode *N)
ImplTy::const_iterator const_iterator
void insert(const ExplodedNodeSet &S)
const_iterator end() const
void Add(ExplodedNode *N)
const_iterator begin() const
const CFGBlock * getCFGBlock() const
llvm::iterator_range< pred_iterator > pred_range
const ProgramStateRef & getState() const
pred_iterator pred_end()
llvm::iterator_range< const_succ_iterator > const_succ_range
pred_iterator pred_begin()
const_pred_iterator pred_begin() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
const_succ_iterator succ_begin() const
llvm::iterator_range< succ_iterator > succ_range
bool isTrivial() const
The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...
const Stmt * getPreviousStmtForDiagnostics() const
Find the statement that was executed immediately before this node.
void Profile(llvm::FoldingSetNodeID &ID) const
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...
llvm::iterator_range< const_pred_iterator > const_pred_range
ExplodedNode * getFirstSucc()
succ_iterator succ_end()
unsigned pred_size() const
static void Profile(llvm::FoldingSetNodeID &ID, const ProgramPoint &Loc, const ProgramStateRef &state, bool IsSink)
const ExplodedNode * getFirstSucc() const
ExplodedNode(const ProgramPoint &loc, ProgramStateRef state, int64_t Id, bool IsSink)
const_succ_range succs() const
succ_iterator succ_begin()
const Stmt * getNextStmtForDiagnostics() const
Find the next statement that was executed on this node's execution path.
const StackFrameContext * getStackFrame() const
ExplodedNode *const * succ_iterator
const ExplodedNode * getFirstPred() const
const_pred_range preds() const
friend class EndOfFunctionNodeBuilder
Definition: ExplodedGraph.h:69
const ParentMap & getParentMap() const
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
const LocationContext * getLocationContext() const
std::optional< T > getLocationAs() const &
const Stmt * getCurrentOrPreviousStmtForDiagnostics() const
Find the statement that was executed at or immediately before this node.
const ExplodedNode *const * const_pred_iterator
ExplodedNode * getFirstPred()
const_succ_iterator succ_end() const
unsigned succ_size() const
ExplodedNode *const * pred_iterator
const ExplodedNode *const * const_succ_iterator
const Decl & getCodeDecl() const
const_pred_iterator pred_end() const
This is the simplest builder which generates nodes in the ExplodedGraph.
Definition: CoreEngine.h:238
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:55
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
long int64_t
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
Definition: Format.h:5394
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
static nodes_iterator nodes_end(const GraphTy G)
static nodes_iterator nodes_begin(const GraphTy G)
static ChildIteratorType child_end(NodeRef N)
clang::ento::ExplodedNode::succ_iterator ChildIteratorType
static NodeRef getEntryNode(const GraphTy G)
static ChildIteratorType child_begin(NodeRef N)