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