151125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==//
24241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//
34241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//                     The LLVM Compiler Infrastructure
44241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//
54241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// This file is distributed under the University of Illinois Open Source
64241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek// License. See LICENSE.TXT for details.
74241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//
84241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//===----------------------------------------------------------------------===//
94241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//
1051125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek//  This file defines the template classes ExplodedNode and ExplodedGraph,
1151125a21eafc29c925cac3655b46cfd8ef55f764Ted Kremenek//  which represent a path-sensitive, intra-procedural "exploded graph."
12b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin//  See "Precise interprocedural dataflow analysis via graph reachability"
13b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin//  by Reps, Horwitz, and Sagiv
14b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin//  (http://portal.acm.org/citation.cfm?id=199462) for the definition of an
15b2213dc3dd8f58b611b91d2fce4834a767efcba7Jeffrey Yasskin//  exploded graph.
164241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//
174241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek//===----------------------------------------------------------------------===//
184241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
19176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
20176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
214241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
2263bbe5312cd89ce0ceb684bff68c5baef636e93cTed Kremenek#include "clang/AST/Decl.h"
2330a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "clang/Analysis/AnalysisContext.h"
2430a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "clang/Analysis/ProgramPoint.h"
2530a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "clang/Analysis/Support/BumpVector.h"
2630a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
2730a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "llvm/ADT/DepthFirstIterator.h"
284241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek#include "llvm/ADT/FoldingSet.h"
2930a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "llvm/ADT/GraphTraits.h"
30f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek#include "llvm/ADT/SmallPtrSet.h"
3130a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "llvm/ADT/SmallVector.h"
324241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek#include "llvm/Support/Allocator.h"
3363bbe5312cd89ce0ceb684bff68c5baef636e93cTed Kremenek#include "llvm/Support/Casting.h"
34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory>
35626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek#include <vector>
364241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
374241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremeneknamespace clang {
384a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
3911062b118476368fa5b294954713e5df97d8599fTed Kremenekclass CFG;
405a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis
419ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremeneknamespace ento {
425a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis
435fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenekclass ExplodedGraph;
4411062b118476368fa5b294954713e5df97d8599fTed Kremenek
45cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
46cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek// ExplodedGraph "implementation" classes.  These classes are not typed to
47cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek// contain a specific kind of state.  Typed-specialized versions are defined
48cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek// on top of these classes.
49cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek//===----------------------------------------------------------------------===//
501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
51bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu// ExplodedNode is not constified all over the engine because we need to add
52bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu// successors to it at any time after creating it.
53bda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7Zhongxing Xu
54c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass ExplodedNode : public llvm::FoldingSetNode {
5538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  friend class ExplodedGraph;
56d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  friend class CoreEngine;
57a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks  friend class NodeBuilder;
58d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  friend class BranchNodeBuilder;
59d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  friend class IndirectGotoNodeBuilder;
60d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  friend class SwitchNodeBuilder;
61e36de1fe51c39d9161915dd3dbef880954af6476Ted Kremenek  friend class EndOfFunctionNodeBuilder;
621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
631833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// Efficiently stores a list of ExplodedNodes, or an optional flag.
641833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  ///
651833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing
661833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// for the case when there is only one node in the group. This is a fairly
671833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// common case in an ExplodedGraph, where most nodes have only one
681833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// predecessor and many have only one successor. It can also be used to
691833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// store a flag rather than a node list, which ExplodedNode uses to mark
701833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// whether a node is a sink. If the flag is set, the group is implicitly
711833d284346b9fa11aae4e6aa07381347c04745cJordan Rose  /// empty and no nodes may be added.
724c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek  class NodeGroup {
7346e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    // Conceptually a discriminated union. If the low bit is set, the node is
7446e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    // a sink. If the low bit is not set, the pointer refers to the storage
7546e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    // for the nodes in the group.
761833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    // This is not a PointerIntPair in order to keep the storage type opaque.
774c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek    uintptr_t P;
78d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
794c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek  public:
8046e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    NodeGroup(bool Flag = false) : P(Flag) {
8146e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose      assert(getFlag() == Flag);
8246e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    }
831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8446e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    ExplodedNode * const *begin() const;
851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8646e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    ExplodedNode * const *end() const;
871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
885d5480380d7b7c3590a0283ddf239220e514e576Ted Kremenek    unsigned size() const;
891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9046e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    bool empty() const { return P == 0 || getFlag() != 0; }
911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
921833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    /// Adds a node to the list.
931833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    ///
941833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    /// The group must not have been created with its flag set.
959c378f705405d37f49795d5e915989de774fe11fTed Kremenek    void addNode(ExplodedNode *N, ExplodedGraph &G);
961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
971833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    /// Replaces the single node in this group with a new node.
981833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    ///
991833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    /// Note that this should only be used when you know the group was not
1001833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    /// created with its flag set, and that the group is empty or contains
1011833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    /// only a single node.
102d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek    void replaceNode(ExplodedNode *node);
103d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
1041833d284346b9fa11aae4e6aa07381347c04745cJordan Rose    /// Returns whether this group was created with its flag set.
105b38911f16b4943548db6a3695fc6ae23070b25d2Ted Kremenek    bool getFlag() const {
10646e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose      return (P & 1);
107f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek    }
1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  };
1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1104a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  /// Location - The program location (within a function body) associated
1114a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  ///  with this node.
1124a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  const ProgramPoint Location;
1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1144323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek  /// State - The state associated with this node.
1158bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef State;
1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1174a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  /// Preds - The predecessors of this node.
1184c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek  NodeGroup Preds;
1191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1204a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  /// Succs - The successors of this node.
1214c4cb527a44037d076da82ad9d12b4e655e64dbbTed Kremenek  NodeGroup Succs;
122c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1234a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenekpublic:
124c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1255204d9e2fe0ea4e4b9c85087e355021c93221764Jordan Rose  explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
1266800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks                        bool IsSink)
12746e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    : Location(loc), State(state), Succs(IsSink) {
12846e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose    assert(isSink() == IsSink);
129e40b69de464bc695afcaf7ef9602ad727d77b981Ted Kremenek  }
130c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1314a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  /// getLocation - Returns the edge associated with the given node.
1320f9063c116b7c3b05d8042b5976463c2dae04861Ted Kremenek  ProgramPoint getLocation() const { return Location; }
133c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const LocationContext *getLocationContext() const {
1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return getLocation().getLocationContext();
13625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  }
13725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
138955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks  const StackFrameContext *getStackFrame() const {
139955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks    return getLocationContext()->getCurrentStackFrame();
140955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks  }
141955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks
1425032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu  const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
1435032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu
1445032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu  CFG &getCFG() const { return *getLocationContext()->getCFG(); }
1455032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu
146b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu  ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
147b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
148a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek  template <typename T>
149a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek  T &getAnalysis() const {
150a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek    return *getLocationContext()->getAnalysis<T>();
151c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  }
152c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1530a6e09f67c719c318856be19d57e19972101f62cJordan Rose  const ProgramStateRef &getState() const { return State; }
154b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
15552c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek  template <typename T>
1567a95de68c093991047ed8d339479ccad51b88663David Blaikie  Optional<T> getLocationAs() const LLVM_LVALUE_FUNCTION {
1577a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getAs<T>();
158dcd42fbb418cf662c136cb035e235a44b58ad91eJordan Rose  }
159dcd42fbb418cf662c136cb035e235a44b58ad91eJordan Rose
1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  static void Profile(llvm::FoldingSetNodeID &ID,
1616800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks                      const ProgramPoint &Loc,
1621831bd29572b6a7243da73d9606209190c0217deBenjamin Kramer                      const ProgramStateRef &state,
1636800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks                      bool IsSink) {
1645fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek    ID.Add(Loc);
165c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    ID.AddPointer(state.get());
1666800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks    ID.AddBoolean(IsSink);
1675fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek  }
168c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
169c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  void Profile(llvm::FoldingSetNodeID& ID) const {
170fbe4d36f1f83ca12b532e0a946cbffcdb54f904cJordan Rose    // We avoid copy constructors by not using accessors.
171fbe4d36f1f83ca12b532e0a946cbffcdb54f904cJordan Rose    Profile(ID, Location, State, isSink());
172c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  }
173c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  /// addPredeccessor - Adds a predecessor to the current node, and
175c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  ///  in tandem add this node as a successor of the other node.
1769c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void addPredecessor(ExplodedNode *V, ExplodedGraph &G);
177c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
1784a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  unsigned succ_size() const { return Succs.size(); }
1794a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  unsigned pred_size() const { return Preds.size(); }
1804a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  bool succ_empty() const { return Succs.empty(); }
1810e8a3c743b9b3e3039e329a1736122d3b5b5fed9Ted Kremenek  bool pred_empty() const { return Preds.empty(); }
1821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
183ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek  bool isSink() const { return Succs.getFlag(); }
1844a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
185cacdbc97d11d2bbde00a63dace6ac26f4b12ed88Craig Topper  bool hasSinglePred() const {
1865903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    return (pred_size() == 1);
1875903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  }
1885903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
1899c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ExplodedNode *getFirstPred() {
1906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return pred_empty() ? nullptr : *(pred_begin());
19152c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek  }
1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1939c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const ExplodedNode *getFirstPred() const {
19452c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek    return const_cast<ExplodedNode*>(this)->getFirstPred();
19552c3196a89a26cebcf069dd140c3396b743b8e33Ted Kremenek  }
1961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1970f8579274a010f360a371b53101859d9d6052314Anna Zaks  const ExplodedNode *getFirstSucc() const {
1986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return succ_empty() ? nullptr : *(succ_begin());
1990f8579274a010f360a371b53101859d9d6052314Anna Zaks  }
2000f8579274a010f360a371b53101859d9d6052314Anna Zaks
2014a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  // Iterators over successor and predecessor vertices.
20246e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose  typedef ExplodedNode*       const *       succ_iterator;
2033148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  typedef const ExplodedNode* const * const_succ_iterator;
20446e778145c56cd9b42cb399795a294b29cb78b62Jordan Rose  typedef ExplodedNode*       const *       pred_iterator;
2053148eb4a75f70f2636075c364d03104223f004d3Ted Kremenek  typedef const ExplodedNode* const * const_pred_iterator;
2064a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
207c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  pred_iterator pred_begin() { return Preds.begin(); }
208c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  pred_iterator pred_end() { return Preds.end(); }
2094a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
2104a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  const_pred_iterator pred_begin() const {
2114a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    return const_cast<ExplodedNode*>(this)->pred_begin();
2121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
2134a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  const_pred_iterator pred_end() const {
2144a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    return const_cast<ExplodedNode*>(this)->pred_end();
2154a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  }
2164a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
217c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  succ_iterator succ_begin() { return Succs.begin(); }
218c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  succ_iterator succ_end() { return Succs.end(); }
2194a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
2204a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  const_succ_iterator succ_begin() const {
2214a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    return const_cast<ExplodedNode*>(this)->succ_begin();
2224a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  }
2234a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  const_succ_iterator succ_end() const {
2244a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    return const_cast<ExplodedNode*>(this)->succ_end();
2254a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  }
226c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
227c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  // For debugging.
2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
229c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xupublic:
2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
231c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  class Auditor {
232c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  public:
233c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    virtual ~Auditor();
2349c378f705405d37f49795d5e915989de774fe11fTed Kremenek    virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
235c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  };
2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
237c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  static void SetAuditor(Auditor* A);
238d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
239d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenekprivate:
240d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
241d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
242c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu};
243c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
244c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rosetypedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>
245c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose        InterExplodedGraphMap;
2464a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
24738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xuclass ExplodedGraph {
2484241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenekprotected:
249d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  friend class CoreEngine;
250e96de2dfde487211fb52f9139cdcae64d051a406Zhongxing Xu
2514241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  // Type definitions.
252626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  typedef std::vector<ExplodedNode *> NodeVector;
2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
254626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  /// The roots of the simulation graph. Usually there will be only
2554241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  /// one, but clients are free to establish multiple subgraphs within a single
2564241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  /// SimulGraph. Moreover, these subgraphs can often merge when paths from
2574241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  /// different roots reach the same state at the same program location.
258626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  NodeVector Roots;
2594241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
260626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  /// The nodes in the simulation graph which have been
261626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  /// specially marked as the endpoint of an abstract simulation path.
262626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  NodeVector EndNodes;
26338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
26438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  /// Nodes - The nodes in the graph.
26538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  llvm::FoldingSet<ExplodedNode> Nodes;
26638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
2675fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek  /// BVC - Allocator and context for allocating nodes and their predecessor
2685fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek  /// and successor groups.
2695fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek  BumpVectorContext BVC;
2701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
27139b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek  /// NumNodes - The number of nodes in the graph.
27239b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek  unsigned NumNodes;
273d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
274d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  /// A list of recently allocated nodes that can potentially be recycled.
2752ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek  NodeVector ChangedNodes;
276d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
277d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  /// A list of nodes that can be reused.
278626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  NodeVector FreeNodes;
279d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
2804d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose  /// Determines how often nodes are reclaimed.
2814d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose  ///
2824d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose  /// If this is 0, nodes will never be reclaimed.
2834d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose  unsigned ReclaimNodeInterval;
2842ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek
2852ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek  /// Counter to determine when to reclaim nodes.
2864d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose  unsigned ReclaimCounter;
2874241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
28838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xupublic:
2896800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks
2906800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks  /// \brief Retrieve the node associated with a (Location,State) pair,
29138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  ///  where the 'Location' is a ProgramPoint in the CFG.  If no node for
2926800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks  ///  this pair exists, it is created. IsNew is set to true if
29338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  ///  the node was freshly created.
2948bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State,
2956800ba622e4edf287801ac69c42c61e7e294b06bAnna Zaks                        bool IsSink = false,
2966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                        bool* IsNew = nullptr);
2971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
298176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
299176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return llvm::make_unique<ExplodedGraph>();
30038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  }
3014a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
3024241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  /// addRoot - Add an untyped node to the set of roots.
3039c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ExplodedNode *addRoot(ExplodedNode *V) {
304ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek    Roots.push_back(V);
305ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek    return V;
306ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek  }
3074241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
3084241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  /// addEndOfPath - Add an untyped node to the set of EOP nodes.
3099c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ExplodedNode *addEndOfPath(ExplodedNode *V) {
310ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek    EndNodes.push_back(V);
311ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek    return V;
312ede5a4ba111f0590879670b6cb07f4d6d0bd9075Ted Kremenek  }
31338b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
3149d0064e802e81d0833e8ccab8978b17c0bac3625Ted Kremenek  ExplodedGraph();
3154a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
316d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  ~ExplodedGraph();
317d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
3184241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  unsigned num_roots() const { return Roots.size(); }
3194a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  unsigned num_eops() const { return EndNodes.size(); }
3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32139b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek  bool empty() const { return NumNodes == 0; }
32239b4c6c98d391b25c376782cf92346aa88c96f7eTed Kremenek  unsigned size() const { return NumNodes; }
323c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
3244241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek  // Iterators.
32538b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef ExplodedNode                        NodeTy;
32638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef llvm::FoldingSet<ExplodedNode>      AllNodesTy;
327626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  typedef NodeVector::iterator                roots_iterator;
328626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  typedef NodeVector::const_iterator          const_roots_iterator;
329626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  typedef NodeVector::iterator                eop_iterator;
330626719bd2c09e27fe7c182724a812d27f59e3819Ted Kremenek  typedef NodeVector::const_iterator          const_eop_iterator;
33138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef AllNodesTy::iterator                node_iterator;
33238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef AllNodesTy::const_iterator          const_node_iterator;
3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  node_iterator nodes_begin() { return Nodes.begin(); }
3357ebde953bb050caa69f791fc1de449d435c6a36fTed Kremenek
33638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  node_iterator nodes_end() { return Nodes.end(); }
3371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33838b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const_node_iterator nodes_begin() const { return Nodes.begin(); }
3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const_node_iterator nodes_end() const { return Nodes.end(); }
3411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  roots_iterator roots_begin() { return Roots.begin(); }
3431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  roots_iterator roots_end() { return Roots.end(); }
3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const_roots_iterator roots_begin() const { return Roots.begin(); }
3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const_roots_iterator roots_end() const { return Roots.end(); }
3494241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
35038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  eop_iterator eop_begin() { return EndNodes.begin(); }
3511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  eop_iterator eop_end() { return EndNodes.end(); }
3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35438b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const_eop_iterator eop_begin() const { return EndNodes.begin(); }
3551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35638b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  const_eop_iterator eop_end() const { return EndNodes.end(); }
35738b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
3585fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek  llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
3595fe4d9deb543a19f557e3d85c5f33867af97cd96Ted Kremenek  BumpVectorContext &getNodeAllocator() { return BVC; }
36038b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
36138b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu  typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
36238b02b912e1a55c912f603c4369431264d36a381Zhongxing Xu
363c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  /// Creates a trimmed version of the graph that only contains paths leading
364c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  /// to the given nodes.
365c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  ///
366c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  /// \param Nodes The nodes which must appear in the final graph. Presumably
367c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  ///              these are end-of-path nodes (i.e. they have no successors).
368c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in
369c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  ///                        the returned graph.
370c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  /// \param[out] InverseMap An optional map from nodes in the returned graph to
371c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  ///                        nodes in this graph.
372c9963132736782d0c9178c744b3e2307cfb98a08Jordan Rose  /// \returns The trimmed graph
373176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::unique_ptr<ExplodedGraph>
374176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  trim(ArrayRef<const NodeTy *> Nodes,
375176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines       InterExplodedGraphMap *ForwardMap = nullptr,
376176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines       InterExplodedGraphMap *InverseMap = nullptr) const;
377d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
378d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  /// Enable tracking of recently allocated nodes for potential reclamation
3792ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek  /// when calling reclaimRecentlyAllocatedNodes().
3804d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose  void enableNodeReclamation(unsigned Interval) {
3814d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose    ReclaimCounter = ReclaimNodeInterval = Interval;
3824d9e497a2b1eab3b1214848216050c64fc3acfd6Jordan Rose  }
383d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek
384d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  /// Reclaim "uninteresting" nodes created since the last time this method
385d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek  /// was called.
3862ac58b7c09938bb28c51c7cd2deada609b75f94cTed Kremenek  void reclaimRecentlyAllocatedNodes();
387841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenek
3884e9c0854382d37325771b50f6cf899a75119fa24Ted Kremenek  /// \brief Returns true if nodes for the given expression kind are always
3894e9c0854382d37325771b50f6cf899a75119fa24Ted Kremenek  ///        kept around.
3904e9c0854382d37325771b50f6cf899a75119fa24Ted Kremenek  static bool isInterestingLValueExpr(const Expr *Ex);
3914e9c0854382d37325771b50f6cf899a75119fa24Ted Kremenek
392841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenekprivate:
393841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenek  bool shouldCollect(const ExplodedNode *node);
394841c96a885789afea9d32d1d842033768c6d2b19Ted Kremenek  void collectNode(ExplodedNode *node);
3954241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek};
396cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek
397f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenekclass ExplodedNodeSet {
398c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy;
399f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  ImplTy Impl;
4001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
401f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenekpublic:
4029c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ExplodedNodeSet(ExplodedNode *N) {
403c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    assert (N && !static_cast<ExplodedNode*>(N)->isSink());
404f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek    Impl.insert(N);
405f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  }
4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
407f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  ExplodedNodeSet() {}
4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4099c378f705405d37f49795d5e915989de774fe11fTed Kremenek  inline void Add(ExplodedNode *N) {
410c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
411f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  }
4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
413c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  typedef ImplTy::iterator       iterator;
414c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  typedef ImplTy::const_iterator const_iterator;
415f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek
416fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek  unsigned size() const { return Impl.size();  }
417fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek  bool empty()    const { return Impl.empty(); }
4181aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks  bool erase(ExplodedNode *N) { return Impl.erase(N); }
419fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek
420fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek  void clear() { Impl.clear(); }
421fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek  void insert(const ExplodedNodeSet &S) {
4222d950b15b2b2b650b102ecf0c6b50b45e0cb6a8aAnna Zaks    assert(&S != this);
423fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek    if (empty())
424fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek      Impl = S.Impl;
425fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek    else
426fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek      Impl.insert(S.begin(), S.end());
427fee96e043108b6e24e7d4c5464bf89ac970a7f81Ted Kremenek  }
4281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
429f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  inline iterator begin() { return Impl.begin(); }
430f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  inline iterator end()   { return Impl.end();   }
4311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
432f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  inline const_iterator begin() const { return Impl.begin(); }
433f6f5ef4aaa66b60270e84d1fe1292886369d2f38Ted Kremenek  inline const_iterator end()   const { return Impl.end();   }
4341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4365a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis} // end GR namespace
4375a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis
4384241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek} // end clang namespace
4394241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek
4404a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek// GraphTraits
4414a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
4424a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremeneknamespace llvm {
4439ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek  template<> struct GraphTraits<clang::ento::ExplodedNode*> {
4449ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek    typedef clang::ento::ExplodedNode NodeType;
445c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    typedef NodeType::succ_iterator  ChildIteratorType;
4464a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    typedef llvm::df_iterator<NodeType*>      nodes_iterator;
4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4484a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline NodeType* getEntryNode(NodeType* N) {
4494a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return N;
4504a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4524a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline ChildIteratorType child_begin(NodeType* N) {
4534a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return N->succ_begin();
4544a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4564a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline ChildIteratorType child_end(NodeType* N) {
4574a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return N->succ_end();
4584a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4604a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline nodes_iterator nodes_begin(NodeType* N) {
4614a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return df_begin(N);
4624a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4644a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline nodes_iterator nodes_end(NodeType* N) {
4654a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return df_end(N);
4664a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4674a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  };
4681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4699ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek  template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
4709ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek    typedef const clang::ento::ExplodedNode NodeType;
471c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    typedef NodeType::const_succ_iterator   ChildIteratorType;
4724a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    typedef llvm::df_iterator<NodeType*>       nodes_iterator;
4731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4744a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline NodeType* getEntryNode(NodeType* N) {
4754a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return N;
4764a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4784a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline ChildIteratorType child_begin(NodeType* N) {
4794a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return N->succ_begin();
4804a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4824a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline ChildIteratorType child_end(NodeType* N) {
4834a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return N->succ_end();
4844a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4864a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline nodes_iterator nodes_begin(NodeType* N) {
4874a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return df_begin(N);
4884a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4904a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    static inline nodes_iterator nodes_end(NodeType* N) {
4914a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek      return df_end(N);
4924a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek    }
4934a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek  };
4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4954a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek} // end llvm namespace
4964a0f5f1646637fcf90eb236b5a46f40e5a5dd739Ted Kremenek
4974241b3d1ad87e9a593bbc6cdf0f49435d5aec235Ted Kremenek#endif
498