ProgramPoint.h revision f4be8ee748831bc23e35b542e6c1bb6d1eb49baa
1//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the interface ProgramPoint, which identifies a
11//  distinct location in a function.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
16#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
17
18#include "clang/AST/CFG.h"
19#include "llvm/Support/DataTypes.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/FoldingSet.h"
22#include <cassert>
23
24namespace clang {
25
26class ProgramPoint {
27public:
28  enum Kind { BlockEdgeKind = 0x0,
29              BlockEntranceKind = 0x1,
30              BlockExitKind = 0x2,
31              // Keep the following four together and in this order.
32              PostStmtKind = 0x3,
33              PostLocationChecksSucceedKind = 0x4,
34              PostOutOfBoundsCheckFailedKind = 0x5,
35              PostNullCheckFailedKind = 0x6,
36              PostUndefLocationCheckFailedKind = 0x7,
37              PostLoadKind = 0x8,
38              PostStoreKind = 0x9,
39              PostPurgeDeadSymbolsKind = 0x10,
40              PostStmtCustomKind = 0x11,
41              MinPostStmtKind = PostStmtKind,
42              MaxPostStmtKind = PostStmtCustomKind };
43
44private:
45  enum { TwoPointers = 0x1, Custom = 0x2, Mask = 0x3 };
46
47  std::pair<uintptr_t,uintptr_t> Data;
48
49protected:
50  ProgramPoint(const void* P, Kind k)
51    : Data(reinterpret_cast<uintptr_t>(P),
52           (uintptr_t) k) {}
53
54  ProgramPoint(const void* P1, const void* P2)
55    : Data(reinterpret_cast<uintptr_t>(P1) | TwoPointers,
56           reinterpret_cast<uintptr_t>(P2)) {}
57
58  ProgramPoint(const void* P1, const void* P2, bool)
59    : Data(reinterpret_cast<uintptr_t>(P1) | Custom,
60           reinterpret_cast<uintptr_t>(P2)) {}
61
62protected:
63  void* getData1NoMask() const {
64    Kind k = getKind(); k = k;
65    assert(k == BlockEntranceKind || k == BlockExitKind);
66    return reinterpret_cast<void*>(Data.first);
67  }
68
69  void* getData1() const {
70    Kind k = getKind(); k = k;
71    assert(k == BlockEdgeKind || (k >= MinPostStmtKind && k < MaxPostStmtKind));
72    return reinterpret_cast<void*>(Data.first & ~Mask);
73  }
74
75  void* getData2() const {
76    Kind k = getKind(); k = k;
77    assert(k == BlockEdgeKind || k == PostStmtCustomKind);
78    return reinterpret_cast<void*>(Data.second);
79  }
80
81public:
82  Kind getKind() const {
83    switch (Data.first & Mask) {
84      case TwoPointers: return BlockEdgeKind;
85      case Custom: return PostStmtCustomKind;
86      default: return (Kind) Data.second;
87    }
88  }
89
90  // For use with DenseMap.
91  unsigned getHashValue() const {
92    std::pair<void*,void*> P(reinterpret_cast<void*>(Data.first),
93                             reinterpret_cast<void*>(Data.second));
94    return llvm::DenseMapInfo<std::pair<void*,void*> >::getHashValue(P);
95  }
96
97  static bool classof(const ProgramPoint*) { return true; }
98
99  bool operator==(const ProgramPoint & RHS) const {
100    return Data == RHS.Data;
101  }
102
103  bool operator!=(const ProgramPoint& RHS) const {
104    return Data != RHS.Data;
105  }
106
107  bool operator<(const ProgramPoint& RHS) const {
108    return Data < RHS.Data;
109  }
110
111  void Profile(llvm::FoldingSetNodeID& ID) const {
112    ID.AddPointer(reinterpret_cast<void*>(Data.first));
113    ID.AddPointer(reinterpret_cast<void*>(Data.second));
114  }
115};
116
117class BlockEntrance : public ProgramPoint {
118public:
119  BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {}
120
121  CFGBlock* getBlock() const {
122    return reinterpret_cast<CFGBlock*>(getData1NoMask());
123  }
124
125  Stmt* getFirstStmt() const {
126    CFGBlock* B = getBlock();
127    return B->empty() ? NULL : B->front();
128  }
129
130  static bool classof(const ProgramPoint* Location) {
131    return Location->getKind() == BlockEntranceKind;
132  }
133};
134
135class BlockExit : public ProgramPoint {
136public:
137  BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {}
138
139  CFGBlock* getBlock() const {
140    return reinterpret_cast<CFGBlock*>(getData1NoMask());
141  }
142
143  Stmt* getLastStmt() const {
144    CFGBlock* B = getBlock();
145    return B->empty() ? NULL : B->back();
146  }
147
148  Stmt* getTerminator() const {
149    return getBlock()->getTerminator();
150  }
151
152  static bool classof(const ProgramPoint* Location) {
153    return Location->getKind() == BlockExitKind;
154  }
155};
156
157
158class PostStmt : public ProgramPoint {
159protected:
160  PostStmt(const Stmt* S, Kind k) : ProgramPoint(S, k) {}
161  PostStmt(const Stmt* S, const void* data) : ProgramPoint(S, data, true) {}
162
163public:
164  PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {}
165
166  Stmt* getStmt() const { return (Stmt*) getData1(); }
167
168  static bool classof(const ProgramPoint* Location) {
169    unsigned k = Location->getKind();
170    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
171  }
172};
173
174class PostLocationChecksSucceed : public PostStmt {
175public:
176  PostLocationChecksSucceed(const Stmt* S)
177    : PostStmt(S, PostLocationChecksSucceedKind) {}
178
179  static bool classof(const ProgramPoint* Location) {
180    return Location->getKind() == PostLocationChecksSucceedKind;
181  }
182};
183
184class PostStmtCustom : public PostStmt {
185  PostStmtCustom(const Stmt* S, const void* Data)
186    : PostStmt(S, Data) {
187    assert(getKind() == PostStmtCustomKind);
188  }
189
190  void* getCustomData() const { return getData2(); }
191
192  static bool classof(const ProgramPoint* Location) {
193    return Location->getKind() == PostStmtCustomKind;
194  }
195};
196
197class PostOutOfBoundsCheckFailed : public PostStmt {
198public:
199  PostOutOfBoundsCheckFailed(const Stmt* S)
200  : PostStmt(S, PostOutOfBoundsCheckFailedKind) {}
201
202  static bool classof(const ProgramPoint* Location) {
203    return Location->getKind() == PostOutOfBoundsCheckFailedKind;
204  }
205};
206
207class PostUndefLocationCheckFailed : public PostStmt {
208public:
209  PostUndefLocationCheckFailed(const Stmt* S)
210  : PostStmt(S, PostUndefLocationCheckFailedKind) {}
211
212  static bool classof(const ProgramPoint* Location) {
213    return Location->getKind() == PostUndefLocationCheckFailedKind;
214  }
215};
216
217class PostNullCheckFailed : public PostStmt {
218public:
219  PostNullCheckFailed(const Stmt* S)
220  : PostStmt(S, PostNullCheckFailedKind) {}
221
222  static bool classof(const ProgramPoint* Location) {
223    return Location->getKind() == PostNullCheckFailedKind;
224  }
225};
226
227class PostLoad : public PostStmt {
228public:
229  PostLoad(const Stmt* S) : PostStmt(S, PostLoadKind) {}
230
231  static bool classof(const ProgramPoint* Location) {
232    return Location->getKind() == PostLoadKind;
233  }
234};
235
236class PostStore : public PostStmt {
237public:
238  PostStore(const Stmt* S) : PostStmt(S, PostStoreKind) {}
239
240  static bool classof(const ProgramPoint* Location) {
241    return Location->getKind() == PostStoreKind;
242  }
243};
244
245class PostPurgeDeadSymbols : public PostStmt {
246public:
247  PostPurgeDeadSymbols(const Stmt* S) : PostStmt(S, PostPurgeDeadSymbolsKind) {}
248
249  static bool classof(const ProgramPoint* Location) {
250    return Location->getKind() == PostPurgeDeadSymbolsKind;
251  }
252};
253
254class BlockEdge : public ProgramPoint {
255public:
256  BlockEdge(const CFGBlock* B1, const CFGBlock* B2)
257    : ProgramPoint(B1, B2) {}
258
259  CFGBlock* getSrc() const {
260    return static_cast<CFGBlock*>(getData1());
261  }
262
263  CFGBlock* getDst() const {
264    return static_cast<CFGBlock*>(getData2());
265  }
266
267  static bool classof(const ProgramPoint* Location) {
268    return Location->getKind() == BlockEdgeKind;
269  }
270};
271
272
273} // end namespace clang
274
275
276namespace llvm { // Traits specialization for DenseMap
277
278template <> struct DenseMapInfo<clang::ProgramPoint> {
279
280static inline clang::ProgramPoint getEmptyKey() {
281  uintptr_t x =
282   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
283  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
284}
285
286static inline clang::ProgramPoint getTombstoneKey() {
287  uintptr_t x =
288   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
289  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
290}
291
292static unsigned getHashValue(const clang::ProgramPoint& Loc) {
293  return Loc.getHashValue();
294}
295
296static bool isEqual(const clang::ProgramPoint& L,
297                    const clang::ProgramPoint& R) {
298  return L == R;
299}
300
301static bool isPod() {
302  return true;
303}
304};
305} // end namespace llvm
306
307#endif
308