ProgramPoint.h revision 852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5
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)
21625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(S, p2, k, L, tag) {}
2171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2185f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2205f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  template <typename T>
2215f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
2221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2235f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2245f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    unsigned k = Location->getKind();
2255f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    return k >= PreStmtKind && k <= MaxPostStmtKind;
2265f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  }
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
229eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
2305f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PreStmt : public StmtPoint {
231cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenekpublic:
232ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
23325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu          const Stmt *SubStmt = 0)
23425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
235cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
237cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
238cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  static bool classof(const ProgramPoint* Location) {
239cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek    return Location->getKind() == PreStmtKind;
240cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  }
241cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek};
242cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2435f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PostStmt : public StmtPoint {
2441b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekprotected:
2459c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
2463d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks           const ProgramPointTag *tag = 0)
24725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, data, k, L, tag) {}
2481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
249eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2509c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, Kind k,
251ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const LocationContext *L, const ProgramPointTag *tag = 0)
2524bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek    : StmtPoint(S, NULL, k, L, tag) {}
2534bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek
2549c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, const LocationContext *L,
255ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const ProgramPointTag *tag = 0)
25625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
25783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
25883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2591b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    unsigned k = Location->getKind();
260f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
2611b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  }
2621b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek};
2638c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek
2648083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek// PostCondition represents the post program point of a branch condition.
2658083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekclass PostCondition : public PostStmt {
2668083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekpublic:
2679c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostCondition(const Stmt *S, const LocationContext *L,
268ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                const ProgramPointTag *tag = 0)
2698083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    : PostStmt(S, PostConditionKind, L, tag) {}
2708083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
2718083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2728083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    return Location->getKind() == PostConditionKind;
2738083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  }
2748083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek};
2758083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
276b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass LocationCheck : public StmtPoint {
277b4b817d704287836b52b34369009e682f208aa2bTed Kremenekprotected:
278b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  LocationCheck(const Stmt *S, const LocationContext *L,
279ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                ProgramPoint::Kind K, const ProgramPointTag *tag)
280b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : StmtPoint(S, NULL, K, L, tag) {}
281b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
282b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
283b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    unsigned k = location->getKind();
284d651141308a777d60ff98309d21e045bb936f8b7Ted Kremenek    return k == PreLoadKind || k == PreStoreKind;
2858c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2868c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
287b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
288b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreLoad : public LocationCheck {
2898c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
290ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreLoad(const Stmt *S, const LocationContext *L,
291ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek          const ProgramPointTag *tag = 0)
292b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : LocationCheck(S, L, PreLoadKind, tag) {}
293b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
294b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
295b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreLoadKind;
2968c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2978c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
299b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreStore : public LocationCheck {
3008c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
301ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStore(const Stmt *S, const LocationContext *L,
302ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
303b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  : LocationCheck(S, L, PreStoreKind, tag) {}
304b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
305b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
306b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreStoreKind;
3078c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3088c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3101b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekclass PostLoad : public PostStmt {
3111b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekpublic:
3129c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLoad(const Stmt *S, const LocationContext *L,
313ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
31425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLoadKind, L, tag) {}
3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3161b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  static bool classof(const ProgramPoint* Location) {
3171b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    return Location->getKind() == PostLoadKind;
318bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
319eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32141c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// \brief Represents a program point after a store evaluation.
32282bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekclass PostStore : public PostStmt {
32382bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekpublic:
3243d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// Construct the post store point.
3253d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \param Loc can be used to store the information about the location
3263d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// used in the form it was uttered in the code.
3273d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
328ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag = 0)
3293d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    : PostStmt(S, PostStoreKind, L, tag) {
3303d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    assert(getData2() == 0);
3313d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    setData2(Loc);
3323d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33482bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  static bool classof(const ProgramPoint* Location) {
33582bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek    return Location->getKind() == PostStoreKind;
33682bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  }
3373d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
3383d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \brief Returns the information about the location used in the store,
3393d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// how it was uttered in the code.
3403d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  const void *getLocationValue() const {
3413d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    return getData2();
3423d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3433d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
34482bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek};
3457090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek
3467090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekclass PostLValue : public PostStmt {
3477090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekpublic:
3489c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLValue(const Stmt *S, const LocationContext *L,
349ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek             const ProgramPointTag *tag = 0)
35025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLValueKind, L, tag) {}
3511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3527090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  static bool classof(const ProgramPoint* Location) {
3537090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek    return Location->getKind() == PostLValueKind;
3547090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  }
3551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35741c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings BEFORE
3580b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the given statement.
35951a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PreStmtPurgeDeadSymbols : public StmtPoint {
360331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekpublic:
3610b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
362ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                       const ProgramPointTag *tag = 0)
36351a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks    : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { }
3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
365331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  static bool classof(const ProgramPoint* Location) {
3660b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == PreStmtPurgeDeadSymbolsKind;
3670b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
3680b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
3690b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
37041c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point after we ran remove dead bindings AFTER
3710b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the  given statement.
37251a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PostStmtPurgeDeadSymbols : public StmtPoint {
3730b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
3740b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
3750b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                       const ProgramPointTag *tag = 0)
37651a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks    : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { }
3770b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
3780b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  static bool classof(const ProgramPoint* Location) {
3790b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == PostStmtPurgeDeadSymbolsKind;
380331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  }
381331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek};
3821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
38383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEdge : public ProgramPoint {
384b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenekpublic:
3859c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
386e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
387e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B1 && "BlockEdge: source block must be non-null");
388e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B2 && "BlockEdge: destination block must be non-null");
389e4c6675cccbaac991843def43072687bca50d989Ted Kremenek  }
3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3919c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getSrc() const {
39203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData1());
393d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3959c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getDst() const {
39603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData2());
397d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
39983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
400d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek    return Location->getKind() == BlockEdgeKind;
401b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek  }
402b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek};
40383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
4049dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xuclass PostInitializer : public ProgramPoint {
4059dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xupublic:
406cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt  PostInitializer(const CXXCtorInitializer *I,
4079dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu                  const LocationContext *L)
4089dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    : ProgramPoint(I, PostInitializerKind, L) {}
4099dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
4109dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  static bool classof(const ProgramPoint *Location) {
4119dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    return Location->getKind() == PostInitializerKind;
4129dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  }
4139dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu};
4149dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
41528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents an implicit call event.
41628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
41728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// The nearest statement is provided for diagnostic purposes.
41828038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass ImplicitCallPoint : public ProgramPoint {
41928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
42028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
42128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                    const LocationContext *L, const ProgramPointTag *Tag)
42228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
42328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
42428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
42528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  SourceLocation getLocation() const {
42628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return SourceLocation::getFromPtrEncoding(getData1());
42728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
42828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
42928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  static bool classof(const ProgramPoint *Location) {
43028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return Location->getKind() >= MinImplicitCallKind &&
43128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose           Location->getKind() <= MaxImplicitCallKind;
43228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
43328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
43428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
43528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just before an implicit call event.
43628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
43728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PreStmt program points.
43828038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PreImplicitCall : public ImplicitCallPoint {
43928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
44028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  PreImplicitCall(const Decl *D, SourceLocation Loc,
44128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                  const LocationContext *L, const ProgramPointTag *Tag = 0)
44228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
44328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
44428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  static bool classof(const ProgramPoint *Location) {
44528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return Location->getKind() == PreImplicitCallKind;
44628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
44728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
44828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
44928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Represents a program point just after an implicit call event.
45028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose///
45128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose/// Explicit calls will appear as PostStmt program points.
45228038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseclass PostImplicitCall : public ImplicitCallPoint {
45328038f33aa2db4833881fea757a1f0daf85ac02bJordan Rosepublic:
45428038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  PostImplicitCall(const Decl *D, SourceLocation Loc,
45528038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose                   const LocationContext *L, const ProgramPointTag *Tag = 0)
45628038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
45728038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
45828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  static bool classof(const ProgramPoint *Location) {
45928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose    return Location->getKind() == PostImplicitCallKind;
46028038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose  }
46128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose};
46228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose
46341c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we begin processing an inlined call.
464852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallEnter : public ProgramPoint {
465102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
46619b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
46719b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu            const LocationContext *callerCtx)
468852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
469102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
470102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  const Stmt *getCallExpr() const {
471102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return static_cast<const Stmt *>(getData1());
472102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
473102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
47419b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  const StackFrameContext *getCalleeContext() const {
47519b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    return static_cast<const StackFrameContext *>(getData2());
476102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
477102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
478102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
479102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return Location->getKind() == CallEnterKind;
480102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
481102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
482102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
48341c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we start the call exit sequence (for inlined call).
4840b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks///
4850b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// The call exit is simulated with a sequence of nodes, which occur between
4860b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// CallExitBegin and CallExitEnd. The following operations occur between the
4870b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// two program points:
4880b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitBegin
4890b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Bind the return value
4900b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
4910b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitEnd
492852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitBegin : public ProgramPoint {
4930b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
4940b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitBegin uses the callee's location context.
495852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitBegin(const StackFrameContext *L)
496852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    : ProgramPoint(0, CallExitBeginKind, L, 0) {}
4970b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
4980b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  static bool classof(const ProgramPoint *Location) {
4990b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == CallExitBeginKind;
5000b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
5010b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
5020b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
50341c2bcff88a23a046ee8d71451bc03717a4248f6Chandler Carruth/// Represents a point when we finish the call exit sequence (for inlined call).
5040b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \sa CallExitBegin
505852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Roseclass CallExitEnd : public ProgramPoint {
506102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
5070b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitEnd uses the caller's location context.
508852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  CallExitEnd(const StackFrameContext *CalleeCtx,
509852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose              const LocationContext *CallerCtx)
510852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, 0) {}
511852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose
512852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  const StackFrameContext *getCalleeContext() const {
513852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose    return static_cast<const StackFrameContext *>(getData1());
514852aa0d2c5d2d1faf2d77b5aa3c0848068a342c5Jordan Rose  }
515102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
516102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
5170b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == CallExitEndKind;
518102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
519102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
520102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
5215903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// This is a meta program point, which should be skipped by all the diagnostic
5225903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// reasoning etc.
5235903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaksclass EpsilonPoint : public ProgramPoint {
5245903a373db3d27794c90b25687e0dd6adb0e497dAnna Zakspublic:
5255903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  EpsilonPoint(const LocationContext *L, const void *Data1,
5265903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks               const void *Data2 = 0, const ProgramPointTag *tag = 0)
5275903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
5285903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
5295903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  const void *getData() const { return getData1(); }
5305903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
5315903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  static bool classof(const ProgramPoint* Location) {
5325903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    return Location->getKind() == EpsilonKind;
5335903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  }
5345903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks};
5355903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
536ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// ProgramPoints can be "tagged" as representing points specific to a given
537ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// analysis entity.  Tags are abstract annotations, with an associated
538ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// description and potentially other information.
539ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag {
540ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
541ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
542ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual ~ProgramPointTag();
543ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual StringRef getTagDescription() const = 0;
544ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
545ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprotected:
5461ab69c513239596946286373e081b89fa3358612Ted Kremenek  /// Used to implement 'classof' in subclasses.
547ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *getTagKind() { return TagKind; }
548ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
549ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprivate:
550ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *TagKind;
551ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
552ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
553ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass SimpleProgramPointTag : public ProgramPointTag {
554ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  std::string desc;
555ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
556ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  SimpleProgramPointTag(StringRef description);
557ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  StringRef getTagDescription() const;
558ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
5591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
560eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek} // end namespace clang
5614c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
5624c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
5631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnamespace llvm { // Traits specialization for DenseMap
5641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
56583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenektemplate <> struct DenseMapInfo<clang::ProgramPoint> {
5664c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
567d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getEmptyKey() {
568d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
5691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
57025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
571d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
572d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
573d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getTombstoneKey() {
574d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
57525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
57625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
577d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
578d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5799c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic unsigned getHashValue(const clang::ProgramPoint &Loc) {
580d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return Loc.getHashValue();
581d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
582d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5839c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic bool isEqual(const clang::ProgramPoint &L,
5849c378f705405d37f49795d5e915989de774fe11fTed Kremenek                    const clang::ProgramPoint &R) {
585d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return L == R;
586d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
587d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5884c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek};
58906159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
59006159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnertemplate <>
59106159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnerstruct isPodLike<clang::ProgramPoint> { static const bool value = true; };
59206159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
5934c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek} // end namespace llvm
5944c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
595eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#endif
596