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