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