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