ProgramPoint.h revision 82bae3f6bf7bc4733d9c87659b266e23ad55f420
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 24namespace clang { 25 26class ProgramPoint { 27public: 28 enum Kind { BlockEdgeKind=0, BlockEntranceKind, BlockExitKind, 29 // Keep the following four together and in this order. 30 PostStmtKind, PostLoadKind, PostStoreKind, 31 PostPurgeDeadSymbolsKind }; 32 33private: 34 std::pair<uintptr_t,uintptr_t> Data; 35 36protected: 37 ProgramPoint(const void* P, Kind k) 38 : Data(reinterpret_cast<uintptr_t>(P), (uintptr_t) k) {} 39 40 ProgramPoint(const void* P1, const void* P2) 41 : Data(reinterpret_cast<uintptr_t>(P1) | 0x1, 42 reinterpret_cast<uintptr_t>(P2)) {} 43 44protected: 45 void* getData1NoMask() const { 46 assert (getKind() != BlockEdgeKind); 47 return reinterpret_cast<void*>(Data.first); 48 } 49 50 void* getData1() const { 51 assert (getKind() == BlockEdgeKind); 52 return reinterpret_cast<void*>(Data.first & ~0x1); 53 } 54 55 void* getData2() const { 56 assert (getKind() == BlockEdgeKind); 57 return reinterpret_cast<void*>(Data.second); 58 } 59 60public: 61 62 uintptr_t getKind() const { 63 return Data.first & 0x1 ? (uintptr_t) BlockEdgeKind : Data.second; 64 } 65 66 // For use with DenseMap. 67 unsigned getHashValue() const { 68 std::pair<void*,void*> P(reinterpret_cast<void*>(Data.first), 69 reinterpret_cast<void*>(Data.second)); 70 return llvm::DenseMapInfo<std::pair<void*,void*> >::getHashValue(P); 71 } 72 73 static bool classof(const ProgramPoint*) { return true; } 74 75 bool operator==(const ProgramPoint & RHS) const { 76 return Data == RHS.Data; 77 } 78 79 bool operator!=(const ProgramPoint& RHS) const { 80 return Data != RHS.Data; 81 } 82 83 bool operator<(const ProgramPoint& RHS) const { 84 return Data < RHS.Data; 85 } 86 87 void Profile(llvm::FoldingSetNodeID& ID) const { 88 ID.AddPointer(reinterpret_cast<void*>(Data.first)); 89 ID.AddPointer(reinterpret_cast<void*>(Data.second)); 90 } 91}; 92 93class BlockEntrance : public ProgramPoint { 94public: 95 BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {} 96 97 CFGBlock* getBlock() const { 98 return reinterpret_cast<CFGBlock*>(getData1NoMask()); 99 } 100 101 Stmt* getFirstStmt() const { 102 CFGBlock* B = getBlock(); 103 return B->empty() ? NULL : B->front(); 104 } 105 106 static bool classof(const ProgramPoint* Location) { 107 return Location->getKind() == BlockEntranceKind; 108 } 109}; 110 111class BlockExit : public ProgramPoint { 112public: 113 BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {} 114 115 CFGBlock* getBlock() const { 116 return reinterpret_cast<CFGBlock*>(getData1NoMask()); 117 } 118 119 Stmt* getLastStmt() const { 120 CFGBlock* B = getBlock(); 121 return B->empty() ? NULL : B->back(); 122 } 123 124 Stmt* getTerminator() const { 125 return getBlock()->getTerminator(); 126 } 127 128 static bool classof(const ProgramPoint* Location) { 129 return Location->getKind() == BlockExitKind; 130 } 131}; 132 133 134class PostStmt : public ProgramPoint { 135protected: 136 PostStmt(const Stmt* S, Kind k) : ProgramPoint(S, k) {} 137public: 138 PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {} 139 140 Stmt* getStmt() const { return (Stmt*) getData1NoMask(); } 141 142 static bool classof(const ProgramPoint* Location) { 143 unsigned k = Location->getKind(); 144 return k >= PostStmtKind && k <= PostPurgeDeadSymbolsKind; 145 } 146}; 147 148class PostLoad : public PostStmt { 149public: 150 PostLoad(const Stmt* S) : PostStmt(S, PostLoadKind) {} 151 152 static bool classof(const ProgramPoint* Location) { 153 return Location->getKind() == PostLoadKind; 154 } 155}; 156 157class PostStore : public PostStmt { 158public: 159 PostStore(const Stmt* S) : PostStmt(S, PostLoadKind) {} 160 161 static bool classof(const ProgramPoint* Location) { 162 return Location->getKind() == PostStoreKind; 163 } 164}; 165 166class PostPurgeDeadSymbols : public PostStmt { 167public: 168 PostPurgeDeadSymbols(const Stmt* S) : PostStmt(S, PostPurgeDeadSymbolsKind) {} 169 170 static bool classof(const ProgramPoint* Location) { 171 return Location->getKind() == PostPurgeDeadSymbolsKind; 172 } 173}; 174 175class BlockEdge : public ProgramPoint { 176public: 177 BlockEdge(const CFGBlock* B1, const CFGBlock* B2) 178 : ProgramPoint(B1, B2) {} 179 180 CFGBlock* getSrc() const { 181 return static_cast<CFGBlock*>(getData1()); 182 } 183 184 CFGBlock* getDst() const { 185 return static_cast<CFGBlock*>(getData2()); 186 } 187 188 static bool classof(const ProgramPoint* Location) { 189 return Location->getKind() == BlockEdgeKind; 190 } 191}; 192 193 194} // end namespace clang 195 196 197namespace llvm { // Traits specialization for DenseMap 198 199template <> struct DenseMapInfo<clang::ProgramPoint> { 200 201static inline clang::ProgramPoint getEmptyKey() { 202 uintptr_t x = 203 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; 204 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); 205} 206 207static inline clang::ProgramPoint getTombstoneKey() { 208 uintptr_t x = 209 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; 210 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); 211} 212 213static unsigned getHashValue(const clang::ProgramPoint& Loc) { 214 return Loc.getHashValue(); 215} 216 217static bool isEqual(const clang::ProgramPoint& L, 218 const clang::ProgramPoint& R) { 219 return L == R; 220} 221 222static bool isPod() { 223 return true; 224} 225}; 226} // end namespace llvm 227 228#endif 229