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