1 //==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the interface ProgramPoint, which identifies a
11 // distinct location in a function.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
16 #define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
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"
28 class LocationContext;
32 enum Kind { BlockEdgeKind,
36 // Keep the following together and in this order.
38 PostLocationChecksSucceedKind,
39 PostOutOfBoundsCheckFailedKind,
40 PostNullCheckFailedKind,
41 PostUndefLocationCheckFailedKind,
44 PostPurgeDeadSymbolsKind,
47 MinPostStmtKind = PostStmtKind,
48 MaxPostStmtKind = PostLValueKind };
51 std::pair<const void *, const void *> Data;
54 // The LocationContext could be NULL to allow ProgramPoint to be used in
55 // context insensitive analysis.
56 const LocationContext *L;
60 ProgramPoint(const void* P, Kind k, const LocationContext *l,
62 : Data(P, NULL), K(k), L(l), Tag(tag) {}
64 ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l,
66 : Data(P1, P2), K(k), L(l), Tag(tag) {}
69 const void* getData1() const { return Data.first; }
70 const void* getData2() const { return Data.second; }
71 const void *getTag() const { return Tag; }
74 Kind getKind() const { return K; }
76 const LocationContext *getLocationContext() const { return L; }
78 // For use with DenseMap. This hash is probably slow.
79 unsigned getHashValue() const {
80 llvm::FoldingSetNodeID ID;
82 return ID.ComputeHash();
85 static bool classof(const ProgramPoint*) { return true; }
87 bool operator==(const ProgramPoint & RHS) const {
88 return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag;
91 bool operator!=(const ProgramPoint& RHS) const {
92 return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag;
95 void Profile(llvm::FoldingSetNodeID& ID) const {
96 ID.AddInteger((unsigned) K);
97 ID.AddPointer(Data.first);
98 ID.AddPointer(Data.second);
104 class BlockEntrance : public ProgramPoint {
106 BlockEntrance(const CFGBlock* B, const LocationContext *L,
108 : ProgramPoint(B, BlockEntranceKind, L, tag) {}
110 CFGBlock* getBlock() const {
111 return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
114 Stmt* getFirstStmt() const {
115 const CFGBlock* B = getBlock();
116 return B->empty() ? NULL : B->front();
119 static bool classof(const ProgramPoint* Location) {
120 return Location->getKind() == BlockEntranceKind;
124 class BlockExit : public ProgramPoint {
126 BlockExit(const CFGBlock* B, const LocationContext *L)
127 : ProgramPoint(B, BlockExitKind, L) {}
129 CFGBlock* getBlock() const {
130 return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
133 Stmt* getLastStmt() const {
134 const CFGBlock* B = getBlock();
135 return B->empty() ? NULL : B->back();
138 Stmt* getTerminator() const {
139 return getBlock()->getTerminator();
142 static bool classof(const ProgramPoint* Location) {
143 return Location->getKind() == BlockExitKind;
147 class StmtPoint : public ProgramPoint {
149 StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
151 : ProgramPoint(S, p2, k, L, tag) {}
153 const Stmt *getStmt() const { return (const Stmt*) getData1(); }
155 template <typename T>
156 const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
158 static bool classof(const ProgramPoint* Location) {
159 unsigned k = Location->getKind();
160 return k >= PreStmtKind && k <= MaxPostStmtKind;
165 class PreStmt : public StmtPoint {
167 PreStmt(const Stmt *S, const LocationContext *L, const void *tag,
168 const Stmt *SubStmt = 0)
169 : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
171 const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
173 static bool classof(const ProgramPoint* Location) {
174 return Location->getKind() == PreStmtKind;
178 class PostStmt : public StmtPoint {
180 PostStmt(const Stmt* S, Kind k, const LocationContext *L, const void *tag = 0)
181 : StmtPoint(S, NULL, k, L, tag) {}
183 PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
185 : StmtPoint(S, data, k, L, tag) {}
188 explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0)
189 : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
191 static bool classof(const ProgramPoint* Location) {
192 unsigned k = Location->getKind();
193 return k >= MinPostStmtKind && k <= MaxPostStmtKind;
197 class PostLocationChecksSucceed : public PostStmt {
199 PostLocationChecksSucceed(const Stmt* S, const LocationContext *L,
201 : PostStmt(S, PostLocationChecksSucceedKind, L, tag) {}
203 static bool classof(const ProgramPoint* Location) {
204 return Location->getKind() == PostLocationChecksSucceedKind;
208 class PostStmtCustom : public PostStmt {
210 PostStmtCustom(const Stmt* S,
211 const std::pair<const void*, const void*>* TaggedData,\
212 const LocationContext *L)
213 : PostStmt(S, TaggedData, PostStmtCustomKind, L) {}
215 const std::pair<const void*, const void*>& getTaggedPair() const {
217 *reinterpret_cast<const std::pair<const void*, const void*>*>(getData2());
220 const void* getTag() const { return getTaggedPair().first; }
222 const void* getTaggedData() const { return getTaggedPair().second; }
224 static bool classof(const ProgramPoint* Location) {
225 return Location->getKind() == PostStmtCustomKind;
229 class PostOutOfBoundsCheckFailed : public PostStmt {
231 PostOutOfBoundsCheckFailed(const Stmt* S, const LocationContext *L,
233 : PostStmt(S, PostOutOfBoundsCheckFailedKind, L, tag) {}
235 static bool classof(const ProgramPoint* Location) {
236 return Location->getKind() == PostOutOfBoundsCheckFailedKind;
240 class PostUndefLocationCheckFailed : public PostStmt {
242 PostUndefLocationCheckFailed(const Stmt* S, const LocationContext *L,
244 : PostStmt(S, PostUndefLocationCheckFailedKind, L, tag) {}
246 static bool classof(const ProgramPoint* Location) {
247 return Location->getKind() == PostUndefLocationCheckFailedKind;
251 class PostNullCheckFailed : public PostStmt {
253 PostNullCheckFailed(const Stmt* S, const LocationContext *L,
255 : PostStmt(S, PostNullCheckFailedKind, L, tag) {}
257 static bool classof(const ProgramPoint* Location) {
258 return Location->getKind() == PostNullCheckFailedKind;
262 class PostLoad : public PostStmt {
264 PostLoad(const Stmt* S, const LocationContext *L, const void *tag = 0)
265 : PostStmt(S, PostLoadKind, L, tag) {}
267 static bool classof(const ProgramPoint* Location) {
268 return Location->getKind() == PostLoadKind;
272 class PostStore : public PostStmt {
274 PostStore(const Stmt* S, const LocationContext *L, const void *tag = 0)
275 : PostStmt(S, PostStoreKind, L, tag) {}
277 static bool classof(const ProgramPoint* Location) {
278 return Location->getKind() == PostStoreKind;
282 class PostLValue : public PostStmt {
284 PostLValue(const Stmt* S, const LocationContext *L, const void *tag = 0)
285 : PostStmt(S, PostLValueKind, L, tag) {}
287 static bool classof(const ProgramPoint* Location) {
288 return Location->getKind() == PostLValueKind;
292 class PostPurgeDeadSymbols : public PostStmt {
294 PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L,
296 : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
298 static bool classof(const ProgramPoint* Location) {
299 return Location->getKind() == PostPurgeDeadSymbolsKind;
303 class BlockEdge : public ProgramPoint {
305 BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
306 : ProgramPoint(B1, B2, BlockEdgeKind, L) {}
308 CFGBlock* getSrc() const {
309 return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1()));
312 CFGBlock* getDst() const {
313 return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2()));
316 static bool classof(const ProgramPoint* Location) {
317 return Location->getKind() == BlockEdgeKind;
322 } // end namespace clang
325 namespace llvm { // Traits specialization for DenseMap
327 template <> struct DenseMapInfo<clang::ProgramPoint> {
329 static inline clang::ProgramPoint getEmptyKey() {
331 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
332 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
335 static inline clang::ProgramPoint getTombstoneKey() {
337 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
338 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
341 static unsigned getHashValue(const clang::ProgramPoint& Loc) {
342 return Loc.getHashValue();
345 static bool isEqual(const clang::ProgramPoint& L,
346 const clang::ProgramPoint& R) {
350 static bool isPod() {
354 } // end namespace llvm