aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis/PathSensitive/SymbolManager.h
blob: a67afed11fcde4df33258b96409ceec21b1fc170 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This files defines SymbolManager, a class that manages symbolic values
//  created for use by GRExprEngine and related classes.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ANALYSIS_SYMMGR_H
#define LLVM_CLANG_ANALYSIS_SYMMGR_H

#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DataTypes.h"
#include <vector>

namespace clang {
  
class SymbolManager;
  
class SymbolID {
  unsigned Data;
public:
  SymbolID() : Data(~0) {}
  SymbolID(unsigned x) : Data(x) {}
  
  bool isInitialized() const { return Data != (unsigned) ~0; }
  operator unsigned() const { assert (isInitialized()); return Data; }
  
  void Profile(llvm::FoldingSetNodeID& ID) const { 
    assert (isInitialized());
    ID.AddInteger(Data);
  }
  
  static inline void Profile(llvm::FoldingSetNodeID& ID, SymbolID X) {
    X.Profile(ID);
  }
};

// SymbolData: Used to record meta data about symbols.

class SymbolData {
public:
  enum Kind { UndefKind, ParmKind, GlobalKind, ContentsOfKind };
  
private:
  uintptr_t Data;
  Kind K;
  
protected:
  SymbolData(uintptr_t D, Kind k) : Data(D), K(k) {}
  SymbolData(void* D, Kind k) : Data(reinterpret_cast<uintptr_t>(D)), K(k) {}
  
  void* getPtr() const { 
    assert (K != UndefKind);
    return reinterpret_cast<void*>(Data);
  }
  
  uintptr_t getInt() const {
    assert (K != UndefKind);
    return Data;
  }
  
public:
  SymbolData() : Data(0), K(UndefKind) {}
  
  Kind  getKind() const { return K; }  
  
  inline bool operator==(const SymbolData& R) const { 
    return K == R.K && Data == R.Data;
  }
  
  QualType getType(const SymbolManager& SymMgr) const;
  
  // Implement isa<T> support.
  static inline bool classof(const SymbolData*) { return true; }
};

class SymbolDataParmVar : public SymbolData {
public:
  SymbolDataParmVar(ParmVarDecl* VD) : SymbolData(VD, ParmKind) {}
  
  ParmVarDecl* getDecl() const { return (ParmVarDecl*) getPtr(); }
  
  // Implement isa<T> support.
  static inline bool classof(const SymbolData* D) {
    return D->getKind() == ParmKind;
  }
};
  
class SymbolDataGlobalVar : public SymbolData {
public:
  SymbolDataGlobalVar(VarDecl* VD) : SymbolData(VD, GlobalKind) {}
  
  VarDecl* getDecl() const { return (VarDecl*) getPtr(); }
  
  // Implement isa<T> support.
  static inline bool classof(const SymbolData* D) {
    return D->getKind() == GlobalKind;
  }
};

class SymbolDataContentsOf : public SymbolData {
public:
  SymbolDataContentsOf(SymbolID ID) : SymbolData(ID, ContentsOfKind) {}
  
  SymbolID getSymbol() const { return (SymbolID) getInt(); }
  
  // Implement isa<T> support.
  static inline bool classof(const SymbolData* D) {
    return D->getKind() == ContentsOfKind;
  }  
};

// Constraints on symbols.  Usually wrapped by RValues.

class SymIntConstraint : public llvm::FoldingSetNode {
  SymbolID Symbol;
  BinaryOperator::Opcode Op;
  const llvm::APSInt& Val;
public:  
  SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op, 
                   const llvm::APSInt& V)
  : Symbol(sym),
  Op(op), Val(V) {}
  
  BinaryOperator::Opcode getOpcode() const { return Op; }
  const SymbolID& getSymbol() const { return Symbol; }
  const llvm::APSInt& getInt() const { return Val; }
  
  static inline void Profile(llvm::FoldingSetNodeID& ID,
                             const SymbolID& Symbol,
                             BinaryOperator::Opcode Op,
                             const llvm::APSInt& Val) {
    Symbol.Profile(ID);
    ID.AddInteger(Op);
    ID.AddPointer(&Val);
  }
  
  void Profile(llvm::FoldingSetNodeID& ID) {
    Profile(ID, Symbol, Op, Val);
  }
};


class SymbolManager {
  std::vector<SymbolData> SymbolToData;
  
  typedef llvm::DenseMap<void*,SymbolID> MapTy;
  MapTy DataToSymbol;
  
  void* getKey(void* P) const {
    return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(P) | 0x1);
  }
  
  void* getKey(SymbolID sym) const {
    return reinterpret_cast<void*>((uintptr_t) (sym << 1));
  }
  
public:
  SymbolManager();
  ~SymbolManager();
  
  SymbolID getSymbol(VarDecl* D);
  SymbolID getContentsOfSymbol(SymbolID sym);
  
  inline const SymbolData& getSymbolData(SymbolID ID) const {
    assert (ID < SymbolToData.size());
    return SymbolToData[ID];
  }
  
  inline QualType getType(SymbolID ID) const {
    return getSymbolData(ID).getType(*this);
  }
};

} // end clang namespace

#endif