ProgramPoint.h revision 1edeed3b0fe01fb07a769bd1acc2ce2dc9ec431d
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"
2003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/DataTypes.h"
214c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek#include "llvm/ADT/DenseMap.h"
22c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek#include "llvm/ADT/PointerIntPair.h"
235226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek#include "llvm/ADT/FoldingSet.h"
246bad354120ce0d35901e86ca63e5534b7b9ed092Ted Kremenek#include "llvm/Support/Casting.h"
25ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "llvm/ADT/StringRef.h"
264c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek#include <cassert>
2759753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek#include <utility>
28ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include <string>
29eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
30eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremeneknamespace clang {
3125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
321d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekclass AnalysisDeclContext;
33102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass FunctionDecl;
34ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass LocationContext;
35ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag;
36ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
3783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass ProgramPoint {
38eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
39cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  enum Kind { BlockEdgeKind,
40cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockEntranceKind,
41cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockExitKind,
42cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PreStmtKind,
4351a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks              PreStmtPurgeDeadSymbolsKind,
4451a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks              PostStmtPurgeDeadSymbolsKind,
45cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStmtKind,
46b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreLoadKind,
47cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLoadKind,
48b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreStoreKind,
49cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStoreKind,
508083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek              PostConditionKind,
51cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLValueKind,
52852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              MinPostStmtKind = PostStmtKind,
53852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              MaxPostStmtKind = PostLValueKind,
549dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu              PostInitializerKind,
55102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor              CallEnterKind,
560b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitBeginKind,
570b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitEndKind,
5828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              PreImplicitCallKind,
5928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              PostImplicitCallKind,
6028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              MinImplicitCallKind = PreImplicitCallKind,
6128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose              MaxImplicitCallKind = PostImplicitCallKind,
625903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks              EpsilonKind};
634c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
64d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprivate:
6528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const void *Data1;
66c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const void *, 2, unsigned> Data2;
6725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
6825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // The LocationContext could be NULL to allow ProgramPoint to be used in
6925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // context insensitive analysis.
70c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
71c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek
7228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
74ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  ProgramPoint();
75ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
76d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
77f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  ProgramPoint(const void *P,
78f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               Kind k,
79f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const LocationContext *l,
80ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek               const ProgramPointTag *tag = 0)
8128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : Data1(P),
8228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose      Data2(0, (((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,
94ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek               const ProgramPointTag *tag = 0)
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
113f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  Kind getKind() const {
11428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    unsigned x = Tag.getInt();
115c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
11628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    x |= L.getInt();
117c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
11828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    x |= Data2.getInt();
119c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return (Kind) x;
120f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
121d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1220b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// \brief Is this a program point corresponding to purge/removal of dead
1230b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// symbols and bindings.
1240b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  bool isPurgeKind() {
1250b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    Kind K = getKind();
1260b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return (K == PostStmtPurgeDeadSymbolsKind ||
1270b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks            K == PreStmtPurgeDeadSymbolsKind);
1280b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
1290b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
13028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const ProgramPointTag *getTag() const { return Tag.getPointer(); }
13158465900ca10e53b8700a64e9265870de34e1acaTed Kremenek
132f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  const LocationContext *getLocationContext() const {
133c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return L.getPointer();
134f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
13525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
136e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek  // For use with DenseMap.  This hash is probably slow.
137d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  unsigned getHashValue() const {
138e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    llvm::FoldingSetNodeID ID;
139d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    Profile(ID);
140e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    return ID.ComputeHash();
141d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
14383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint*) { return true; }
144d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
145d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  bool operator==(const ProgramPoint & RHS) const {
1466403683411dac55afbe3435ceb19033e27cd9f96Ted Kremenek    return Data1 == RHS.Data1 &&
147c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 == RHS.Data2 &&
148c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L == RHS.L &&
149c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag == RHS.Tag;
150d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
151d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1529c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool operator!=(const ProgramPoint &RHS) const {
153c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return Data1 != RHS.Data1 ||
154c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 != RHS.Data2 ||
155c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L != RHS.L ||
156c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag != RHS.Tag;
157d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1595226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek  void Profile(llvm::FoldingSetNodeID& ID) const {
160f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddInteger((unsigned) getKind());
161f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getData1());
162c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    ID.AddPointer(getData2());
163f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getLocationContext());
16428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    ID.AddPointer(getTag());
1652680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenek  }
16663d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks
16763d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
16863d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const LocationContext *LC,
16963d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const ProgramPointTag *tag);
170eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
1711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
17283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEntrance : public ProgramPoint {
173eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
1749c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEntrance(const CFGBlock *B, const LocationContext *L,
175ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                const ProgramPointTag *tag = 0)
1762f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    : ProgramPoint(B, BlockEntranceKind, L, tag) {
1772f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    assert(B && "BlockEntrance requires non-null block");
1782f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek  }
1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1809c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
18103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
182bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
1831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  const CFGElement getFirstElement() const {
1859c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const CFGBlock *B = getBlock();
186852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    return B->empty() ? CFGElement() : B->front();
187852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek  }
188852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
18983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
19083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return Location->getKind() == BlockEntranceKind;
191bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
192eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
19383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
19483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockExit : public ProgramPoint {
195eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
1969c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockExit(const CFGBlock *B, const LocationContext *L)
19725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(B, BlockExitKind, L) {}
1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1999c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
20003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
201bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
20283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
2039c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Stmt *getTerminator() const {
20483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return getBlock()->getTerminator();
205bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
2061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
20883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return Location->getKind() == BlockExitKind;
209bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
210bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek};
2111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2125f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass StmtPoint : public ProgramPoint {
2135f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekpublic:
2141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
215ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag)
2161edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks    : ProgramPoint(S, p2, k, L, tag) {
2171edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks    assert(S);
2181edeed3b0fe01fb07a769bd1acc2ce2dc9ec431dAnna Zaks  }
2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2205f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2225f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  template <typename T>
2235f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
2241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2255f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2265f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    unsigned k = Location->getKind();
2275f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    return k >= PreStmtKind && k <= MaxPostStmtKind;
2285f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  }
2291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
231eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
2325f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PreStmt : public StmtPoint {
233cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenekpublic:
234ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
23525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu          const Stmt *SubStmt = 0)
23625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
237cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
239cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
240cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  static bool classof(const ProgramPoint* Location) {
241cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek    return Location->getKind() == PreStmtKind;
242cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  }
243cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek};
244cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2455f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PostStmt : public StmtPoint {
2461b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekprotected:
2479c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
2483d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks           const ProgramPointTag *tag = 0)
24925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, data, k, L, tag) {}
2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
251eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2529c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, Kind k,
253ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const LocationContext *L, const ProgramPointTag *tag = 0)
2544bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek    : StmtPoint(S, NULL, k, L, tag) {}
2554bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek
2569c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, const LocationContext *L,
257ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const ProgramPointTag *tag = 0)
25825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
25983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
26083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2611b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    unsigned k = Location->getKind();
262f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
2631b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  }
2641b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek};
2658c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek
2668083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek// PostCondition represents the post program point of a branch condition.
2678083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekclass PostCondition : public PostStmt {
2688083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekpublic:
2699c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostCondition(const Stmt *S, const LocationContext *L,
270ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                const ProgramPointTag *tag = 0)
2718083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    : PostStmt(S, PostConditionKind, L, tag) {}
2728083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
2738083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2748083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    return Location->getKind() == PostConditionKind;
2758083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  }
2768083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek};
2778083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
278b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass LocationCheck : public StmtPoint {
279b4b817d704287836b52b34369009e682f208aa2bTed Kremenekprotected:
280b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  LocationCheck(const Stmt *S, const LocationContext *L,
281ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                ProgramPoint::Kind K, const ProgramPointTag *tag)
282b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : StmtPoint(S, NULL, K, L, tag) {}
283b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
284b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
285b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    unsigned k = location->getKind();
286d651141308a777d60ff98309d21e045bb936f8b7Ted Kremenek    return k == PreLoadKind || k == PreStoreKind;
2878c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2888c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
289b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
290b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreLoad : public LocationCheck {
2918c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
292ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreLoad(const Stmt *S, const LocationContext *L,
293ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek          const ProgramPointTag *tag = 0)
294b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : LocationCheck(S, L, PreLoadKind, tag) {}
295b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
296b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
297b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreLoadKind;
2988c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2998c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
301b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreStore : public LocationCheck {
3028c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
303ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStore(const Stmt *S, const LocationContext *L,
304ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
305b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  : LocationCheck(S, L, PreStoreKind, tag) {}
306b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
307b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
308b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreStoreKind;
3098c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3108c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3121b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekclass PostLoad : public PostStmt {
3131b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekpublic:
3149c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLoad(const Stmt *S, const LocationContext *L,
315ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
31625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLoadKind, L, tag) {}
3171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3181b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  static bool classof(const ProgramPoint* Location) {
3191b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    return Location->getKind() == PostLoadKind;
320bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
321eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
3221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32341c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// \brief Represents a program point after a store evaluation.
32482bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekclass PostStore : public PostStmt {
32582bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekpublic:
3263d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// Construct the post store point.
3273d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \param Loc can be used to store the information about the location
3283d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// used in the form it was uttered in the code.
3293d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
330ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag = 0)
3313d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    : PostStmt(S, PostStoreKind, L, tag) {
3323d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    assert(getData2() == 0);
3333d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    setData2(Loc);
3343d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33682bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  static bool classof(const ProgramPoint* Location) {
33782bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek    return Location->getKind() == PostStoreKind;
33882bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  }
3393d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
3403d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \brief Returns the information about the location used in the store,
3413d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// how it was uttered in the code.
3423d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  const void *getLocationValue() const {
3433d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    return getData2();
3443d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3453d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
34682bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek};
3477090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek
3487090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekclass PostLValue : public PostStmt {
3497090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekpublic:
3509c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLValue(const Stmt *S, const LocationContext *L,
351ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek             const ProgramPointTag *tag = 0)
35225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLValueKind, L, tag) {}
3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3547090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  static bool classof(const ProgramPoint* Location) {
3557090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek    return Location->getKind() == PostLValueKind;
3567090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  }
3571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35941c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings BEFORE
3600b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the given statement.
36151a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PreStmtPurgeDeadSymbols : public StmtPoint {
362331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekpublic:
3630b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
364ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                       const ProgramPointTag *tag = 0)
36551a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks    : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { }
3661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
367331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  static bool classof(const ProgramPoint* Location) {
3680b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == PreStmtPurgeDeadSymbolsKind;
3690b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
3700b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
3710b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
37241c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings AFTER
3730b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the  given statement.
37451a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PostStmtPurgeDeadSymbols : public StmtPoint {
3750b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
3760b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
3770b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                       const ProgramPointTag *tag = 0)
37851a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks    : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { }
3790b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
3800b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  static bool classof(const ProgramPoint* Location) {
3810b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == PostStmtPurgeDeadSymbolsKind;
382331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  }
383331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek};
3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
38583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEdge : public ProgramPoint {
386b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenekpublic:
3879c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
388e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
389e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B1 && "BlockEdge: source block must be non-null");
390e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B2 && "BlockEdge: destination block must be non-null");
391e4c6675cccbaac991843def43072687bca50d989Ted Kremenek  }
3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3939c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getSrc() const {
39403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData1());
395d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
3961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3979c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getDst() const {
39803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData2());
399d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
4001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
40183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
402d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek    return Location->getKind() == BlockEdgeKind;
403b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek  }
404b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek};
40583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
4069dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xuclass PostInitializer : public ProgramPoint {
4079dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xupublic:
408cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt  PostInitializer(const CXXCtorInitializer *I,
4099dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu                  const LocationContext *L)
4109dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    : ProgramPoint(I, PostInitializerKind, L) {}
4119dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
4129dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  static bool classof(const ProgramPoint *Location) {
4139dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    return Location->getKind() == PostInitializerKind;
4149dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  }
4159dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu};
4169dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
41728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents an implicit call event.
41828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
41928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// The nearest statement is provided for diagnostic purposes.
42028038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass ImplicitCallPoint : public ProgramPoint {
42128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
42228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
42328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                    const LocationContext *L, const ProgramPointTag *Tag)
42428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
42528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
42628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
42728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  SourceLocation getLocation() const {
42828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return SourceLocation::getFromPtrEncoding(getData1());
42928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
43028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
43128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  static bool classof(const ProgramPoint *Location) {
43228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return Location->getKind() >= MinImplicitCallKind &&
43328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose           Location->getKind() <= MaxImplicitCallKind;
43428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
43528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
43628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
43728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just before an implicit call event.
43828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
43928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PreStmt program points.
44028038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PreImplicitCall : public ImplicitCallPoint {
44128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
44228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  PreImplicitCall(const Decl *D, SourceLocation Loc,
44328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                  const LocationContext *L, const ProgramPointTag *Tag = 0)
44428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
44528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
44628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  static bool classof(const ProgramPoint *Location) {
44728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return Location->getKind() == PreImplicitCallKind;
44828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
44928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
45028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
45128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just after an implicit call event.
45228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
45328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PostStmt program points.
45428038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PostImplicitCall : public ImplicitCallPoint {
45528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
45628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  PostImplicitCall(const Decl *D, SourceLocation Loc,
45728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                   const LocationContext *L, const ProgramPointTag *Tag = 0)
45828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
45928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
46028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  static bool classof(const ProgramPoint *Location) {
46128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return Location->getKind() == PostImplicitCallKind;
46228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
46328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
46428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
46541c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we begin processing an inlined call.
46680de487e03dd0f44e4572e2122ebc1aa6a3961f5Anna Zaks/// CallEnter uses the caller's location context.
467852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallEnter : public ProgramPoint {
468102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
46919b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
47019b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu            const LocationContext *callerCtx)
471852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
472102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
473102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  const Stmt *getCallExpr() const {
474102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return static_cast<const Stmt *>(getData1());
475102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
476102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
47719b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  const StackFrameContext *getCalleeContext() const {
47819b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    return static_cast<const StackFrameContext *>(getData2());
479102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
480102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
481102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
482102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return Location->getKind() == CallEnterKind;
483102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
484102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
485102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
48641c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we start the call exit sequence (for inlined call).
4870b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks///
4880b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// The call exit is simulated with a sequence of nodes, which occur between
4890b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// CallExitBegin and CallExitEnd. The following operations occur between the
4900b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// two program points:
4910b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitBegin
4920b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Bind the return value
4930b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
4940b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitEnd
495852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitBegin : public ProgramPoint {
4960b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
4970b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitBegin uses the callee's location context.
498852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitBegin(const StackFrameContext *L)
499852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    : ProgramPoint(0, CallExitBeginKind, L, 0) {}
5000b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
5010b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  static bool classof(const ProgramPoint *Location) {
5020b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == CallExitBeginKind;
5030b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
5040b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
5050b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
50641c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we finish the call exit sequence (for inlined call).
5070b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \sa CallExitBegin
508852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitEnd : public ProgramPoint {
509102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
5100b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitEnd uses the caller's location context.
511852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitEnd(const StackFrameContext *CalleeCtx,
512852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              const LocationContext *CallerCtx)
513852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, 0) {}
514852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose
515852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  const StackFrameContext *getCalleeContext() const {
516852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    return static_cast<const StackFrameContext *>(getData1());
517852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  }
518102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
519102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
5200b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == CallExitEndKind;
521102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
522102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
523102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
5245903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// This is a meta program point, which should be skipped by all the diagnostic
5255903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// reasoning etc.
5265903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaksclass EpsilonPoint : public ProgramPoint {
5275903a373db3d27794c90b25687e0dd6adb0e497dAnna Zakspublic:
5285903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  EpsilonPoint(const LocationContext *L, const void *Data1,
5295903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks               const void *Data2 = 0, const ProgramPointTag *tag = 0)
5305903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
5315903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
5325903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  const void *getData() const { return getData1(); }
5335903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
5345903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  static bool classof(const ProgramPoint* Location) {
5355903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    return Location->getKind() == EpsilonKind;
5365903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  }
5375903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks};
5385903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
539ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// ProgramPoints can be "tagged" as representing points specific to a given
540ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// analysis entity.  Tags are abstract annotations, with an associated
541ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// description and potentially other information.
542ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag {
543ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
544ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
545ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual ~ProgramPointTag();
546ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual StringRef getTagDescription() const = 0;
547ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
548ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprotected:
5491ab69c513239596946286373e081b89fa3358612Ted Kremenek  /// Used to implement 'classof' in subclasses.
550ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *getTagKind() { return TagKind; }
551ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
552ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprivate:
553ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *TagKind;
554ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
555ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
556ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass SimpleProgramPointTag : public ProgramPointTag {
557ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  std::string desc;
558ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
559ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  SimpleProgramPointTag(StringRef description);
560ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  StringRef getTagDescription() const;
561ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
5621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
563eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek} // end namespace clang
5644c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
5654c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
5661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnamespace llvm { // Traits specialization for DenseMap
5671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
56883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenektemplate <> struct DenseMapInfo<clang::ProgramPoint> {
5694c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
570d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getEmptyKey() {
571d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
5721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
57325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
574d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
575d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
576d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getTombstoneKey() {
577d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
57825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
57925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
580d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
581d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5829c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic unsigned getHashValue(const clang::ProgramPoint &Loc) {
583d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return Loc.getHashValue();
584d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
585d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5869c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic bool isEqual(const clang::ProgramPoint &L,
5879c378f705405d37f49795d5e915989de774fe11fTed Kremenek                    const clang::ProgramPoint &R) {
588d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return L == R;
589d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
590d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5914c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek};
59206159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
59306159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnertemplate <>
59406159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnerstruct isPodLike<clang::ProgramPoint> { static const bool value = true; };
59506159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
5964c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek} // end namespace llvm
5974c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
598eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#endif
599