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