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