ProgramPoint.h revision 2680b5f926fad29c1a2b2723a70d189f4b637979
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 if (getKind() != PostStmtCustomKind) 115 ID.AddPointer(reinterpret_cast<void*>(Data.second)); 116 else { 117 const std::pair<const void*, const void*> *P = 118 reinterpret_cast<std::pair<const void*, const void*>*>(Data.second); 119 ID.AddPointer(P->first); 120 ID.AddPointer(P->second); 121 } 122 } 123}; 124 125class BlockEntrance : public ProgramPoint { 126public: 127 BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {} 128 129 CFGBlock* getBlock() const { 130 return reinterpret_cast<CFGBlock*>(getData1NoMask()); 131 } 132 133 Stmt* getFirstStmt() const { 134 CFGBlock* B = getBlock(); 135 return B->empty() ? NULL : B->front(); 136 } 137 138 static bool classof(const ProgramPoint* Location) { 139 return Location->getKind() == BlockEntranceKind; 140 } 141}; 142 143class BlockExit : public ProgramPoint { 144public: 145 BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {} 146 147 CFGBlock* getBlock() const { 148 return reinterpret_cast<CFGBlock*>(getData1NoMask()); 149 } 150 151 Stmt* getLastStmt() const { 152 CFGBlock* B = getBlock(); 153 return B->empty() ? NULL : B->back(); 154 } 155 156 Stmt* getTerminator() const { 157 return getBlock()->getTerminator(); 158 } 159 160 static bool classof(const ProgramPoint* Location) { 161 return Location->getKind() == BlockExitKind; 162 } 163}; 164 165 166class PostStmt : public ProgramPoint { 167protected: 168 PostStmt(const Stmt* S, Kind k) : ProgramPoint(S, k) {} 169 PostStmt(const Stmt* S, const void* data) : ProgramPoint(S, data, true) {} 170 171public: 172 PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {} 173 174 Stmt* getStmt() const { return (Stmt*) getData1(); } 175 176 static bool classof(const ProgramPoint* Location) { 177 unsigned k = Location->getKind(); 178 return k >= MinPostStmtKind && k <= MaxPostStmtKind; 179 } 180}; 181 182class PostLocationChecksSucceed : public PostStmt { 183public: 184 PostLocationChecksSucceed(const Stmt* S) 185 : PostStmt(S, PostLocationChecksSucceedKind) {} 186 187 static bool classof(const ProgramPoint* Location) { 188 return Location->getKind() == PostLocationChecksSucceedKind; 189 } 190}; 191 192class PostStmtCustom : public PostStmt { 193public: 194 PostStmtCustom(const Stmt* S, 195 const std::pair<const void*, const void*>* TaggedData) 196 : PostStmt(S, TaggedData) { 197 assert(getKind() == PostStmtCustomKind); 198 } 199 200 const std::pair<const void*, const void*>& getTaggedPair() const { 201 return *reinterpret_cast<std::pair<const void*, const void*>*>(getData2()); 202 } 203 204 const void* getTag() const { return getTaggedPair().first; } 205 206 const void* getTaggedData() const { return getTaggedPair().second; } 207 208 static bool classof(const ProgramPoint* Location) { 209 return Location->getKind() == PostStmtCustomKind; 210 } 211}; 212 213class PostOutOfBoundsCheckFailed : public PostStmt { 214public: 215 PostOutOfBoundsCheckFailed(const Stmt* S) 216 : PostStmt(S, PostOutOfBoundsCheckFailedKind) {} 217 218 static bool classof(const ProgramPoint* Location) { 219 return Location->getKind() == PostOutOfBoundsCheckFailedKind; 220 } 221}; 222 223class PostUndefLocationCheckFailed : public PostStmt { 224public: 225 PostUndefLocationCheckFailed(const Stmt* S) 226 : PostStmt(S, PostUndefLocationCheckFailedKind) {} 227 228 static bool classof(const ProgramPoint* Location) { 229 return Location->getKind() == PostUndefLocationCheckFailedKind; 230 } 231}; 232 233class PostNullCheckFailed : public PostStmt { 234public: 235 PostNullCheckFailed(const Stmt* S) 236 : PostStmt(S, PostNullCheckFailedKind) {} 237 238 static bool classof(const ProgramPoint* Location) { 239 return Location->getKind() == PostNullCheckFailedKind; 240 } 241}; 242 243class PostLoad : public PostStmt { 244public: 245 PostLoad(const Stmt* S) : PostStmt(S, PostLoadKind) {} 246 247 static bool classof(const ProgramPoint* Location) { 248 return Location->getKind() == PostLoadKind; 249 } 250}; 251 252class PostStore : public PostStmt { 253public: 254 PostStore(const Stmt* S) : PostStmt(S, PostStoreKind) {} 255 256 static bool classof(const ProgramPoint* Location) { 257 return Location->getKind() == PostStoreKind; 258 } 259}; 260 261class PostPurgeDeadSymbols : public PostStmt { 262public: 263 PostPurgeDeadSymbols(const Stmt* S) : PostStmt(S, PostPurgeDeadSymbolsKind) {} 264 265 static bool classof(const ProgramPoint* Location) { 266 return Location->getKind() == PostPurgeDeadSymbolsKind; 267 } 268}; 269 270class BlockEdge : public ProgramPoint { 271public: 272 BlockEdge(const CFGBlock* B1, const CFGBlock* B2) 273 : ProgramPoint(B1, B2) {} 274 275 CFGBlock* getSrc() const { 276 return static_cast<CFGBlock*>(getData1()); 277 } 278 279 CFGBlock* getDst() const { 280 return static_cast<CFGBlock*>(getData2()); 281 } 282 283 static bool classof(const ProgramPoint* Location) { 284 return Location->getKind() == BlockEdgeKind; 285 } 286}; 287 288 289} // end namespace clang 290 291 292namespace llvm { // Traits specialization for DenseMap 293 294template <> struct DenseMapInfo<clang::ProgramPoint> { 295 296static inline clang::ProgramPoint getEmptyKey() { 297 uintptr_t x = 298 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; 299 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); 300} 301 302static inline clang::ProgramPoint getTombstoneKey() { 303 uintptr_t x = 304 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; 305 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); 306} 307 308static unsigned getHashValue(const clang::ProgramPoint& Loc) { 309 return Loc.getHashValue(); 310} 311 312static bool isEqual(const clang::ProgramPoint& L, 313 const clang::ProgramPoint& R) { 314 return L == R; 315} 316 317static bool isPod() { 318 return true; 319} 320}; 321} // end namespace llvm 322 323#endif 324