ProgramPoint.h revision 1d26f48dc2eea1c07431ca1519d7034a21b9bcff
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"
225226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek#include "llvm/ADT/FoldingSet.h"
236bad354120ce0d35901e86ca63e5534b7b9ed092Ted Kremenek#include "llvm/Support/Casting.h"
24ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "llvm/ADT/StringRef.h"
254c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek#include <cassert>
2659753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek#include <utility>
27ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include <string>
28eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
29eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremeneknamespace clang {
3025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
311d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekclass AnalysisDeclContext;
32102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass FunctionDecl;
33ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass LocationContext;
34ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag;
35ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
3683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass ProgramPoint {
37eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
38cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  enum Kind { BlockEdgeKind,
39cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockEntranceKind,
40cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              BlockExitKind,
41cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PreStmtKind,
42cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStmtKind,
43b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreLoadKind,
44cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLoadKind,
45b4b817d704287836b52b34369009e682f208aa2bTed Kremenek              PreStoreKind,
46cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostStoreKind,
47cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostPurgeDeadSymbolsKind,
488083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek              PostConditionKind,
49cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek              PostLValueKind,
509dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu              PostInitializerKind,
51102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor              CallEnterKind,
52102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor              CallExitKind,
53f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek              MinPostStmtKind = PostStmtKind,
544462ee2f0000e6cb966e3fff4516c84292f0cce8Ted Kremenek              MaxPostStmtKind = CallExitKind };
554c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
56d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprivate:
57d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek  std::pair<const void *, const void *> Data;
58d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek  Kind K;
5925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
6025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // The LocationContext could be NULL to allow ProgramPoint to be used in
6125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  // context insensitive analysis.
6225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  const LocationContext *L;
63ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const ProgramPointTag *Tag;
641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  ProgramPoint();
66ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
67d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
689c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ProgramPoint(const void *P, Kind k, const LocationContext *l,
69ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek               const ProgramPointTag *tag = 0)
70a5fdd9ce694b1c2dbfd225cb6f55ef743d1ab562Douglas Gregor    : Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {}
711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
729c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ProgramPoint(const void *P1, const void *P2, Kind k, const LocationContext *l,
73ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek               const ProgramPointTag *tag = 0)
7425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : Data(P1, P2), K(k), L(l), Tag(tag) {}
75f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek
76d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected:
779c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const void *getData1() const { return Data.first; }
789c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const void *getData2() const { return Data.second; }
791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic:
81af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// Create a new ProgramPoint object that is the same as the original
82af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  /// except for using the specified tag value.
8363d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  ProgramPoint withTag(const ProgramPointTag *tag) const {
84af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks    return ProgramPoint(Data.first, Data.second, K, L, tag);
85af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks  }
86af42712cd8f548f15c700d49a7038ddb846aafa8Anna Zaks
87d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek  Kind getKind() const { return K; }
88d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
89ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const ProgramPointTag *getTag() const { return Tag; }
9058465900ca10e53b8700a64e9265870de34e1acaTed Kremenek
91fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu  const LocationContext *getLocationContext() const { return L; }
9225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu
93e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek  // For use with DenseMap.  This hash is probably slow.
94d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  unsigned getHashValue() const {
95e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    llvm::FoldingSetNodeID ID;
96d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    Profile(ID);
97e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    return ID.ComputeHash();
98d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint*) { return true; }
101d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
102d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  bool operator==(const ProgramPoint & RHS) const {
10325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag;
104d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
105d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
1069c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool operator!=(const ProgramPoint &RHS) const {
10725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag;
108d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1105226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek  void Profile(llvm::FoldingSetNodeID& ID) const {
111d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    ID.AddInteger((unsigned) K);
112d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    ID.AddPointer(Data.first);
113d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek    ID.AddPointer(Data.second);
11425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    ID.AddPointer(L);
115e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek    ID.AddPointer(Tag);
1162680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenek  }
11763d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks
11863d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
11963d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const LocationContext *LC,
12063d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks                                      const ProgramPointTag *tag);
12163d3201619fdac284adfd3b9328562fa20a01c40Anna Zaks
122eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
1231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
12483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEntrance : public ProgramPoint {
125eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
1269c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEntrance(const CFGBlock *B, const LocationContext *L,
127ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                const ProgramPointTag *tag = 0)
1282f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    : ProgramPoint(B, BlockEntranceKind, L, tag) {
1292f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek    assert(B && "BlockEntrance requires non-null block");
1302f041d0b12aa87f3345e5fb2e38fefba30c5bff3Ted Kremenek  }
1311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1329c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
13303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
134bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  const CFGElement getFirstElement() const {
1379c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const CFGBlock *B = getBlock();
138852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    return B->empty() ? CFGElement() : B->front();
139852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek  }
140852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
14183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
14283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return Location->getKind() == BlockEntranceKind;
143bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
144eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
14583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
14683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockExit : public ProgramPoint {
147eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
1489c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockExit(const CFGBlock *B, const LocationContext *L)
14925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(B, BlockExitKind, L) {}
1501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1519c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getBlock() const {
15203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return reinterpret_cast<const CFGBlock*>(getData1());
153bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
15483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
1559c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const Stmt *getTerminator() const {
15683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return getBlock()->getTerminator();
157bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
15983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
16083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek    return Location->getKind() == BlockExitKind;
161bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
162bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek};
1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1645f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass StmtPoint : public ProgramPoint {
1655f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekpublic:
1661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
167ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag)
16825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : ProgramPoint(S, p2, k, L, tag) {}
1691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1705f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
1711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1725f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  template <typename T>
1735f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
1741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1755f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  static bool classof(const ProgramPoint* Location) {
1765f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    unsigned k = Location->getKind();
1775f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek    return k >= PreStmtKind && k <= MaxPostStmtKind;
1785f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek  }
1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
1801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
181eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek
1825f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PreStmt : public StmtPoint {
183cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenekpublic:
184ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
18525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu          const Stmt *SubStmt = 0)
18625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
187cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
189cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
190cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  static bool classof(const ProgramPoint* Location) {
191cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek    return Location->getKind() == PreStmtKind;
192cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek  }
193cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek};
194cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek
1955f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PostStmt : public StmtPoint {
1961b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekprotected:
1979c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
198ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag =0)
19925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, data, k, L, tag) {}
2001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
201eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic:
2029c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, Kind k,
203ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const LocationContext *L, const ProgramPointTag *tag = 0)
2044bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek    : StmtPoint(S, NULL, k, L, tag) {}
2054bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek
2069c378f705405d37f49795d5e915989de774fe11fTed Kremenek  explicit PostStmt(const Stmt *S, const LocationContext *L,
207ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                    const ProgramPointTag *tag = 0)
20825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
20983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
21083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2111b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    unsigned k = Location->getKind();
212f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
2131b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  }
2141b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek};
2158c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek
2168083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek// PostCondition represents the post program point of a branch condition.
2178083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekclass PostCondition : public PostStmt {
2188083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekpublic:
2199c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostCondition(const Stmt *S, const LocationContext *L,
220ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                const ProgramPointTag *tag = 0)
2218083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    : PostStmt(S, PostConditionKind, L, tag) {}
2228083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
2238083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  static bool classof(const ProgramPoint* Location) {
2248083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek    return Location->getKind() == PostConditionKind;
2258083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek  }
2268083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek};
2278083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek
228b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass LocationCheck : public StmtPoint {
229b4b817d704287836b52b34369009e682f208aa2bTed Kremenekprotected:
230b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  LocationCheck(const Stmt *S, const LocationContext *L,
231ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                ProgramPoint::Kind K, const ProgramPointTag *tag)
232b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : StmtPoint(S, NULL, K, L, tag) {}
233b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
234b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
235b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    unsigned k = location->getKind();
236d651141308a777d60ff98309d21e045bb936f8b7Ted Kremenek    return k == PreLoadKind || k == PreStoreKind;
2378c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2388c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
239b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
240b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreLoad : public LocationCheck {
2418c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
242ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreLoad(const Stmt *S, const LocationContext *L,
243ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek          const ProgramPointTag *tag = 0)
244b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    : LocationCheck(S, L, PreLoadKind, tag) {}
245b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
246b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
247b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreLoadKind;
2488c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2498c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
251b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreStore : public LocationCheck {
2528c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic:
253ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  PreStore(const Stmt *S, const LocationContext *L,
254ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
255b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  : LocationCheck(S, L, PreStoreKind, tag) {}
256b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
257b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  static bool classof(const ProgramPoint *location) {
258b4b817d704287836b52b34369009e682f208aa2bTed Kremenek    return location->getKind() == PreStoreKind;
2598c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek  }
2608c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek};
2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2621b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekclass PostLoad : public PostStmt {
2631b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekpublic:
2649c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLoad(const Stmt *S, const LocationContext *L,
265ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek           const ProgramPointTag *tag = 0)
26625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLoadKind, L, tag) {}
2671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2681b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek  static bool classof(const ProgramPoint* Location) {
2691b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek    return Location->getKind() == PostLoadKind;
270bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek  }
271eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek};
2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
27382bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekclass PostStore : public PostStmt {
27482bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekpublic:
2759c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostStore(const Stmt *S, const LocationContext *L,
276ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek            const ProgramPointTag *tag = 0)
27725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostStoreKind, L, tag) {}
2781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
27982bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  static bool classof(const ProgramPoint* Location) {
28082bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek    return Location->getKind() == PostStoreKind;
28182bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek  }
28282bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek};
2837090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek
2847090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekclass PostLValue : public PostStmt {
2857090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekpublic:
2869c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostLValue(const Stmt *S, const LocationContext *L,
287ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek             const ProgramPointTag *tag = 0)
28825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostLValueKind, L, tag) {}
2891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2907090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  static bool classof(const ProgramPoint* Location) {
2917090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek    return Location->getKind() == PostLValueKind;
2927090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek  }
2931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump};
2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
295331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekclass PostPurgeDeadSymbols : public PostStmt {
296331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekpublic:
2979c378f705405d37f49795d5e915989de774fe11fTed Kremenek  PostPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
298ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                       const ProgramPointTag *tag = 0)
29925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu    : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
3001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
301331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  static bool classof(const ProgramPoint* Location) {
302331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek    return Location->getKind() == PostPurgeDeadSymbolsKind;
303331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek  }
304331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek};
3051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
30683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEdge : public ProgramPoint {
307b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenekpublic:
3089c378f705405d37f49795d5e915989de774fe11fTed Kremenek  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
309e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
310e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B1 && "BlockEdge: source block must be non-null");
311e4c6675cccbaac991843def43072687bca50d989Ted Kremenek    assert(B2 && "BlockEdge: destination block must be non-null");
312e4c6675cccbaac991843def43072687bca50d989Ted Kremenek  }
3131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3149c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getSrc() const {
31503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData1());
316d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
3171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3189c378f705405d37f49795d5e915989de774fe11fTed Kremenek  const CFGBlock *getDst() const {
31903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    return static_cast<const CFGBlock*>(getData2());
320d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  }
3211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32283c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek  static bool classof(const ProgramPoint* Location) {
323d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek    return Location->getKind() == BlockEdgeKind;
324b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek  }
325b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek};
32683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek
3279dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xuclass PostInitializer : public ProgramPoint {
3289dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xupublic:
329cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt  PostInitializer(const CXXCtorInitializer *I,
3309dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu                  const LocationContext *L)
3319dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    : ProgramPoint(I, PostInitializerKind, L) {}
3329dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
3339dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  static bool classof(const ProgramPoint *Location) {
3349dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu    return Location->getKind() == PostInitializerKind;
3359dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu  }
3369dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu};
3379dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
338102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass CallEnter : public StmtPoint {
339102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
34019b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
34119b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu            const LocationContext *callerCtx)
34219b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
343102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
344102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  const Stmt *getCallExpr() const {
345102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return static_cast<const Stmt *>(getData1());
346102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
347102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
34819b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu  const StackFrameContext *getCalleeContext() const {
34919b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu    return static_cast<const StackFrameContext *>(getData2());
350102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
351102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
352102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
353102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return Location->getKind() == CallEnterKind;
354102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
355102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
356102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
357102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass CallExit : public StmtPoint {
358102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic:
359102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  // CallExit uses the callee's location context.
360102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  CallExit(const Stmt *S, const LocationContext *L)
361102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    : StmtPoint(S, 0, CallExitKind, L, 0) {}
362102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
363102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  static bool classof(const ProgramPoint *Location) {
364102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor    return Location->getKind() == CallExitKind;
365102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor  }
366102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor};
367102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor
368ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// ProgramPoints can be "tagged" as representing points specific to a given
369ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// analysis entity.  Tags are abstract annotations, with an associated
370ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// description and potentially other information.
371ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag {
372ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
373ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
374ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual ~ProgramPointTag();
375ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  virtual StringRef getTagDescription() const = 0;
376ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
377ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprotected:
3781ab69c513239596946286373e081b89fa3358612Ted Kremenek  /// Used to implement 'classof' in subclasses.
379ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *getTagKind() { return TagKind; }
380ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
381ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprivate:
382ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  const void *TagKind;
383ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
384ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek
385ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass SimpleProgramPointTag : public ProgramPointTag {
386ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  std::string desc;
387ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic:
388ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  SimpleProgramPointTag(StringRef description);
389ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek  StringRef getTagDescription() const;
390ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek};
3911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
392eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek} // end namespace clang
3934c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
3944c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
3951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnamespace llvm { // Traits specialization for DenseMap
3961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
39783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenektemplate <> struct DenseMapInfo<clang::ProgramPoint> {
3984c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
399d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getEmptyKey() {
400d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
40225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
403d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
404d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
405d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getTombstoneKey() {
406d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  uintptr_t x =
40725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
40825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
409d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
410d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
4119c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic unsigned getHashValue(const clang::ProgramPoint &Loc) {
412d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return Loc.getHashValue();
413d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
414d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
4159c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic bool isEqual(const clang::ProgramPoint &L,
4169c378f705405d37f49795d5e915989de774fe11fTed Kremenek                    const clang::ProgramPoint &R) {
417d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek  return L == R;
418d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek}
419d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek
4204c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek};
42106159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
42206159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnertemplate <>
42306159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnerstruct isPodLike<clang::ProgramPoint> { static const bool value = true; };
42406159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner
4254c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek} // end namespace llvm
4264c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek
427eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#endif
428