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