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