 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
77.8% |
14 / 18 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
94.4% |
17 / 18 |
| |
|
Line Coverage: |
91.4% |
85 / 93 |
| |
 |
|
 |
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/System/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 :
26 : namespace clang {
27 :
28 : class LocationContext;
29 :
30 130560: class ProgramPoint {
31 : public:
32 : enum Kind { BlockEdgeKind,
33 : BlockEntranceKind,
34 : BlockExitKind,
35 : PreStmtKind,
36 : PostStmtKind,
37 : PreLoadKind,
38 : PostLoadKind,
39 : PreStoreKind,
40 : PostStoreKind,
41 : PostPurgeDeadSymbolsKind,
42 : PostStmtCustomKind,
43 : PostLValueKind,
44 : MinPostStmtKind = PostStmtKind,
45 : MaxPostStmtKind = PostLValueKind };
46 :
47 : private:
48 : std::pair<const void *, const void *> Data;
49 : Kind K;
50 :
51 : // The LocationContext could be NULL to allow ProgramPoint to be used in
52 : // context insensitive analysis.
53 : const LocationContext *L;
54 : const void *Tag;
55 :
56 : protected:
57 : ProgramPoint(const void* P, Kind k, const LocationContext *l,
58 221900: const void *tag = 0)
59 221900: : Data(P, NULL), K(k), L(l), Tag(tag) {}
60 :
61 : ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l,
62 87570: const void *tag = 0)
63 87570: : Data(P1, P2), K(k), L(l), Tag(tag) {}
64 :
65 : protected:
66 62634: const void* getData1() const { return Data.first; }
67 10301: const void* getData2() const { return Data.second; }
68 : const void *getTag() const { return Tag; }
69 :
70 : public:
71 132343: Kind getKind() const { return K; }
72 :
73 148555: const LocationContext *getLocationContext() const { return L; }
74 :
75 : // For use with DenseMap. This hash is probably slow.
76 39017: unsigned getHashValue() const {
77 39017: llvm::FoldingSetNodeID ID;
78 39017: Profile(ID);
79 39017: return ID.ComputeHash();
80 : }
81 :
82 : static bool classof(const ProgramPoint*) { return true; }
83 :
84 344973: bool operator==(const ProgramPoint & RHS) const {
182020: branch 0 taken
162953: branch 1 taken
177237: branch 3 taken
4783: branch 4 taken
177237: branch 5 taken
0: branch 6 not taken
177123: branch 7 taken
114: branch 8 taken
85 344973: return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag;
86 : }
87 :
88 : bool operator!=(const ProgramPoint& RHS) const {
89 : return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag;
90 : }
91 :
92 163693: void Profile(llvm::FoldingSetNodeID& ID) const {
93 163693: ID.AddInteger((unsigned) K);
94 163693: ID.AddPointer(Data.first);
95 163693: ID.AddPointer(Data.second);
96 163693: ID.AddPointer(L);
97 163693: ID.AddPointer(Tag);
98 163693: }
99 : };
100 :
101 : class BlockEntrance : public ProgramPoint {
102 : public:
103 : BlockEntrance(const CFGBlock* B, const LocationContext *L,
104 221900: const void *tag = 0)
105 221900: : ProgramPoint(B, BlockEntranceKind, L, tag) {}
106 :
107 20469: CFGBlock* getBlock() const {
108 20469: return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
109 : }
110 :
111 7376: CFGElement getFirstElement() const {
112 7376: const CFGBlock* B = getBlock();
7146: branch 2 taken
0: branch 2 not taken
113 7376: return B->empty() ? CFGElement() : B->front();
114 : }
115 :
116 832: Stmt *getFirstStmt() const {
117 832: return getFirstElement().getStmt();
118 : }
119 :
120 14667: static bool classof(const ProgramPoint* Location) {
121 14667: return Location->getKind() == BlockEntranceKind;
122 : }
123 : };
124 :
125 : class BlockExit : public ProgramPoint {
126 : public:
127 : BlockExit(const CFGBlock* B, const LocationContext *L)
128 : : ProgramPoint(B, BlockExitKind, L) {}
129 :
130 : CFGBlock* getBlock() const {
131 : return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
132 : }
133 :
134 : Stmt* getLastStmt() const {
135 : const CFGBlock* B = getBlock();
136 : return B->empty() ? CFGElement() : B->back();
137 : }
138 :
139 : Stmt* getTerminator() const {
140 : return getBlock()->getTerminator();
141 : }
142 :
143 : static bool classof(const ProgramPoint* Location) {
144 : return Location->getKind() == BlockExitKind;
145 : }
146 : };
147 :
148 : class StmtPoint : public ProgramPoint {
149 : public:
150 : StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
151 48069: const void *tag)
152 48069: : ProgramPoint(S, p2, k, L, tag) {}
153 :
154 41003: const Stmt *getStmt() const { return (const Stmt*) getData1(); }
155 :
156 : template <typename T>
157 993: const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
158 :
159 3107: static bool classof(const ProgramPoint* Location) {
160 3107: unsigned k = Location->getKind();
2968: branch 0 taken
139: branch 1 taken
2968: branch 2 taken
0: branch 3 not taken
161 3107: return k >= PreStmtKind && k <= MaxPostStmtKind;
162 : }
163 : };
164 :
165 :
166 : class PreStmt : public StmtPoint {
167 : public:
168 : PreStmt(const Stmt *S, const LocationContext *L, const void *tag,
169 185: const Stmt *SubStmt = 0)
170 185: : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
171 :
172 : const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
173 :
174 0: static bool classof(const ProgramPoint* Location) {
175 0: return Location->getKind() == PreStmtKind;
176 : }
177 : };
178 :
179 : class PostStmt : public StmtPoint {
180 : protected:
181 16044: PostStmt(const Stmt* S, Kind k, const LocationContext *L, const void *tag = 0)
182 16044: : StmtPoint(S, NULL, k, L, tag) {}
183 :
184 : PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
185 14: const void *tag =0)
186 14: : StmtPoint(S, data, k, L, tag) {}
187 :
188 : public:
189 28931: explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0)
190 28931: : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
191 :
192 68419: static bool classof(const ProgramPoint* Location) {
193 68419: unsigned k = Location->getKind();
67654: branch 0 taken
765: branch 1 taken
67654: branch 2 taken
0: branch 3 not taken
194 68419: return k >= MinPostStmtKind && k <= MaxPostStmtKind;
195 : }
196 : };
197 :
198 : class PostStmtCustom : public PostStmt {
199 : public:
200 : PostStmtCustom(const Stmt* S,
201 : const std::pair<const void*, const void*>* TaggedData,\
202 14: const LocationContext *L)
203 14: : PostStmt(S, TaggedData, PostStmtCustomKind, L) {}
204 :
205 : const std::pair<const void*, const void*>& getTaggedPair() const {
206 : return
207 : *reinterpret_cast<const std::pair<const void*, const void*>*>(getData2());
208 : }
209 :
210 : const void* getTag() const { return getTaggedPair().first; }
211 :
212 : const void* getTaggedData() const { return getTaggedPair().second; }
213 :
214 : static bool classof(const ProgramPoint* Location) {
215 : return Location->getKind() == PostStmtCustomKind;
216 : }
217 : };
218 :
219 :
220 : class LocationCheck : public StmtPoint {
221 : protected:
222 : LocationCheck(const Stmt *S, const LocationContext *L,
223 2895: ProgramPoint::Kind K, const void *tag)
224 2895: : StmtPoint(S, NULL, K, L, tag) {}
225 :
226 : static bool classof(const ProgramPoint *location) {
227 : unsigned k = location->getKind();
228 : return k == PreLoadKind || k == PreStoreKind;
229 : }
230 : };
231 :
232 : class PreLoad : public LocationCheck {
233 : public:
234 429: PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0)
235 429: : LocationCheck(S, L, PreLoadKind, tag) {}
236 :
237 : static bool classof(const ProgramPoint *location) {
238 : return location->getKind() == PreLoadKind;
239 : }
240 : };
241 :
242 : class PreStore : public LocationCheck {
243 : public:
244 2466: PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0)
245 2466: : LocationCheck(S, L, PreStoreKind, tag) {}
246 :
247 : static bool classof(const ProgramPoint *location) {
248 : return location->getKind() == PreStoreKind;
249 : }
250 : };
251 :
252 : class PostLoad : public PostStmt {
253 : public:
254 7942: PostLoad(const Stmt* S, const LocationContext *L, const void *tag = 0)
255 7942: : PostStmt(S, PostLoadKind, L, tag) {}
256 :
257 0: static bool classof(const ProgramPoint* Location) {
258 0: return Location->getKind() == PostLoadKind;
259 : }
260 : };
261 :
262 : class PostStore : public PostStmt {
263 : public:
264 2212: PostStore(const Stmt* S, const LocationContext *L, const void *tag = 0)
265 2212: : PostStmt(S, PostStoreKind, L, tag) {}
266 :
267 0: static bool classof(const ProgramPoint* Location) {
268 0: return Location->getKind() == PostStoreKind;
269 : }
270 : };
271 :
272 : class PostLValue : public PostStmt {
273 : public:
274 4980: PostLValue(const Stmt* S, const LocationContext *L, const void *tag = 0)
275 4980: : PostStmt(S, PostLValueKind, L, tag) {}
276 :
277 0: static bool classof(const ProgramPoint* Location) {
278 0: return Location->getKind() == PostLValueKind;
279 : }
280 : };
281 :
282 : class PostPurgeDeadSymbols : public PostStmt {
283 : public:
284 : PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L,
285 910: const void *tag = 0)
286 910: : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
287 :
288 : static bool classof(const ProgramPoint* Location) {
289 : return Location->getKind() == PostPurgeDeadSymbolsKind;
290 : }
291 : };
292 :
293 : class BlockEdge : public ProgramPoint {
294 : public:
295 39501: BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
296 39501: : ProgramPoint(B1, B2, BlockEdgeKind, L) {}
297 :
298 1162: CFGBlock* getSrc() const {
299 1162: return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1()));
300 : }
301 :
302 10301: CFGBlock* getDst() const {
303 10301: return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2()));
304 : }
305 :
306 18820: static bool classof(const ProgramPoint* Location) {
307 18820: return Location->getKind() == BlockEdgeKind;
308 : }
309 : };
310 :
311 :
312 : } // end namespace clang
313 :
314 :
315 : namespace llvm { // Traits specialization for DenseMap
316 :
317 : template <> struct DenseMapInfo<clang::ProgramPoint> {
318 :
319 111466: static inline clang::ProgramPoint getEmptyKey() {
320 : uintptr_t x =
321 111466: reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
322 111466: return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
323 : }
324 :
325 101281: static inline clang::ProgramPoint getTombstoneKey() {
326 : uintptr_t x =
327 101281: reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
328 101281: return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
329 : }
330 :
331 39017: static unsigned getHashValue(const clang::ProgramPoint& Loc) {
332 39017: return Loc.getHashValue();
333 : }
334 :
335 : static bool isEqual(const clang::ProgramPoint& L,
336 333526: const clang::ProgramPoint& R) {
337 333526: return L == R;
338 : }
339 :
340 : };
341 :
342 : template <>
343 : struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
344 :
345 : } // end namespace llvm
346 :
347 : #endif
Generated: 2010-02-10 01:31 by zcov