ProgramPoint.h revision 6e5977f0a8a680191fb4b4d8f32bc2c629faf0c2
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 { BlockEntranceKind=0, PostStmtKind=1, BlockExitKind=2, 29 BlockEdgeSrcKind=3, BlockEdgeDstKind=4, BlockEdgeAuxKind=5 }; 30protected: 31 uintptr_t Data; 32 33 ProgramPoint(const void* Ptr, Kind k) { 34 setRawData(Ptr, k); 35 } 36 37 ProgramPoint() : Data(0) {} 38 39 void setRawData(const void* Ptr, Kind k) { 40 assert ((reinterpret_cast<uintptr_t>(const_cast<void*>(Ptr)) & 0x7) == 0 41 && "Address must have at least an 8-byte alignment."); 42 43 Data = reinterpret_cast<uintptr_t>(const_cast<void*>(Ptr)) | k; 44 } 45 46public: 47 unsigned getKind() const { return Data & 0x7; } 48 void* getRawPtr() const { return reinterpret_cast<void*>(Data & ~0x7); } 49 void* getRawData() const { return reinterpret_cast<void*>(Data); } 50 51 static bool classof(const ProgramPoint*) { return true; } 52 bool operator==(const ProgramPoint & RHS) const { return Data == RHS.Data; } 53 bool operator!=(const ProgramPoint& RHS) const { return Data != RHS.Data; } 54 55 void Profile(llvm::FoldingSetNodeID& ID) const { 56 ID.AddInteger(getKind()); 57 ID.AddPointer(getRawPtr()); 58 } 59}; 60 61class BlockEntrance : public ProgramPoint { 62public: 63 BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {} 64 65 CFGBlock* getBlock() const { 66 return reinterpret_cast<CFGBlock*>(getRawPtr()); 67 } 68 69 Stmt* getFirstStmt() const { 70 CFGBlock* B = getBlock(); 71 return B->empty() ? NULL : B->front(); 72 } 73 74 static bool classof(const ProgramPoint* Location) { 75 return Location->getKind() == BlockEntranceKind; 76 } 77}; 78 79class BlockExit : public ProgramPoint { 80public: 81 BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {} 82 83 CFGBlock* getBlock() const { 84 return reinterpret_cast<CFGBlock*>(getRawPtr()); 85 } 86 87 Stmt* getLastStmt() const { 88 CFGBlock* B = getBlock(); 89 return B->empty() ? NULL : B->back(); 90 } 91 92 Stmt* getTerminator() const { 93 return getBlock()->getTerminator(); 94 } 95 96 static bool classof(const ProgramPoint* Location) { 97 return Location->getKind() == BlockExitKind; 98 } 99}; 100 101 102class PostStmt : public ProgramPoint { 103public: 104 PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {} 105 106 Stmt* getStmt() const { return (Stmt*) getRawPtr(); } 107 108 static bool classof(const ProgramPoint* Location) { 109 return Location->getKind() == PostStmtKind; 110 } 111}; 112 113class BlockEdge : public ProgramPoint { 114 typedef std::pair<CFGBlock*,CFGBlock*> BPair; 115public: 116 BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2); 117 118 /// This ctor forces the BlockEdge to be constructed using an explicitly 119 /// allocated pair object that is stored in the CFG. This is usually 120 /// used to construct edges representing jumps using computed gotos. 121 BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2, bool) 122 : ProgramPoint(cfg.getBlockEdgeImpl(B1, B2), BlockEdgeAuxKind) {} 123 124 125 CFGBlock* getSrc() const; 126 CFGBlock* getDst() const; 127 128 static bool classof(const ProgramPoint* Location) { 129 unsigned k = Location->getKind(); 130 return k >= BlockEdgeSrcKind && k <= BlockEdgeAuxKind; 131 } 132}; 133 134 135 136} // end namespace clang 137 138 139namespace llvm { // Traits specialization for DenseMap 140 141template <> struct DenseMapInfo<clang::ProgramPoint> { 142 143 static inline clang::ProgramPoint getEmptyKey() { 144 uintptr_t x = 145 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; 146 147 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); 148 } 149 150 static inline clang::ProgramPoint getTombstoneKey() { 151 uintptr_t x = 152 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; 153 154 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); 155 } 156 157 static unsigned getHashValue(const clang::ProgramPoint& Loc) { 158 return DenseMapInfo<void*>::getHashValue(Loc.getRawData()); 159 } 160 161 static bool isEqual(const clang::ProgramPoint& L, 162 const clang::ProgramPoint& R) { 163 return L == R; 164 } 165 166 static bool isPod() { 167 return true; 168 } 169}; 170} // end namespace llvm 171 172#endif 173