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