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