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