ProgramPoint.h revision 82bae3f6bf7bc4733d9c87659b266e23ad55f420
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, PostLoadKind, PostStoreKind,
31              PostPurgeDeadSymbolsKind };
32
33private:
34  std::pair<uintptr_t,uintptr_t> Data;
35
36protected:
37  ProgramPoint(const void* P, Kind k)
38    : Data(reinterpret_cast<uintptr_t>(P), (uintptr_t) k) {}
39
40  ProgramPoint(const void* P1, const void* P2)
41    : Data(reinterpret_cast<uintptr_t>(P1) | 0x1,
42           reinterpret_cast<uintptr_t>(P2)) {}
43
44protected:
45  void* getData1NoMask() const {
46    assert (getKind() != BlockEdgeKind);
47    return reinterpret_cast<void*>(Data.first);
48  }
49
50  void* getData1() const {
51    assert (getKind() == BlockEdgeKind);
52    return reinterpret_cast<void*>(Data.first & ~0x1);
53  }
54
55  void* getData2() const {
56    assert (getKind() == BlockEdgeKind);
57    return reinterpret_cast<void*>(Data.second);
58  }
59
60public:
61
62  uintptr_t getKind() const {
63    return Data.first & 0x1 ? (uintptr_t) BlockEdgeKind : Data.second;
64  }
65
66  // For use with DenseMap.
67  unsigned getHashValue() const {
68    std::pair<void*,void*> P(reinterpret_cast<void*>(Data.first),
69                             reinterpret_cast<void*>(Data.second));
70    return llvm::DenseMapInfo<std::pair<void*,void*> >::getHashValue(P);
71  }
72
73  static bool classof(const ProgramPoint*) { return true; }
74
75  bool operator==(const ProgramPoint & RHS) const {
76    return Data == RHS.Data;
77  }
78
79  bool operator!=(const ProgramPoint& RHS) const {
80    return Data != RHS.Data;
81  }
82
83  bool operator<(const ProgramPoint& RHS) const {
84    return Data < RHS.Data;
85  }
86
87  void Profile(llvm::FoldingSetNodeID& ID) const {
88    ID.AddPointer(reinterpret_cast<void*>(Data.first));
89    ID.AddPointer(reinterpret_cast<void*>(Data.second));
90  }
91};
92
93class BlockEntrance : public ProgramPoint {
94public:
95  BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {}
96
97  CFGBlock* getBlock() const {
98    return reinterpret_cast<CFGBlock*>(getData1NoMask());
99  }
100
101  Stmt* getFirstStmt() const {
102    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 reinterpret_cast<CFGBlock*>(getData1NoMask());
117  }
118
119  Stmt* getLastStmt() const {
120    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
133
134class PostStmt : public ProgramPoint {
135protected:
136  PostStmt(const Stmt* S, Kind k) : ProgramPoint(S, k) {}
137public:
138  PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {}
139
140  Stmt* getStmt() const { return (Stmt*) getData1NoMask(); }
141
142  static bool classof(const ProgramPoint* Location) {
143    unsigned k = Location->getKind();
144    return k >= PostStmtKind && k <= PostPurgeDeadSymbolsKind;
145  }
146};
147
148class PostLoad : public PostStmt {
149public:
150  PostLoad(const Stmt* S) : PostStmt(S, PostLoadKind) {}
151
152  static bool classof(const ProgramPoint* Location) {
153    return Location->getKind() == PostLoadKind;
154  }
155};
156
157class PostStore : public PostStmt {
158public:
159  PostStore(const Stmt* S) : PostStmt(S, PostLoadKind) {}
160
161  static bool classof(const ProgramPoint* Location) {
162    return Location->getKind() == PostStoreKind;
163  }
164};
165
166class PostPurgeDeadSymbols : public PostStmt {
167public:
168  PostPurgeDeadSymbols(const Stmt* S) : PostStmt(S, PostPurgeDeadSymbolsKind) {}
169
170  static bool classof(const ProgramPoint* Location) {
171    return Location->getKind() == PostPurgeDeadSymbolsKind;
172  }
173};
174
175class BlockEdge : public ProgramPoint {
176public:
177  BlockEdge(const CFGBlock* B1, const CFGBlock* B2)
178    : ProgramPoint(B1, B2) {}
179
180  CFGBlock* getSrc() const {
181    return static_cast<CFGBlock*>(getData1());
182  }
183
184  CFGBlock* getDst() const {
185    return static_cast<CFGBlock*>(getData2());
186  }
187
188  static bool classof(const ProgramPoint* Location) {
189    return Location->getKind() == BlockEdgeKind;
190  }
191};
192
193
194} // end namespace clang
195
196
197namespace llvm { // Traits specialization for DenseMap
198
199template <> struct DenseMapInfo<clang::ProgramPoint> {
200
201static inline clang::ProgramPoint getEmptyKey() {
202  uintptr_t x =
203   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
204  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
205}
206
207static inline clang::ProgramPoint getTombstoneKey() {
208  uintptr_t x =
209   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
210  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
211}
212
213static unsigned getHashValue(const clang::ProgramPoint& Loc) {
214  return Loc.getHashValue();
215}
216
217static bool isEqual(const clang::ProgramPoint& L,
218                    const clang::ProgramPoint& R) {
219  return L == R;
220}
221
222static bool isPod() {
223  return true;
224}
225};
226} // end namespace llvm
227
228#endif
229