ProgramPoint.h revision 51a31ca9a9903ecba1b25bc0989f62e1e2bebb4c
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,
529dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu              PostInitializerKind,
53102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor              CallEnterKind,
540b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitBeginKind,
550b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              CallExitEndKind,
56f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek              MinPostStmtKind = PostStmtKind,
570b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks              MaxPostStmtKind = CallExitEndKind,
585903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks              EpsilonKind};
594c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
60d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprivate:
61c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const void *, 2, unsigned> Data1;
62c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const void *, 2, unsigned> Data2;
6325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
6425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // The LocationContext could be NULL to allow ProgramPoint to be used in
6525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // context insensitive analysis.
66c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
67c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek
68ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const ProgramPointTag *Tag;
691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
70ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  ProgramPoint();
71ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
72d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
73f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  ProgramPoint(const void *P,
74f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               Kind k,
75f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const LocationContext *l,
76ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek               const ProgramPointTag *tag = 0)
77c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    : Data1(P, ((unsigned) k) & 0x3),
78c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek      Data2(0, (((unsigned) k) >> 2) & 0x3),
79c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek      L(l, (((unsigned) k) >> 4) & 0x3),
80f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek      Tag(tag) {
81f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getKind() == k);
82f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getLocationContext() == l);
83f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek        assert(getData1() == P);
84f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek      }
85f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek
86f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  ProgramPoint(const void *P1,
87f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const void *P2,
88f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               Kind k,
89f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek               const LocationContext *l,
90ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek               const ProgramPointTag *tag = 0)
91c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    : Data1(P1, ((unsigned) k) & 0x3),
92c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek      Data2(P2, (((unsigned) k) >> 2) & 0x3),
93c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek      L(l, (((unsigned) k) >> 4) & 0x3),
94f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek      Tag(tag) {}
95f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek
96d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
97c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  const void *getData1() const { return Data1.getPointer(); }
98c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  const void *getData2() const { return Data2.getPointer(); }
99c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek  void setData2(const void *d) { Data2.setPointer(d); }
1001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
102af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// Create a new ProgramPoint object that is the same as the original
103af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// except for using the specified tag value.
10463d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  ProgramPoint withTag(const ProgramPointTag *tag) const {
105c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return ProgramPoint(getData1(), getData2(), getKind(),
106f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek                        getLocationContext(), tag);
107af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  }
108af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks
109f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  Kind getKind() const {
110c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    unsigned x = L.getInt();
111c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
112c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x |= Data2.getInt();
113c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x <<= 2;
114c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    x |= Data1.getInt();
115c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return (Kind) x;
116f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
117d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1180b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// \brief Is this a program point corresponding to purge/removal of dead
1190b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  /// symbols and bindings.
1200b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  bool isPurgeKind() {
1210b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    Kind K = getKind();
1220b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return (K == PostStmtPurgeDeadSymbolsKind ||
1230b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks            K == PreStmtPurgeDeadSymbolsKind);
1240b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
1250b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
126ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const ProgramPointTag *getTag() const { return Tag; }
12758465900ca10e53b8700a64e9265870de34e1acaTed Kremenek
128f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  const LocationContext *getLocationContext() const {
129c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return L.getPointer();
130f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek  }
13125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
132e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek  // For use with DenseMap.  This hash is probably slow.
133d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  unsigned getHashValue() const {
134e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    llvm::FoldingSetNodeID ID;
135d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    Profile(ID);
136e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    return ID.ComputeHash();
137d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint*) { return true; }
140d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
141d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  bool operator==(const ProgramPoint & RHS) const {
1426403683411dac55afbe3435ceb19033e27cd9f96Ted Kremenek    return Data1 == RHS.Data1 &&
143c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 == RHS.Data2 &&
144c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L == RHS.L &&
145c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag == RHS.Tag;
146d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
147d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1489c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool operator!=(const ProgramPoint &RHS) const {
149c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    return Data1 != RHS.Data1 ||
150c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Data2 != RHS.Data2 ||
151c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           L != RHS.L ||
152c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek           Tag != RHS.Tag;
153d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1555226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek  void Profile(llvm::FoldingSetNodeID& ID) const {
156f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddInteger((unsigned) getKind());
157f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getData1());
158c8443e592dbab65cd06ddea9fad6c6f049a08942Ted Kremenek    ID.AddPointer(getData2());
159f30c0a97d9addc72a4928b8bb2039b2b464e1f94Ted Kremenek    ID.AddPointer(getLocationContext());
160e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    ID.AddPointer(Tag);
1612680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenek  }
16263d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks
16363d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
16463d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const LocationContext *LC,
16563d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const ProgramPointTag *tag);
166eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
1671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
16883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEntrance : public ProgramPoint {
169eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
1709c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEntrance(const CFGBlock *B, const LocationContext *L,
171ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                const ProgramPointTag *tag = 0)
1722f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    : ProgramPoint(B, BlockEntranceKind, L, tag) {
1732f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    assert(B && "BlockEntrance requires non-null block");
1742f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek  }
1751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1769c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
17703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
178bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  const CFGElement getFirstElement() const {
1819c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const CFGBlock *B = getBlock();
182852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    return B->empty() ? CFGElement() : B->front();
183852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek  }
184852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
18583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
18683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return Location->getKind() == BlockEntranceKind;
187bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
188eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
18983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
19083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockExit : public ProgramPoint {
191eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
1929c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockExit(const CFGBlock *B, const LocationContext *L)
19325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(B, BlockExitKind, L) {}
1941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1959c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
19603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
197bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
19883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
1999c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Stmt *getTerminator() const {
20083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return getBlock()->getTerminator();
201bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
20483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return Location->getKind() == BlockExitKind;
205bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
206bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek};
2071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2085f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass StmtPoint : public ProgramPoint {
2095f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekpublic:
2101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
211ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag)
21225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(S, p2, k, L, tag) {}
2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2145f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2165f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  template <typename T>
2175f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2195f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2205f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    unsigned k = Location->getKind();
2215f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    return k >= PreStmtKind && k <= MaxPostStmtKind;
2225f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  }
2231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
2241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
225eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
2265f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PreStmt : public StmtPoint {
227cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenekpublic:
228ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
22925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu          const Stmt *SubStmt = 0)
23025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
231cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
233cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
234cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  static bool classof(const ProgramPoint* Location) {
235cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek    return Location->getKind() == PreStmtKind;
236cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  }
237cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek};
238cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
2395f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PostStmt : public StmtPoint {
2401b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekprotected:
2419c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
2423d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks           const ProgramPointTag *tag = 0)
24325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, data, k, L, tag) {}
2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
245eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2469c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, Kind k,
247ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const LocationContext *L, const ProgramPointTag *tag = 0)
2484bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek    : StmtPoint(S, NULL, k, L, tag) {}
2494bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek
2509c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, const LocationContext *L,
251ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const ProgramPointTag *tag = 0)
25225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
25383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
25483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2551b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    unsigned k = Location->getKind();
256f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
2571b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  }
2581b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek};
2598c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek
2608083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek// PostCondition represents the post program point of a branch condition.
2618083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekclass PostCondition : public PostStmt {
2628083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekpublic:
2639c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostCondition(const Stmt *S, const LocationContext *L,
264ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                const ProgramPointTag *tag = 0)
2658083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    : PostStmt(S, PostConditionKind, L, tag) {}
2668083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
2678083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2688083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    return Location->getKind() == PostConditionKind;
2698083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  }
2708083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek};
2718083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
272b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass LocationCheck : public StmtPoint {
273b4b817d704287836b52b34369009e682f208aa2bTed Kremenekprotected:
274b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  LocationCheck(const Stmt *S, const LocationContext *L,
275ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                ProgramPoint::Kind K, const ProgramPointTag *tag)
276b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : StmtPoint(S, NULL, K, L, tag) {}
277b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
278b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
279b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    unsigned k = location->getKind();
280d651141308a777d60ff98309d21e045bb936f8b7Ted Kremenek    return k == PreLoadKind || k == PreStoreKind;
2818c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2828c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
283b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
284b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreLoad : public LocationCheck {
2858c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
286ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreLoad(const Stmt *S, const LocationContext *L,
287ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek          const ProgramPointTag *tag = 0)
288b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : LocationCheck(S, L, PreLoadKind, tag) {}
289b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
290b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
291b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreLoadKind;
2928c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2938c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
295b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreStore : public LocationCheck {
2968c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
297ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStore(const Stmt *S, const LocationContext *L,
298ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
299b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  : LocationCheck(S, L, PreStoreKind, tag) {}
300b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
301b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
302b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreStoreKind;
3038c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
3048c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
3051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3061b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekclass PostLoad : public PostStmt {
3071b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekpublic:
3089c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLoad(const Stmt *S, const LocationContext *L,
309ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
31025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLoadKind, L, tag) {}
3111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3121b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  static bool classof(const ProgramPoint* Location) {
3131b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    return Location->getKind() == PostLoadKind;
314bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
315eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3173d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks/// \class Represents a program point after a store evaluation.
31882bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekclass PostStore : public PostStmt {
31982bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekpublic:
3203d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// Construct the post store point.
3213d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \param Loc can be used to store the information about the location
3223d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// used in the form it was uttered in the code.
3233d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
324ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag = 0)
3253d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    : PostStmt(S, PostStoreKind, L, tag) {
3263d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    assert(getData2() == 0);
3273d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    setData2(Loc);
3283d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33082bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  static bool classof(const ProgramPoint* Location) {
33182bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek    return Location->getKind() == PostStoreKind;
33282bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  }
3333d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
3343d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// \brief Returns the information about the location used in the store,
3353d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  /// how it was uttered in the code.
3363d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  const void *getLocationValue() const {
3373d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks    return getData2();
3383d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks  }
3393d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks
34082bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek};
3417090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek
3427090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekclass PostLValue : public PostStmt {
3437090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekpublic:
3449c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLValue(const Stmt *S, const LocationContext *L,
345ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek             const ProgramPointTag *tag = 0)
34625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLValueKind, L, tag) {}
3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3487090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  static bool classof(const ProgramPoint* Location) {
3497090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek    return Location->getKind() == PostLValueKind;
3507090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  }
3511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3530b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \class Represents a point after we ran remove dead bindings BEFORE
3540b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the given statement.
35551a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PreStmtPurgeDeadSymbols : public StmtPoint {
356331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekpublic:
3570b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
358ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                       const ProgramPointTag *tag = 0)
35951a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks    : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { }
3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
361331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  static bool classof(const ProgramPoint* Location) {
3620b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == PreStmtPurgeDeadSymbolsKind;
3630b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
3640b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
3650b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
3660b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \class Represents a point after we ran remove dead bindings AFTER
3670b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// processing the  given statement.
36851a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaksclass PostStmtPurgeDeadSymbols : public StmtPoint {
3690b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
3700b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
3710b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                       const ProgramPointTag *tag = 0)
37251a31ca9a9903ecba1b25bc0989f62e1e2bebb4cAnna Zaks    : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { }
3730b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
3740b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  static bool classof(const ProgramPoint* Location) {
3750b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == PostStmtPurgeDeadSymbolsKind;
376331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  }
377331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek};
3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
37983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEdge : public ProgramPoint {
380b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenekpublic:
3819c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
382e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
383e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B1 && "BlockEdge: source block must be non-null");
384e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B2 && "BlockEdge: destination block must be non-null");
385e4c6675cccbaac991843def43072687bca50d989Ted Kremenek  }
3861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3879c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getSrc() const {
38803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData1());
389d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3919c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getDst() const {
39203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData2());
393d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
39583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
396d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek    return Location->getKind() == BlockEdgeKind;
397b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek  }
398b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek};
39983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
4009dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xuclass PostInitializer : public ProgramPoint {
4019dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xupublic:
402cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt  PostInitializer(const CXXCtorInitializer *I,
4039dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu                  const LocationContext *L)
4049dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    : ProgramPoint(I, PostInitializerKind, L) {}
4059dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
4069dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  static bool classof(const ProgramPoint *Location) {
4079dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    return Location->getKind() == PostInitializerKind;
4089dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  }
4099dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu};
4109dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
4110b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \class Represents a point when we begin processing an inlined call.
412102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass CallEnter : public StmtPoint {
413102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
41419b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
41519b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu            const LocationContext *callerCtx)
41619b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
417102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
418102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  const Stmt *getCallExpr() const {
419102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return static_cast<const Stmt *>(getData1());
420102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
421102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
42219b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  const StackFrameContext *getCalleeContext() const {
42319b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    return static_cast<const StackFrameContext *>(getData2());
424102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
425102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
426102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
427102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return Location->getKind() == CallEnterKind;
428102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
429102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
430102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
4310b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \class Represents a point when we start the call exit sequence (for
4320b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// inlined call).
4330b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks///
4340b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// The call exit is simulated with a sequence of nodes, which occur between
4350b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// CallExitBegin and CallExitEnd. The following operations occur between the
4360b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// two program points:
4370b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitBegin
4380b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Bind the return value
4390b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
4400b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// - CallExitEnd
4410b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaksclass CallExitBegin : public StmtPoint {
4420b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zakspublic:
4430b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitBegin uses the callee's location context.
4440b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  CallExitBegin(const Stmt *S, const LocationContext *L)
4450b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    : StmtPoint(S, 0, CallExitBeginKind, L, 0) {}
4460b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
4470b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  static bool classof(const ProgramPoint *Location) {
4480b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == CallExitBeginKind;
4490b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  }
4500b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks};
4510b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks
4520b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \class Represents a point when we finish the call exit sequence (for
4530b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// inlined call).
4540b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks/// \sa CallExitBegin
4550b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaksclass CallExitEnd : public StmtPoint {
456102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
4570b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  // CallExitEnd uses the caller's location context.
4580b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  CallExitEnd(const Stmt *S, const LocationContext *L)
4590b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    : StmtPoint(S, 0, CallExitEndKind, L, 0) {}
460102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
461102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
4620b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    return Location->getKind() == CallExitEndKind;
463102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
464102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
465102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
4665903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// This is a meta program point, which should be skipped by all the diagnostic
4675903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks/// reasoning etc.
4685903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaksclass EpsilonPoint : public ProgramPoint {
4695903a373db3d27794c90b25687e0dd6adb0e497dAnna Zakspublic:
4705903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  EpsilonPoint(const LocationContext *L, const void *Data1,
4715903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks               const void *Data2 = 0, const ProgramPointTag *tag = 0)
4725903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
4735903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
4745903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  const void *getData() const { return getData1(); }
4755903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
4765903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  static bool classof(const ProgramPoint* Location) {
4775903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks    return Location->getKind() == EpsilonKind;
4785903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks  }
4795903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks};
4805903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks
481ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// ProgramPoints can be "tagged" as representing points specific to a given
482ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// analysis entity.  Tags are abstract annotations, with an associated
483ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// description and potentially other information.
484ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag {
485ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
486ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
487ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual ~ProgramPointTag();
488ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual StringRef getTagDescription() const = 0;
489ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
490ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprotected:
4911ab69c513239596946286373e081b89fa3358612Ted Kremenek  /// Used to implement 'classof' in subclasses.
492ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *getTagKind() { return TagKind; }
493ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
494ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprivate:
495ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *TagKind;
496ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
497ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
498ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass SimpleProgramPointTag : public ProgramPointTag {
499ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  std::string desc;
500ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
501ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  SimpleProgramPointTag(StringRef description);
502ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  StringRef getTagDescription() const;
503ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
5041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
505eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek} // end namespace clang
5064c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
5074c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
5081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnamespace llvm { // Traits specialization for DenseMap
5091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
51083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenektemplate <> struct DenseMapInfo<clang::ProgramPoint> {
5114c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
512d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getEmptyKey() {
513d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
5141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
51525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
516d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
517d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
518d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getTombstoneKey() {
519d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
52025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
52125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
522d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
523d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5249c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic unsigned getHashValue(const clang::ProgramPoint &Loc) {
525d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return Loc.getHashValue();
526d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
527d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5289c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic bool isEqual(const clang::ProgramPoint &L,
5299c378f705405d37f49795d5e915989de774fe11fTed Kremenek                    const clang::ProgramPoint &R) {
530d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return L == R;
531d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
532d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
5334c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek};
53406159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
53506159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnertemplate <>
53606159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnerstruct isPodLike<clang::ProgramPoint> { static const bool value = true; };
53706159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
5384c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek} // end namespace llvm
5394c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
540eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#endif
541