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
1583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
1683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
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 Kremenekclass ProgramPointTag;
37ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
3883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass ProgramPoint {
39eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
40cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  enum Kind { BlockEdgeKind,
41cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockEntranceKind,
42cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockExitKind,
43cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PreStmtKind,
4451a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks              PreStmtPurgeDeadSymbolsKind,
4551a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks              PostStmtPurgeDeadSymbolsKind,
46cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStmtKind,
47b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreLoadKind,
48cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLoadKind,
49b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreStoreKind,
50cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStoreKind,
518083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek              PostConditionKind,
52cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLValueKind,
53852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              MinPostStmtKind = PostStmtKind,
54852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              MaxPostStmtKind = PostLValueKind,
559dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu              PostInitializerKind,
56102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor              CallEnterKind,
570b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitBeginKind,
580b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitEndKind,
5928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              PreImplicitCallKind,
6028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              PostImplicitCallKind,
6128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              MinImplicitCallKind = PreImplicitCallKind,
6228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              MaxImplicitCallKind = PostImplicitCallKind,
635903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks              EpsilonKind};
644c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
65d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprivate:
6628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const void *Data1;
67c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const void *, 2, unsigned> Data2;
6825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
6925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // The LocationContext could be NULL to allow ProgramPoint to be used in
7025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // context insensitive analysis.
71c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
72c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek
7328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
75d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
767a95de68c093991047ed8d339479ccad51b88663David Blaikie  ProgramPoint() {}
77f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  ProgramPoint(const void *P,
78f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               Kind k,
79f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const LocationContext *l,
806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const ProgramPointTag *tag = nullptr)
8128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : Data1(P),
826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Data2(nullptr, (((unsigned) k) >> 0) & 0x3),
8328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      L(l, (((unsigned) k) >> 2) & 0x3),
8428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      Tag(tag, (((unsigned) k) >> 4) & 0x3) {
85f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getKind() == k);
86f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getLocationContext() == l);
87f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getData1() == P);
88f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek      }
89f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek
90f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  ProgramPoint(const void *P1,
91f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const void *P2,
92f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               Kind k,
93f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const LocationContext *l,
946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const ProgramPointTag *tag = nullptr)
9528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : Data1(P1),
9628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      Data2(P2, (((unsigned) k) >> 0) & 0x3),
9728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      L(l, (((unsigned) k) >> 2) & 0x3),
9828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
99f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek
100d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
10128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const void *getData1() const { return Data1; }
102c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  const void *getData2() const { return Data2.getPointer(); }
103c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  void setData2(const void *d) { Data2.setPointer(d); }
1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
106af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// Create a new ProgramPoint object that is the same as the original
107af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// except for using the specified tag value.
10863d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  ProgramPoint withTag(const ProgramPointTag *tag) const {
109c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return ProgramPoint(getData1(), getData2(), getKind(),
110f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek                        getLocationContext(), tag);
111af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  }
112af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks
1133c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// \brief Convert to the specified ProgramPoint type, asserting that this
1143c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// ProgramPoint is of the desired type.
1157a95de68c093991047ed8d339479ccad51b88663David Blaikie  template<typename T>
1167a95de68c093991047ed8d339479ccad51b88663David Blaikie  T castAs() const {
1177a95de68c093991047ed8d339479ccad51b88663David Blaikie    assert(T::isKind(*this));
1187a95de68c093991047ed8d339479ccad51b88663David Blaikie    T t;
1197a95de68c093991047ed8d339479ccad51b88663David Blaikie    ProgramPoint& PP = t;
1207a95de68c093991047ed8d339479ccad51b88663David Blaikie    PP = *this;
1217a95de68c093991047ed8d339479ccad51b88663David Blaikie    return t;
1227a95de68c093991047ed8d339479ccad51b88663David Blaikie  }
1237a95de68c093991047ed8d339479ccad51b88663David Blaikie
1243c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// \brief Convert to the specified ProgramPoint type, returning None if this
1253c16431cb973079d178338833dafd6b483bf8c8dDavid Blaikie  /// ProgramPoint is not of the desired type.
1267a95de68c093991047ed8d339479ccad51b88663David Blaikie  template<typename T>
1277a95de68c093991047ed8d339479ccad51b88663David Blaikie  Optional<T> getAs() const {
1287a95de68c093991047ed8d339479ccad51b88663David Blaikie    if (!T::isKind(*this))
1297a95de68c093991047ed8d339479ccad51b88663David Blaikie      return None;
1307a95de68c093991047ed8d339479ccad51b88663David Blaikie    T t;
1317a95de68c093991047ed8d339479ccad51b88663David Blaikie    ProgramPoint& PP = t;
1327a95de68c093991047ed8d339479ccad51b88663David Blaikie    PP = *this;
1337a95de68c093991047ed8d339479ccad51b88663David Blaikie    return t;
1347a95de68c093991047ed8d339479ccad51b88663David Blaikie  }
1357a95de68c093991047ed8d339479ccad51b88663David Blaikie
136f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  Kind getKind() const {
13728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    unsigned x = Tag.getInt();
138c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
13928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    x |= L.getInt();
140c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
14128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    x |= Data2.getInt();
142c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return (Kind) x;
143f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
144d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1450b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// \brief Is this a program point corresponding to purge/removal of dead
1460b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// symbols and bindings.
1470b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  bool isPurgeKind() {
1480b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    Kind K = getKind();
1490b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return (K == PostStmtPurgeDeadSymbolsKind ||
1500b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks            K == PreStmtPurgeDeadSymbolsKind);
1510b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
1520b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
15328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
15458465900ca10e53b8700a64e9265870de34e1acaTed Kremenek
155f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  const LocationContext *getLocationContext() const {
156c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return L.getPointer();
157f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
15825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
159e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek  // For use with DenseMap.  This hash is probably slow.
160d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  unsigned getHashValue() const {
161e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    llvm::FoldingSetNodeID ID;
162d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    Profile(ID);
163e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    return ID.ComputeHash();
164d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
166d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  bool operator==(const ProgramPoint & RHS) const {
1676403683411dac55afbe3435ceb19033e27cd9f96Ted Kremenek    return Data1 == RHS.Data1 &&
168c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 == RHS.Data2 &&
169c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L == RHS.L &&
170c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag == RHS.Tag;
171d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
172d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1739c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool operator!=(const ProgramPoint &RHS) const {
174c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return Data1 != RHS.Data1 ||
175c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 != RHS.Data2 ||
176c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L != RHS.L ||
177c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag != RHS.Tag;
178d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1805226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek  void Profile(llvm::FoldingSetNodeID& ID) const {
181f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddInteger((unsigned) getKind());
182f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getData1());
183c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    ID.AddPointer(getData2());
184f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getLocationContext());
18528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    ID.AddPointer(getTag());
1862680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenek  }
18763d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks
18863d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
18963d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const LocationContext *LC,
19063d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const ProgramPointTag *tag);
191eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEntrance : public ProgramPoint {
194eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
1959c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEntrance(const CFGBlock *B, const LocationContext *L,
1966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                const ProgramPointTag *tag = nullptr)
1972f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    : ProgramPoint(B, BlockEntranceKind, L, tag) {
1982f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    assert(B && "BlockEntrance requires non-null block");
1992f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek  }
2001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2019c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
20203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
203bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
205b07805485c603be3d8011f72611465324c9e664bDavid Blaikie  Optional<CFGElement> getFirstElement() const {
2069c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const CFGBlock *B = getBlock();
207b07805485c603be3d8011f72611465324c9e664bDavid Blaikie    return B->empty() ? Optional<CFGElement>() : B->front();
208852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek  }
209852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
2107a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2117a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2127a95de68c093991047ed8d339479ccad51b88663David Blaikie  BlockEntrance() {}
2137a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2147a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == BlockEntranceKind;
215bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
216eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
21783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
21883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockExit : public ProgramPoint {
219eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2209c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockExit(const CFGBlock *B, const LocationContext *L)
22125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(B, BlockExitKind, L) {}
2221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2239c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
22403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
225bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
22683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
2279c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Stmt *getTerminator() const {
22883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return getBlock()->getTerminator();
229bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2317a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2327a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2337a95de68c093991047ed8d339479ccad51b88663David Blaikie  BlockExit() {}
2347a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2357a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == BlockExitKind;
236bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
237bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek};
2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2395f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass StmtPoint : public ProgramPoint {
2405f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekpublic:
2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
242ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag)
2431edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks    : ProgramPoint(S, p2, k, L, tag) {
2441edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks    assert(S);
2451edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks  }
2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2475f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
2481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2495f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  template <typename T>
250cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2527a95de68c093991047ed8d339479ccad51b88663David Blaikieprotected:
2537a95de68c093991047ed8d339479ccad51b88663David Blaikie  StmtPoint() {}
2547a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2557a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2567a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2577a95de68c093991047ed8d339479ccad51b88663David Blaikie    unsigned k = Location.getKind();
2585f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    return k >= PreStmtKind && k <= MaxPostStmtKind;
2595f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  }
2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
262eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
2635f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PreStmt : public StmtPoint {
264cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenekpublic:
265ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
2666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          const Stmt *SubStmt = nullptr)
26725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
268cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
270cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2717a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2727a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2737a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreStmt() {}
2747a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2757a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PreStmtKind;
276cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  }
277cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek};
278cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2795f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PostStmt : public StmtPoint {
2801b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekprotected:
2817a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostStmt() {}
2829c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
2836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           const ProgramPointTag *tag = nullptr)
28425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, data, k, L, tag) {}
2851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
286eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
2886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    const ProgramPointTag *tag = nullptr)
2896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, k, L, tag) {}
2904bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek
2919c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, const LocationContext *L,
2926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    const ProgramPointTag *tag = nullptr)
2936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
29483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
2957a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
2967a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
2977a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
2987a95de68c093991047ed8d339479ccad51b88663David Blaikie    unsigned k = Location.getKind();
299f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
3001b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  }
3011b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek};
3028c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek
3038083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek// PostCondition represents the post program point of a branch condition.
3048083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekclass PostCondition : public PostStmt {
3058083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekpublic:
3069c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostCondition(const Stmt *S, const LocationContext *L,
3076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                const ProgramPointTag *tag = nullptr)
3088083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    : PostStmt(S, PostConditionKind, L, tag) {}
3098083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
3107a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3117a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3127a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostCondition() {}
3137a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
3147a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostConditionKind;
3158083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  }
3168083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek};
3178083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
318b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass LocationCheck : public StmtPoint {
319b4b817d704287836b52b34369009e682f208aa2bTed Kremenekprotected:
3207a95de68c093991047ed8d339479ccad51b88663David Blaikie  LocationCheck() {}
321b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  LocationCheck(const Stmt *S, const LocationContext *L,
322ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                ProgramPoint::Kind K, const ProgramPointTag *tag)
3236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, K, L, tag) {}
324b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
3257a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3267a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3277a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &location) {
3287a95de68c093991047ed8d339479ccad51b88663David Blaikie    unsigned k = location.getKind();
329d651141308a777d60ff98309d21e045bb936f8b7Ted Kremenek    return k == PreLoadKind || k == PreStoreKind;
3308c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3318c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
332b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
333b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreLoad : public LocationCheck {
3348c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
335ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreLoad(const Stmt *S, const LocationContext *L,
3366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          const ProgramPointTag *tag = nullptr)
337b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : LocationCheck(S, L, PreLoadKind, tag) {}
338b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
3397a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3407a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3417a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreLoad() {}
3427a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &location) {
3437a95de68c093991047ed8d339479ccad51b88663David Blaikie    return location.getKind() == PreLoadKind;
3448c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3458c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
347b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreStore : public LocationCheck {
3488c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
349ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStore(const Stmt *S, const LocationContext *L,
3506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           const ProgramPointTag *tag = nullptr)
351b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  : LocationCheck(S, L, PreStoreKind, tag) {}
352b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
3537a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3547a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3557a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreStore() {}
3567a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &location) {
3577a95de68c093991047ed8d339479ccad51b88663David Blaikie    return location.getKind() == PreStoreKind;
3588c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3598c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3611b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekclass PostLoad : public PostStmt {
3621b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekpublic:
3639c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLoad(const Stmt *S, const LocationContext *L,
3646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           const ProgramPointTag *tag = nullptr)
36525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLoadKind, L, tag) {}
3661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3677a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3687a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3697a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostLoad() {}
3707a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
3717a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostLoadKind;
372bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
373eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37541c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// \brief Represents a program point after a store evaluation.
37682bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekclass PostStore : public PostStmt {
37782bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekpublic:
3783d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// Construct the post store point.
3793d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \param Loc can be used to store the information about the location
3803d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// used in the form it was uttered in the code.
3813d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
3826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines            const ProgramPointTag *tag = nullptr)
3833d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    : PostStmt(S, PostStoreKind, L, tag) {
3846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    assert(getData2() == nullptr);
3853d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    setData2(Loc);
3863d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3883d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \brief Returns the information about the location used in the store,
3893d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// how it was uttered in the code.
3903d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  const void *getLocationValue() const {
3913d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    return getData2();
3923d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3933d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
3947a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
3957a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
3967a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostStore() {}
3977a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
3987a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostStoreKind;
3997a95de68c093991047ed8d339479ccad51b88663David Blaikie  }
40082bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek};
4017090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek
4027090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekclass PostLValue : public PostStmt {
4037090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekpublic:
4049c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLValue(const Stmt *S, const LocationContext *L,
4056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines             const ProgramPointTag *tag = nullptr)
40625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLValueKind, L, tag) {}
4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4087a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4097a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4107a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostLValue() {}
4117a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4127a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostLValueKind;
4137090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  }
4141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
4151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
41641c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings BEFORE
4170b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the given statement.
41851a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PreStmtPurgeDeadSymbols : public StmtPoint {
419331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekpublic:
4200b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
4216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       const ProgramPointTag *tag = nullptr)
4226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
4231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4247a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4257a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4267a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreStmtPurgeDeadSymbols() {}
4277a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4287a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
4290b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
4300b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
4310b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
43241c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings AFTER
4330b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the  given statement.
43451a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PostStmtPurgeDeadSymbols : public StmtPoint {
4350b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
4360b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
4376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       const ProgramPointTag *tag = nullptr)
4386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
4390b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
4407a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4417a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4427a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostStmtPurgeDeadSymbols() {}
4437a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4447a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
445331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  }
446331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek};
4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
44883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEdge : public ProgramPoint {
449b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenekpublic:
4509c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
451e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
452e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B1 && "BlockEdge: source block must be non-null");
453e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B2 && "BlockEdge: destination block must be non-null");
454e4c6675cccbaac991843def43072687bca50d989Ted Kremenek  }
4551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4569c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getSrc() const {
45703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData1());
458d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
4591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4609c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getDst() const {
46103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData2());
462d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4647a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4657a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4667a95de68c093991047ed8d339479ccad51b88663David Blaikie  BlockEdge() {}
4677a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4687a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == BlockEdgeKind;
469b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek  }
470b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek};
47183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
4729dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xuclass PostInitializer : public ProgramPoint {
4739dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xupublic:
474610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \brief Construct a PostInitializer point that represents a location after
475610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  ///   CXXCtorInitializer expression evaluation.
476610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  ///
477610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \param I The initializer.
478610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \param Loc The location of the field being initialized.
479610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  PostInitializer(const CXXCtorInitializer *I,
480610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks                  const void *Loc,
4819dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu                  const LocationContext *L)
482610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks    : ProgramPoint(I, Loc, PostInitializerKind, L) {}
4839dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
4841aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose  const CXXCtorInitializer *getInitializer() const {
4851aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose    return static_cast<const CXXCtorInitializer *>(getData1());
4861aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose  }
4871aa4f5019164592643bf46b7d61f15b6ef509c8eJordan Rose
488610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  /// \brief Returns the location of the field.
489610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  const void *getLocationValue() const {
490610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks    return getData2();
491610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks  }
492610f79cbab4d752349b5c81a94682a6a82b102e7Anna Zaks
4937a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
4947a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
4957a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostInitializer() {}
4967a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
4977a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostInitializerKind;
4989dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  }
4999dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu};
5009dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
50128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents an implicit call event.
50228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
50328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// The nearest statement is provided for diagnostic purposes.
50428038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass ImplicitCallPoint : public ProgramPoint {
50528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
50628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
50728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                    const LocationContext *L, const ProgramPointTag *Tag)
50828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
50928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
51028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
51128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  SourceLocation getLocation() const {
51228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return SourceLocation::getFromPtrEncoding(getData1());
51328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
51428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
5157a95de68c093991047ed8d339479ccad51b88663David Blaikieprotected:
5167a95de68c093991047ed8d339479ccad51b88663David Blaikie  ImplicitCallPoint() {}
5177a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5187a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5197a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5207a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() >= MinImplicitCallKind &&
5217a95de68c093991047ed8d339479ccad51b88663David Blaikie           Location.getKind() <= MaxImplicitCallKind;
52228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
52328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
52428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
52528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just before an implicit call event.
52628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
52728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PreStmt program points.
52828038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PreImplicitCall : public ImplicitCallPoint {
52928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
5306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
5316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                  const ProgramPointTag *Tag = nullptr)
53228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
53328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
5347a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5357a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5367a95de68c093991047ed8d339479ccad51b88663David Blaikie  PreImplicitCall() {}
5377a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5387a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PreImplicitCallKind;
53928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
54028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
54128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
54228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just after an implicit call event.
54328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
54428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PostStmt program points.
54528038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PostImplicitCall : public ImplicitCallPoint {
54628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
5476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
5486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                   const ProgramPointTag *Tag = nullptr)
54928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
55028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
5517a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5527a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5537a95de68c093991047ed8d339479ccad51b88663David Blaikie  PostImplicitCall() {}
5547a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5557a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == PostImplicitCallKind;
55628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
55728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
55828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
55941c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we begin processing an inlined call.
56080de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks/// CallEnter uses the caller's location context.
561852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallEnter : public ProgramPoint {
562102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
56319b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
56419b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu            const LocationContext *callerCtx)
5656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
566102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
567102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  const Stmt *getCallExpr() const {
568102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return static_cast<const Stmt *>(getData1());
569102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
570102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
57119b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  const StackFrameContext *getCalleeContext() const {
57219b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    return static_cast<const StackFrameContext *>(getData2());
573102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
574102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
5757a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5767a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
5777a95de68c093991047ed8d339479ccad51b88663David Blaikie  CallEnter() {}
5787a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
5797a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == CallEnterKind;
580102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
581102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
582102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
58341c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we start the call exit sequence (for inlined call).
5840b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks///
5850b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// The call exit is simulated with a sequence of nodes, which occur between
5860b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// CallExitBegin and CallExitEnd. The following operations occur between the
5870b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// two program points:
5880b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitBegin
5890b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Bind the return value
5900b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
5910b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitEnd
592852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitBegin : public ProgramPoint {
5930b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
5940b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitBegin uses the callee's location context.
595852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitBegin(const StackFrameContext *L)
5966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {}
5970b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
5987a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
5997a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
6007a95de68c093991047ed8d339479ccad51b88663David Blaikie  CallExitBegin() {}
6017a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
6027a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == CallExitBeginKind;
6030b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
6040b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
6050b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
60641c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we finish the call exit sequence (for inlined call).
6070b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \sa CallExitBegin
608852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitEnd : public ProgramPoint {
609102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
6100b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitEnd uses the caller's location context.
611852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitEnd(const StackFrameContext *CalleeCtx,
612852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              const LocationContext *CallerCtx)
6136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
614852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose
615852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  const StackFrameContext *getCalleeContext() const {
616852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    return static_cast<const StackFrameContext *>(getData1());
617852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  }
618102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
6197a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
6207a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
6217a95de68c093991047ed8d339479ccad51b88663David Blaikie  CallExitEnd() {}
6227a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
6237a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == CallExitEndKind;
624102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
625102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
626102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
6275903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// This is a meta program point, which should be skipped by all the diagnostic
6285903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// reasoning etc.
6295903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaksclass EpsilonPoint : public ProgramPoint {
6305903a373db3d27794c90b25687e0dd6adb0e497dAnna Zakspublic:
6315903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  EpsilonPoint(const LocationContext *L, const void *Data1,
6326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const void *Data2 = nullptr,
6336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines               const ProgramPointTag *tag = nullptr)
6345903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
6355903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
6365903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  const void *getData() const { return getData1(); }
6375903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
6387a95de68c093991047ed8d339479ccad51b88663David Blaikieprivate:
6397a95de68c093991047ed8d339479ccad51b88663David Blaikie  friend class ProgramPoint;
6407a95de68c093991047ed8d339479ccad51b88663David Blaikie  EpsilonPoint() {}
6417a95de68c093991047ed8d339479ccad51b88663David Blaikie  static bool isKind(const ProgramPoint &Location) {
6427a95de68c093991047ed8d339479ccad51b88663David Blaikie    return Location.getKind() == EpsilonKind;
6435903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  }
6445903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks};
6455903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
646ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// ProgramPoints can be "tagged" as representing points specific to a given
647ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// analysis entity.  Tags are abstract annotations, with an associated
648ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// description and potentially other information.
649ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag {
650ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
6516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
652ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual ~ProgramPointTag();
653ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual StringRef getTagDescription() const = 0;
654ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
655ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprotected:
6567a95de68c093991047ed8d339479ccad51b88663David Blaikie  /// Used to implement 'isKind' in subclasses.
657ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *getTagKind() { return TagKind; }
658ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
659ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprivate:
660ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *TagKind;
661ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
662651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
663ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass SimpleProgramPointTag : public ProgramPointTag {
664651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::string Desc;
665ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StringRef getTagDescription() const override;
668ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
6691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
670eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek} // end namespace clang
6714c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
6724c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
6731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnamespace llvm { // Traits specialization for DenseMap
6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
67583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenektemplate <> struct DenseMapInfo<clang::ProgramPoint> {
6764c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
677d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getEmptyKey() {
678d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
6791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
6806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
681d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
682d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
683d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getTombstoneKey() {
684d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
68525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
6866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
687d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
688d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
6899c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic unsigned getHashValue(const clang::ProgramPoint &Loc) {
690d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return Loc.getHashValue();
691d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
692d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
6939c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic bool isEqual(const clang::ProgramPoint &L,
6949c378f705405d37f49795d5e915989de774fe11fTed Kremenek                    const clang::ProgramPoint &R) {
695d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return L == R;
696d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
697d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
6984c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek};
69906159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
70006159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnertemplate <>
70106159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnerstruct isPodLike<clang::ProgramPoint> { static const bool value = true; };
70206159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
7034c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek} // end namespace llvm
7044c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
705eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#endif
706