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