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