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