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