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