183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
2eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//
3eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//                     The LLVM Compiler Infrastructure
4eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
7eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//
8eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//===----------------------------------------------------------------------===//
9eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//
1083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek//  This file defines the interface ProgramPoint, which identifies a
1183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek//  distinct location in a function.
12eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//
13eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//===----------------------------------------------------------------------===//
14eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
15176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
16176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
17eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
18c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu#include "clang/Analysis/AnalysisContext.h"
19e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h"
204c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek#include "llvm/ADT/DenseMap.h"
215226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek#include "llvm/ADT/FoldingSet.h"
227a95de68c093991047ed8d339479ccad51b88663David Blaikie#include "llvm/ADT/Optional.h"
2330a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "llvm/ADT/PointerIntPair.h"
24ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "llvm/ADT/StringRef.h"
2530a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "llvm/Support/Casting.h"
2630a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "llvm/Support/DataTypes.h"
274c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek#include <cassert>
28ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include <string>
2930a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include <utility>
30eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
31eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremeneknamespace clang {
3225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
331d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekclass AnalysisDeclContext;
34102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass FunctionDecl;
35ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass LocationContext;
36ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar/// ProgramPoints can be "tagged" as representing points specific to a given
384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar/// analysis entity.  Tags are abstract annotations, with an associated
394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar/// description and potentially other information.
404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarclass ProgramPointTag {
414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarpublic:
424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  virtual ~ProgramPointTag();
444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  virtual StringRef getTagDescription() const = 0;
454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarprotected:
474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  /// Used to implement 'isKind' in subclasses.
484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  const void *getTagKind() { return TagKind; }
494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarprivate:
514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  const void *TagKind;
524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar};
534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarclass SimpleProgramPointTag : public ProgramPointTag {
554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  std::string Desc;
564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarpublic:
574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  StringRef getTagDescription() const override;
594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar};
604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
6183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass ProgramPoint {
62eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
63cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  enum Kind { BlockEdgeKind,
64cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockEntranceKind,
65cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockExitKind,
66cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PreStmtKind,
6751a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks              PreStmtPurgeDeadSymbolsKind,
6851a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks              PostStmtPurgeDeadSymbolsKind,
69cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStmtKind,
70b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreLoadKind,
71cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLoadKind,
72b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreStoreKind,
73cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStoreKind,
748083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek              PostConditionKind,
75cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLValueKind,
76852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              MinPostStmtKind = PostStmtKind,
77852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              MaxPostStmtKind = PostLValueKind,
789dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu              PostInitializerKind,
79102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor              CallEnterKind,
800b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitBeginKind,
810b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitEndKind,
8228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              PreImplicitCallKind,
8328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              PostImplicitCallKind,
8428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              MinImplicitCallKind = PreImplicitCallKind,
8528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              MaxImplicitCallKind = PostImplicitCallKind,
865903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks              EpsilonKind};
874c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
88d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprivate:
8928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const void *Data1;
90c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const void *, 2, unsigned> Data2;
9125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
9225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // The LocationContext could be NULL to allow ProgramPoint to be used in
9325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // context insensitive analysis.
94c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
95c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek
9628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
98d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
997a95de68c093991047ed8d339479ccad51b88663David Blaikie  ProgramPoint() {}
100f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  ProgramPoint(const void *P,
101f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               Kind k,
102f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const LocationContext *l,
1036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const ProgramPointTag *tag = nullptr)
10428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : Data1(P),
1056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Data2(nullptr, (((unsigned) k) >> 0) & 0x3),
10628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      L(l, (((unsigned) k) >> 2) & 0x3),
10728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
108f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getKind() == k);
109f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getLocationContext() == l);
110f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getData1() == P);
111f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek      }
112f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek
113f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  ProgramPoint(const void *P1,
114f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const void *P2,
115f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               Kind k,
116f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const LocationContext *l,
1176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const ProgramPointTag *tag = nullptr)
11828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : Data1(P1),
11928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      Data2(P2, (((unsigned) k) >> 0) & 0x3),
12028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      L(l, (((unsigned) k) >> 2) & 0x3),
12128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
122f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek
123d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
12428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const void *getData1() const { return Data1; }
125c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  const void *getData2() const { return Data2.getPointer(); }
126c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  void setData2(const void *d) { Data2.setPointer(d); }
1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
129af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// Create a new ProgramPoint object that is the same as the original
130af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// except for using the specified tag value.
13163d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  ProgramPoint withTag(const ProgramPointTag *tag) const {
132c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return ProgramPoint(getData1(), getData2(), getKind(),
133f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek                        getLocationContext(), tag);
134af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  }
135af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks
1363c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// \brief Convert to the specified ProgramPoint type, asserting that this
1373c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// ProgramPoint is of the desired type.
1387a95de68c093991047ed8d339479ccad51b88663David Blaikie  template<typename T>
1397a95de68c093991047ed8d339479ccad51b88663David Blaikie  T castAs() const {
1407a95de68c093991047ed8d339479ccad51b88663David Blaikie    assert(T::isKind(*this));
1417a95de68c093991047ed8d339479ccad51b88663David Blaikie    T t;
1427a95de68c093991047ed8d339479ccad51b88663David Blaikie    ProgramPoint& PP = t;
1437a95de68c093991047ed8d339479ccad51b88663David Blaikie    PP = *this;
1447a95de68c093991047ed8d339479ccad51b88663David Blaikie    return t;
1457a95de68c093991047ed8d339479ccad51b88663David Blaikie  }
1467a95de68c093991047ed8d339479ccad51b88663David Blaikie
1473c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// \brief Convert to the specified ProgramPoint type, returning None if this
1483c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// ProgramPoint is not of the desired type.
1497a95de68c093991047ed8d339479ccad51b88663David Blaikie  template<typename T>
1507a95de68c093991047ed8d339479ccad51b88663David Blaikie  Optional<T> getAs() const {
1517a95de68c093991047ed8d339479ccad51b88663David Blaikie    if (!T::isKind(*this))
1527a95de68c093991047ed8d339479ccad51b88663David Blaikie      return None;
1537a95de68c093991047ed8d339479ccad51b88663David Blaikie    T t;
1547a95de68c093991047ed8d339479ccad51b88663David Blaikie    ProgramPoint& PP = t;
1557a95de68c093991047ed8d339479ccad51b88663David Blaikie    PP = *this;
1567a95de68c093991047ed8d339479ccad51b88663David Blaikie    return t;
1577a95de68c093991047ed8d339479ccad51b88663David Blaikie  }
1587a95de68c093991047ed8d339479ccad51b88663David Blaikie
159f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  Kind getKind() const {
16028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    unsigned x = Tag.getInt();
161c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
16228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    x |= L.getInt();
163c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
16428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    x |= Data2.getInt();
165c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return (Kind) x;
166f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
167d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1680b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// \brief Is this a program point corresponding to purge/removal of dead
1690b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// symbols and bindings.
1700b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  bool isPurgeKind() {
1710b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    Kind K = getKind();
1720b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return (K == PostStmtPurgeDeadSymbolsKind ||
1730b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks            K == PreStmtPurgeDeadSymbolsKind);
1740b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
1750b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
17628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
17758465900ca10e53b8700a64e9265870de34e1acaTed Kremenek
178f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  const LocationContext *getLocationContext() const {
179c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return L.getPointer();
180f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
18125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
182e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek  // For use with DenseMap.  This hash is probably slow.
183d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  unsigned getHashValue() const {
184e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    llvm::FoldingSetNodeID ID;
185d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    Profile(ID);
186e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    return ID.ComputeHash();
187d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
189d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  bool operator==(const ProgramPoint & RHS) const {
1906403683411dac55afbe3435ceb19033e27cd9f96Ted Kremenek    return Data1 == RHS.Data1 &&
191c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 == RHS.Data2 &&
192c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L == RHS.L &&
193c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag == RHS.Tag;
194d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
195d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1969c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool operator!=(const ProgramPoint &RHS) const {
197c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return Data1 != RHS.Data1 ||
198c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 != RHS.Data2 ||
199c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L != RHS.L ||
200c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag != RHS.Tag;
201d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2035226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek  void Profile(llvm::FoldingSetNodeID& ID) const {
204f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddInteger((unsigned) getKind());
205f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getData1());
206c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    ID.AddPointer(getData2());
207f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getLocationContext());
20828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    ID.AddPointer(getTag());
2092680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenek  }
21063d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks
21163d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
21263d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const LocationContext *LC,
21363d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const ProgramPointTag *tag);
214eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
21683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEntrance : public ProgramPoint {
217eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2189c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEntrance(const CFGBlock *B, const LocationContext *L,
2196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                const ProgramPointTag *tag = nullptr)
2202f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    : ProgramPoint(B, BlockEntranceKind, L, tag) {
2212f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    assert(B && "BlockEntrance requires non-null block");
2222f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek  }
2231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2249c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
22503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
226bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
228b07805485c603be3d8011f72611465324c9e664bDavid Blaikie  Optional<CFGElement> getFirstElement() const {
2299c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const CFGBlock *B = getBlock();
230b07805485c603be3d8011f72611465324c9e664bDavid Blaikie    return B->empty() ? Optional<CFGElement>() : B->front();
231852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek  }
232852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
2337a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2347a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2357a95de68c093991047ed8d339479ccad51b88663David Blaikie  BlockEntrance() {}
2367a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2377a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == BlockEntranceKind;
238bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
239eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
24083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
24183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockExit : public ProgramPoint {
242eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2439c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockExit(const CFGBlock *B, const LocationContext *L)
24425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(B, BlockExitKind, L) {}
2451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2469c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
24703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
248bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
24983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
2509c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Stmt *getTerminator() const {
25183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return getBlock()->getTerminator();
252bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2547a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2557a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2567a95de68c093991047ed8d339479ccad51b88663David Blaikie  BlockExit() {}
2577a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2587a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == BlockExitKind;
259bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
260bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek};
2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2625f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass StmtPoint : public ProgramPoint {
2635f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekpublic:
2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
265ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag)
2661edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks    : ProgramPoint(S, p2, k, L, tag) {
2671edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks    assert(S);
2681edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks  }
2691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2705f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
2711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2725f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  template <typename T>
273cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2757a95de68c093991047ed8d339479ccad51b88663David Blaikieprotected:
2767a95de68c093991047ed8d339479ccad51b88663David Blaikie  StmtPoint() {}
2777a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2787a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2797a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2807a95de68c093991047ed8d339479ccad51b88663David Blaikie    unsigned k = Location.getKind();
2815f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    return k >= PreStmtKind && k <= MaxPostStmtKind;
2825f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  }
2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
2841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
285eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
2865f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PreStmt : public StmtPoint {
287cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenekpublic:
288ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
2896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          const Stmt *SubStmt = nullptr)
29025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
291cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
293cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2947a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2957a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2967a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreStmt() {}
2977a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2987a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PreStmtKind;
299cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  }
300cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek};
301cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
3025f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PostStmt : public StmtPoint {
3031b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekprotected:
3047a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostStmt() {}
3059c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
3066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           const ProgramPointTag *tag = nullptr)
30725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, data, k, L, tag) {}
3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
309eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
3106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
3116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    const ProgramPointTag *tag = nullptr)
3126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, k, L, tag) {}
3134bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek
3149c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, const LocationContext *L,
3156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    const ProgramPointTag *tag = nullptr)
3166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
31783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
3187a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3197a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3207a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
3217a95de68c093991047ed8d339479ccad51b88663David Blaikie    unsigned k = Location.getKind();
322f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
3231b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  }
3241b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek};
3258c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek
3268083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek// PostCondition represents the post program point of a branch condition.
3278083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekclass PostCondition : public PostStmt {
3288083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekpublic:
3299c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostCondition(const Stmt *S, const LocationContext *L,
3306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                const ProgramPointTag *tag = nullptr)
3318083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    : PostStmt(S, PostConditionKind, L, tag) {}
3328083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
3337a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3347a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3357a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostCondition() {}
3367a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
3377a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostConditionKind;
3388083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  }
3398083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek};
3408083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
341b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass LocationCheck : public StmtPoint {
342b4b817d704287836b52b34369009e682f208aa2bTed Kremenekprotected:
3437a95de68c093991047ed8d339479ccad51b88663David Blaikie  LocationCheck() {}
344b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  LocationCheck(const Stmt *S, const LocationContext *L,
345ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                ProgramPoint::Kind K, const ProgramPointTag *tag)
3466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, K, L, tag) {}
347b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
3487a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3497a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3507a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &location) {
3517a95de68c093991047ed8d339479ccad51b88663David Blaikie    unsigned k = location.getKind();
352d651141308a777d60ff98309d21e045bb936f8b7Ted Kremenek    return k == PreLoadKind || k == PreStoreKind;
3538c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3548c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
355b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
356b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreLoad : public LocationCheck {
3578c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
358ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreLoad(const Stmt *S, const LocationContext *L,
3596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          const ProgramPointTag *tag = nullptr)
360b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : LocationCheck(S, L, PreLoadKind, tag) {}
361b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
3627a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3637a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3647a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreLoad() {}
3657a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &location) {
3667a95de68c093991047ed8d339479ccad51b88663David Blaikie    return location.getKind() == PreLoadKind;
3678c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3688c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
370b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreStore : public LocationCheck {
3718c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
372ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStore(const Stmt *S, const LocationContext *L,
3736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           const ProgramPointTag *tag = nullptr)
374b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  : LocationCheck(S, L, PreStoreKind, tag) {}
375b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
3767a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3777a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3787a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreStore() {}
3797a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &location) {
3807a95de68c093991047ed8d339479ccad51b88663David Blaikie    return location.getKind() == PreStoreKind;
3818c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3828c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3841b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekclass PostLoad : public PostStmt {
3851b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekpublic:
3869c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLoad(const Stmt *S, const LocationContext *L,
3876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           const ProgramPointTag *tag = nullptr)
38825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLoadKind, L, tag) {}
3891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3907a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3917a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3927a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostLoad() {}
3937a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
3947a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostLoadKind;
395bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
396eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
3971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
39841c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// \brief Represents a program point after a store evaluation.
39982bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekclass PostStore : public PostStmt {
40082bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekpublic:
4013d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// Construct the post store point.
4023d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \param Loc can be used to store the information about the location
4033d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// used in the form it was uttered in the code.
4043d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
4056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines            const ProgramPointTag *tag = nullptr)
4063d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    : PostStmt(S, PostStoreKind, L, tag) {
4076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    assert(getData2() == nullptr);
4083d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    setData2(Loc);
4093d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4113d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \brief Returns the information about the location used in the store,
4123d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// how it was uttered in the code.
4133d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  const void *getLocationValue() const {
4143d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    return getData2();
4153d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
4163d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
4177a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4187a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4197a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostStore() {}
4207a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4217a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostStoreKind;
4227a95de68c093991047ed8d339479ccad51b88663David Blaikie  }
42382bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek};
4247090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek
4257090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekclass PostLValue : public PostStmt {
4267090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekpublic:
4279c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLValue(const Stmt *S, const LocationContext *L,
4286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines             const ProgramPointTag *tag = nullptr)
42925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLValueKind, L, tag) {}
4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4317a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4327a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4337a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostLValue() {}
4347a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4357a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostLValueKind;
4367090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  }
4371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
4381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
43941c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings BEFORE
4400b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the given statement.
44151a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PreStmtPurgeDeadSymbols : public StmtPoint {
442331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekpublic:
4430b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
4446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       const ProgramPointTag *tag = nullptr)
4456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
4461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4477a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4487a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4497a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreStmtPurgeDeadSymbols() {}
4507a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4517a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
4520b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
4530b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
4540b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
45541c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings AFTER
4560b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the  given statement.
45751a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PostStmtPurgeDeadSymbols : public StmtPoint {
4580b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
4590b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
4606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       const ProgramPointTag *tag = nullptr)
4616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
4620b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
4637a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4647a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4657a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostStmtPurgeDeadSymbols() {}
4667a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4677a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
468331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  }
469331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek};
4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
47183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEdge : public ProgramPoint {
472b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenekpublic:
4739c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
474e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
475e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B1 && "BlockEdge: source block must be non-null");
476e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B2 && "BlockEdge: destination block must be non-null");
477e4c6675cccbaac991843def43072687bca50d989Ted Kremenek  }
4781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4799c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getSrc() const {
48003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData1());
481d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
4821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4839c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getDst() const {
48403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData2());
485d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4877a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4887a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4897a95de68c093991047ed8d339479ccad51b88663David Blaikie  BlockEdge() {}
4907a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4917a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == BlockEdgeKind;
492b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek  }
493b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek};
49483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
4959dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xuclass PostInitializer : public ProgramPoint {
4969dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xupublic:
497610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \brief Construct a PostInitializer point that represents a location after
498610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  ///   CXXCtorInitializer expression evaluation.
499610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  ///
500610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \param I The initializer.
501610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \param Loc The location of the field being initialized.
502610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  PostInitializer(const CXXCtorInitializer *I,
503610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks                  const void *Loc,
5049dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu                  const LocationContext *L)
505610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks    : ProgramPoint(I, Loc, PostInitializerKind, L) {}
5069dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
5071aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose  const CXXCtorInitializer *getInitializer() const {
5081aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose    return static_cast<const CXXCtorInitializer *>(getData1());
5091aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose  }
5101aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose
511610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \brief Returns the location of the field.
512610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  const void *getLocationValue() const {
513610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks    return getData2();
514610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  }
515610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks
5167a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5177a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5187a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostInitializer() {}
5197a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5207a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostInitializerKind;
5219dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  }
5229dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu};
5239dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
52428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents an implicit call event.
52528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
52628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// The nearest statement is provided for diagnostic purposes.
52728038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass ImplicitCallPoint : public ProgramPoint {
52828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
52928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
53028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                    const LocationContext *L, const ProgramPointTag *Tag)
53128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
53228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
53328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
53428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  SourceLocation getLocation() const {
53528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return SourceLocation::getFromPtrEncoding(getData1());
53628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
53728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
5387a95de68c093991047ed8d339479ccad51b88663David Blaikieprotected:
5397a95de68c093991047ed8d339479ccad51b88663David Blaikie  ImplicitCallPoint() {}
5407a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5417a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5427a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5437a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() >= MinImplicitCallKind &&
5447a95de68c093991047ed8d339479ccad51b88663David Blaikie           Location.getKind() <= MaxImplicitCallKind;
54528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
54628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
54728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
54828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just before an implicit call event.
54928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
55028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PreStmt program points.
55128038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PreImplicitCall : public ImplicitCallPoint {
55228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
5536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
5546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                  const ProgramPointTag *Tag = nullptr)
55528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
55628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
5577a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5587a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5597a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreImplicitCall() {}
5607a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5617a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PreImplicitCallKind;
56228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
56328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
56428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
56528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just after an implicit call event.
56628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
56728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PostStmt program points.
56828038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PostImplicitCall : public ImplicitCallPoint {
56928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
5706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
5716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                   const ProgramPointTag *Tag = nullptr)
57228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
57328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
5747a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5757a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5767a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostImplicitCall() {}
5777a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5787a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostImplicitCallKind;
57928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
58028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
58128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
58241c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we begin processing an inlined call.
58380de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks/// CallEnter uses the caller's location context.
584852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallEnter : public ProgramPoint {
585102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
58619b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
58719b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu            const LocationContext *callerCtx)
5886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
589102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
590102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  const Stmt *getCallExpr() const {
591102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return static_cast<const Stmt *>(getData1());
592102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
593102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
59419b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  const StackFrameContext *getCalleeContext() const {
59519b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    return static_cast<const StackFrameContext *>(getData2());
596102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
597102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
5984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  /// Returns the entry block in the CFG for the entered function.
5994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  const CFGBlock *getEntry() const {
6004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    const StackFrameContext *CalleeCtx = getCalleeContext();
6014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    const CFG *CalleeCFG = CalleeCtx->getCFG();
6024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    return &(CalleeCFG->getEntry());
6034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
6044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
6057a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
6067a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
6077a95de68c093991047ed8d339479ccad51b88663David Blaikie  CallEnter() {}
6087a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
6097a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == CallEnterKind;
610102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
611102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
612102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
61341c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we start the call exit sequence (for inlined call).
6140b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks///
6150b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// The call exit is simulated with a sequence of nodes, which occur between
6160b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// CallExitBegin and CallExitEnd. The following operations occur between the
6170b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// two program points:
6180b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitBegin
6190b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Bind the return value
6200b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
6210b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitEnd
622852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitBegin : public ProgramPoint {
6230b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
6240b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitBegin uses the callee's location context.
625852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitBegin(const StackFrameContext *L)
6266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {}
6270b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
6287a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
6297a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
6307a95de68c093991047ed8d339479ccad51b88663David Blaikie  CallExitBegin() {}
6317a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
6327a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == CallExitBeginKind;
6330b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
6340b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
6350b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
63641c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we finish the call exit sequence (for inlined call).
6370b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \sa CallExitBegin
638852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitEnd : public ProgramPoint {
639102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
6400b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitEnd uses the caller's location context.
641852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitEnd(const StackFrameContext *CalleeCtx,
642852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              const LocationContext *CallerCtx)
6436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
644852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose
645852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  const StackFrameContext *getCalleeContext() const {
646852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    return static_cast<const StackFrameContext *>(getData1());
647852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  }
648102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
6497a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
6507a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
6517a95de68c093991047ed8d339479ccad51b88663David Blaikie  CallExitEnd() {}
6527a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
6537a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == CallExitEndKind;
654102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
655102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
656102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
6575903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// This is a meta program point, which should be skipped by all the diagnostic
6585903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// reasoning etc.
6595903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaksclass EpsilonPoint : public ProgramPoint {
6605903a373db3d27794c90b25687e0dd6adb0e497dAnna Zakspublic:
6615903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  EpsilonPoint(const LocationContext *L, const void *Data1,
6626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const void *Data2 = nullptr,
6636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const ProgramPointTag *tag = nullptr)
6645903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
6655903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
6665903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  const void *getData() const { return getData1(); }
6675903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
6687a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
6697a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
6707a95de68c093991047ed8d339479ccad51b88663David Blaikie  EpsilonPoint() {}
6717a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
6727a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == EpsilonKind;
6735903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  }
6745903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks};
6755903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
676eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek} // end namespace clang
6774c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
6784c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
6791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnamespace llvm { // Traits specialization for DenseMap
6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
68183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenektemplate <> struct DenseMapInfo<clang::ProgramPoint> {
6824c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
683d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getEmptyKey() {
684d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
6851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
6866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
687d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
688d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
689d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getTombstoneKey() {
690d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
69125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
6926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
693d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
694d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
6959c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic unsigned getHashValue(const clang::ProgramPoint &Loc) {
696d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return Loc.getHashValue();
697d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
698d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
6999c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic bool isEqual(const clang::ProgramPoint &L,
7009c378f705405d37f49795d5e915989de774fe11fTed Kremenek                    const clang::ProgramPoint &R) {
701d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return L == R;
702d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
703d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
7044c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek};
70506159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
70606159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnertemplate <>
70706159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnerstruct isPodLike<clang::ProgramPoint> { static const bool value = true; };
70806159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
7094c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek} // end namespace llvm
7104c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
711eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#endif
712