ProgramPoint.h revision 8c354758c2d39db87c77c723d81e34b4d967f762
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=0, BlockEntranceKind, BlockExitKind,
29              // Keep the following four together and in this order.
30              PostStmtKind,
31              PostLocationChecksSucceedKind,
32              PostOutOfBoundsCheckFailedKind,
33              PostNullCheckFailedKind,
34              PostUndefLocationCheckFailedKind,
35              PostLoadKind, PostStoreKind,
36              PostPurgeDeadSymbolsKind };
37
38private:
39  std::pair<uintptr_t,uintptr_t> Data;
40
41protected:
42  ProgramPoint(const void* P, Kind k)
43    : Data(reinterpret_cast<uintptr_t>(P), (uintptr_t) k) {}
44
45  ProgramPoint(const void* P1, const void* P2)
46    : Data(reinterpret_cast<uintptr_t>(P1) | 0x1,
47           reinterpret_cast<uintptr_t>(P2)) {}
48
49protected:
50  void* getData1NoMask() const {
51    assert (getKind() != BlockEdgeKind);
52    return reinterpret_cast<void*>(Data.first);
53  }
54
55  void* getData1() const {
56    assert (getKind() == BlockEdgeKind);
57    return reinterpret_cast<void*>(Data.first & ~0x1);
58  }
59
60  void* getData2() const {
61    assert (getKind() == BlockEdgeKind);
62    return reinterpret_cast<void*>(Data.second);
63  }
64
65public:
66
67  uintptr_t getKind() const {
68    return Data.first & 0x1 ? (uintptr_t) BlockEdgeKind : Data.second;
69  }
70
71  // For use with DenseMap.
72  unsigned getHashValue() const {
73    std::pair<void*,void*> P(reinterpret_cast<void*>(Data.first),
74                             reinterpret_cast<void*>(Data.second));
75    return llvm::DenseMapInfo<std::pair<void*,void*> >::getHashValue(P);
76  }
77
78  static bool classof(const ProgramPoint*) { return true; }
79
80  bool operator==(const ProgramPoint & RHS) const {
81    return Data == RHS.Data;
82  }
83
84  bool operator!=(const ProgramPoint& RHS) const {
85    return Data != RHS.Data;
86  }
87
88  bool operator<(const ProgramPoint& RHS) const {
89    return Data < RHS.Data;
90  }
91
92  void Profile(llvm::FoldingSetNodeID& ID) const {
93    ID.AddPointer(reinterpret_cast<void*>(Data.first));
94    ID.AddPointer(reinterpret_cast<void*>(Data.second));
95  }
96};
97
98class BlockEntrance : public ProgramPoint {
99public:
100  BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {}
101
102  CFGBlock* getBlock() const {
103    return reinterpret_cast<CFGBlock*>(getData1NoMask());
104  }
105
106  Stmt* getFirstStmt() const {
107    CFGBlock* B = getBlock();
108    return B->empty() ? NULL : B->front();
109  }
110
111  static bool classof(const ProgramPoint* Location) {
112    return Location->getKind() == BlockEntranceKind;
113  }
114};
115
116class BlockExit : public ProgramPoint {
117public:
118  BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {}
119
120  CFGBlock* getBlock() const {
121    return reinterpret_cast<CFGBlock*>(getData1NoMask());
122  }
123
124  Stmt* getLastStmt() const {
125    CFGBlock* B = getBlock();
126    return B->empty() ? NULL : B->back();
127  }
128
129  Stmt* getTerminator() const {
130    return getBlock()->getTerminator();
131  }
132
133  static bool classof(const ProgramPoint* Location) {
134    return Location->getKind() == BlockExitKind;
135  }
136};
137
138
139class PostStmt : public ProgramPoint {
140protected:
141  PostStmt(const Stmt* S, Kind k) : ProgramPoint(S, k) {}
142public:
143  PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {}
144
145  Stmt* getStmt() const { return (Stmt*) getData1NoMask(); }
146
147  static bool classof(const ProgramPoint* Location) {
148    unsigned k = Location->getKind();
149    return k >= PostStmtKind && k <= PostPurgeDeadSymbolsKind;
150  }
151};
152
153class PostLocationChecksSucceed : public PostStmt {
154public:
155  PostLocationChecksSucceed(const Stmt* S)
156    : PostStmt(S, PostLocationChecksSucceedKind) {}
157
158  static bool classof(const ProgramPoint* Location) {
159    return Location->getKind() == PostLocationChecksSucceedKind;
160  }
161};
162
163class PostOutOfBoundsCheckFailed : public PostStmt {
164public:
165  PostOutOfBoundsCheckFailed(const Stmt* S)
166  : PostStmt(S, PostOutOfBoundsCheckFailedKind) {}
167
168  static bool classof(const ProgramPoint* Location) {
169    return Location->getKind() == PostOutOfBoundsCheckFailedKind;
170  }
171};
172
173class PostUndefLocationCheckFailed : public PostStmt {
174public:
175  PostUndefLocationCheckFailed(const Stmt* S)
176  : PostStmt(S, PostUndefLocationCheckFailedKind) {}
177
178  static bool classof(const ProgramPoint* Location) {
179    return Location->getKind() == PostUndefLocationCheckFailedKind;
180  }
181};
182
183class PostNullCheckFailed : public PostStmt {
184public:
185  PostNullCheckFailed(const Stmt* S)
186  : PostStmt(S, PostNullCheckFailedKind) {}
187
188  static bool classof(const ProgramPoint* Location) {
189    return Location->getKind() == PostNullCheckFailedKind;
190  }
191};
192
193class PostLoad : public PostStmt {
194public:
195  PostLoad(const Stmt* S) : PostStmt(S, PostLoadKind) {}
196
197  static bool classof(const ProgramPoint* Location) {
198    return Location->getKind() == PostLoadKind;
199  }
200};
201
202class PostStore : public PostStmt {
203public:
204  PostStore(const Stmt* S) : PostStmt(S, PostStoreKind) {}
205
206  static bool classof(const ProgramPoint* Location) {
207    return Location->getKind() == PostStoreKind;
208  }
209};
210
211class PostPurgeDeadSymbols : public PostStmt {
212public:
213  PostPurgeDeadSymbols(const Stmt* S) : PostStmt(S, PostPurgeDeadSymbolsKind) {}
214
215  static bool classof(const ProgramPoint* Location) {
216    return Location->getKind() == PostPurgeDeadSymbolsKind;
217  }
218};
219
220class BlockEdge : public ProgramPoint {
221public:
222  BlockEdge(const CFGBlock* B1, const CFGBlock* B2)
223    : ProgramPoint(B1, B2) {}
224
225  CFGBlock* getSrc() const {
226    return static_cast<CFGBlock*>(getData1());
227  }
228
229  CFGBlock* getDst() const {
230    return static_cast<CFGBlock*>(getData2());
231  }
232
233  static bool classof(const ProgramPoint* Location) {
234    return Location->getKind() == BlockEdgeKind;
235  }
236};
237
238
239} // end namespace clang
240
241
242namespace llvm { // Traits specialization for DenseMap
243
244template <> struct DenseMapInfo<clang::ProgramPoint> {
245
246static inline clang::ProgramPoint getEmptyKey() {
247  uintptr_t x =
248   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
249  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
250}
251
252static inline clang::ProgramPoint getTombstoneKey() {
253  uintptr_t x =
254   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
255  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
256}
257
258static unsigned getHashValue(const clang::ProgramPoint& Loc) {
259  return Loc.getHashValue();
260}
261
262static bool isEqual(const clang::ProgramPoint& L,
263                    const clang::ProgramPoint& R) {
264  return L == R;
265}
266
267static bool isPod() {
268  return true;
269}
270};
271} // end namespace llvm
272
273#endif
274