APValue.h revision e24f5fc8c763f1b5536b8d70dd510ca959db3a80
1//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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 APValue class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_APVALUE_H
15#define LLVM_CLANG_AST_APVALUE_H
16
17#include "clang/Basic/LLVM.h"
18#include "llvm/ADT/APSInt.h"
19#include "llvm/ADT/APFloat.h"
20#include "llvm/ADT/PointerIntPair.h"
21#include "llvm/ADT/PointerUnion.h"
22
23namespace clang {
24  class CharUnits;
25  class DiagnosticBuilder;
26  class Expr;
27  class FieldDecl;
28  class Decl;
29  class ValueDecl;
30  class CXXRecordDecl;
31
32/// APValue - This class implements a discriminated union of [uninitialized]
33/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
34/// [Vector: N * APValue], [Array: N * APValue]
35class APValue {
36  typedef llvm::APSInt APSInt;
37  typedef llvm::APFloat APFloat;
38public:
39  enum ValueKind {
40    Uninitialized,
41    Int,
42    Float,
43    ComplexInt,
44    ComplexFloat,
45    LValue,
46    Vector,
47    Array,
48    Struct,
49    Union,
50    MemberPointer
51  };
52  typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase;
53  typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
54  union LValuePathEntry {
55    /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
56    /// in the path. An opaque value of type BaseOrMemberType.
57    void *BaseOrMember;
58    /// ArrayIndex - The array index of the next item in the path.
59    uint64_t ArrayIndex;
60  };
61  struct NoLValuePath {};
62  struct UninitArray {};
63  struct UninitStruct {};
64private:
65  ValueKind Kind;
66
67  struct ComplexAPSInt {
68    APSInt Real, Imag;
69    ComplexAPSInt() : Real(1), Imag(1) {}
70  };
71  struct ComplexAPFloat {
72    APFloat Real, Imag;
73    ComplexAPFloat() : Real(0.0), Imag(0.0) {}
74  };
75  struct LV;
76  struct Vec {
77    APValue *Elts;
78    unsigned NumElts;
79    Vec() : Elts(0), NumElts(0) {}
80    ~Vec() { delete[] Elts; }
81  };
82  struct Arr {
83    APValue *Elts;
84    unsigned NumElts, ArrSize;
85    Arr(unsigned NumElts, unsigned ArrSize);
86    ~Arr();
87  };
88  struct StructData {
89    APValue *Elts;
90    unsigned NumBases;
91    unsigned NumFields;
92    StructData(unsigned NumBases, unsigned NumFields);
93    ~StructData();
94  };
95  struct UnionData {
96    const FieldDecl *Field;
97    APValue *Value;
98    UnionData();
99    ~UnionData();
100  };
101  struct MemberPointerData;
102
103  enum {
104    MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
105               sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
106  };
107
108  union {
109    void *Aligner;
110    char Data[MaxSize];
111  };
112
113public:
114  APValue() : Kind(Uninitialized) {}
115  explicit APValue(const APSInt &I) : Kind(Uninitialized) {
116    MakeInt(); setInt(I);
117  }
118  explicit APValue(const APFloat &F) : Kind(Uninitialized) {
119    MakeFloat(); setFloat(F);
120  }
121  explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
122    MakeVector(); setVector(E, N);
123  }
124  APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
125    MakeComplexInt(); setComplexInt(R, I);
126  }
127  APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
128    MakeComplexFloat(); setComplexFloat(R, I);
129  }
130  APValue(const APValue &RHS) : Kind(Uninitialized) {
131    *this = RHS;
132  }
133  APValue(LValueBase B, const CharUnits &O, NoLValuePath N)
134      : Kind(Uninitialized) {
135    MakeLValue(); setLValue(B, O, N);
136  }
137  APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
138          bool OnePastTheEnd)
139      : Kind(Uninitialized) {
140    MakeLValue(); setLValue(B, O, Path, OnePastTheEnd);
141  }
142  APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
143    MakeArray(InitElts, Size);
144  }
145  APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
146    MakeStruct(B, M);
147  }
148  explicit APValue(const FieldDecl *D, const APValue &V = APValue())
149      : Kind(Uninitialized) {
150    MakeUnion(); setUnion(D, V);
151  }
152  APValue(const ValueDecl *Member, bool IsDerivedMember,
153          ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
154    MakeMemberPointer(Member, IsDerivedMember, Path);
155  }
156
157  ~APValue() {
158    MakeUninit();
159  }
160
161  ValueKind getKind() const { return Kind; }
162  bool isUninit() const { return Kind == Uninitialized; }
163  bool isInt() const { return Kind == Int; }
164  bool isFloat() const { return Kind == Float; }
165  bool isComplexInt() const { return Kind == ComplexInt; }
166  bool isComplexFloat() const { return Kind == ComplexFloat; }
167  bool isLValue() const { return Kind == LValue; }
168  bool isVector() const { return Kind == Vector; }
169  bool isArray() const { return Kind == Array; }
170  bool isStruct() const { return Kind == Struct; }
171  bool isUnion() const { return Kind == Union; }
172  bool isMemberPointer() const { return Kind == MemberPointer; }
173
174  void print(raw_ostream &OS) const;
175  void dump() const;
176
177  APSInt &getInt() {
178    assert(isInt() && "Invalid accessor");
179    return *(APSInt*)(char*)Data;
180  }
181  const APSInt &getInt() const {
182    return const_cast<APValue*>(this)->getInt();
183  }
184
185  APFloat &getFloat() {
186    assert(isFloat() && "Invalid accessor");
187    return *(APFloat*)(char*)Data;
188  }
189  const APFloat &getFloat() const {
190    return const_cast<APValue*>(this)->getFloat();
191  }
192
193  APSInt &getComplexIntReal() {
194    assert(isComplexInt() && "Invalid accessor");
195    return ((ComplexAPSInt*)(char*)Data)->Real;
196  }
197  const APSInt &getComplexIntReal() const {
198    return const_cast<APValue*>(this)->getComplexIntReal();
199  }
200
201  APSInt &getComplexIntImag() {
202    assert(isComplexInt() && "Invalid accessor");
203    return ((ComplexAPSInt*)(char*)Data)->Imag;
204  }
205  const APSInt &getComplexIntImag() const {
206    return const_cast<APValue*>(this)->getComplexIntImag();
207  }
208
209  APFloat &getComplexFloatReal() {
210    assert(isComplexFloat() && "Invalid accessor");
211    return ((ComplexAPFloat*)(char*)Data)->Real;
212  }
213  const APFloat &getComplexFloatReal() const {
214    return const_cast<APValue*>(this)->getComplexFloatReal();
215  }
216
217  APFloat &getComplexFloatImag() {
218    assert(isComplexFloat() && "Invalid accessor");
219    return ((ComplexAPFloat*)(char*)Data)->Imag;
220  }
221  const APFloat &getComplexFloatImag() const {
222    return const_cast<APValue*>(this)->getComplexFloatImag();
223  }
224
225  const LValueBase getLValueBase() const;
226  CharUnits &getLValueOffset();
227  const CharUnits &getLValueOffset() const {
228    return const_cast<APValue*>(this)->getLValueOffset();
229  }
230  bool isLValueOnePastTheEnd() const;
231  bool hasLValuePath() const;
232  ArrayRef<LValuePathEntry> getLValuePath() const;
233
234  APValue &getVectorElt(unsigned I) {
235    assert(isVector() && "Invalid accessor");
236    assert(I < getVectorLength() && "Index out of range");
237    return ((Vec*)(char*)Data)->Elts[I];
238  }
239  const APValue &getVectorElt(unsigned I) const {
240    return const_cast<APValue*>(this)->getVectorElt(I);
241  }
242  unsigned getVectorLength() const {
243    assert(isVector() && "Invalid accessor");
244    return ((const Vec*)(const void *)Data)->NumElts;
245  }
246
247  APValue &getArrayInitializedElt(unsigned I) {
248    assert(isArray() && "Invalid accessor");
249    assert(I < getArrayInitializedElts() && "Index out of range");
250    return ((Arr*)(char*)Data)->Elts[I];
251  }
252  const APValue &getArrayInitializedElt(unsigned I) const {
253    return const_cast<APValue*>(this)->getArrayInitializedElt(I);
254  }
255  bool hasArrayFiller() const {
256    return getArrayInitializedElts() != getArraySize();
257  }
258  APValue &getArrayFiller() {
259    assert(isArray() && "Invalid accessor");
260    assert(hasArrayFiller() && "No array filler");
261    return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()];
262  }
263  const APValue &getArrayFiller() const {
264    return const_cast<APValue*>(this)->getArrayFiller();
265  }
266  unsigned getArrayInitializedElts() const {
267    assert(isArray() && "Invalid accessor");
268    return ((const Arr*)(const void *)Data)->NumElts;
269  }
270  unsigned getArraySize() const {
271    assert(isArray() && "Invalid accessor");
272    return ((const Arr*)(const void *)Data)->ArrSize;
273  }
274
275  unsigned getStructNumBases() const {
276    assert(isStruct() && "Invalid accessor");
277    return ((const StructData*)(const char*)Data)->NumBases;
278  }
279  unsigned getStructNumFields() const {
280    assert(isStruct() && "Invalid accessor");
281    return ((const StructData*)(const char*)Data)->NumFields;
282  }
283  APValue &getStructBase(unsigned i) {
284    assert(isStruct() && "Invalid accessor");
285    return ((StructData*)(char*)Data)->Elts[i];
286  }
287  APValue &getStructField(unsigned i) {
288    assert(isStruct() && "Invalid accessor");
289    return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i];
290  }
291  const APValue &getStructBase(unsigned i) const {
292    return const_cast<APValue*>(this)->getStructBase(i);
293  }
294  const APValue &getStructField(unsigned i) const {
295    return const_cast<APValue*>(this)->getStructField(i);
296  }
297
298  const FieldDecl *getUnionField() const {
299    assert(isUnion() && "Invalid accessor");
300    return ((const UnionData*)(const char*)Data)->Field;
301  }
302  APValue &getUnionValue() {
303    assert(isUnion() && "Invalid accessor");
304    return *((UnionData*)(char*)Data)->Value;
305  }
306  const APValue &getUnionValue() const {
307    return const_cast<APValue*>(this)->getUnionValue();
308  }
309
310  const ValueDecl *getMemberPointerDecl() const;
311  bool isMemberPointerToDerivedMember() const;
312  ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
313
314  void setInt(const APSInt &I) {
315    assert(isInt() && "Invalid accessor");
316    *(APSInt*)(char*)Data = I;
317  }
318  void setFloat(const APFloat &F) {
319    assert(isFloat() && "Invalid accessor");
320    *(APFloat*)(char*)Data = F;
321  }
322  void setVector(const APValue *E, unsigned N) {
323    assert(isVector() && "Invalid accessor");
324    ((Vec*)(char*)Data)->Elts = new APValue[N];
325    ((Vec*)(char*)Data)->NumElts = N;
326    for (unsigned i = 0; i != N; ++i)
327      ((Vec*)(char*)Data)->Elts[i] = E[i];
328  }
329  void setComplexInt(const APSInt &R, const APSInt &I) {
330    assert(R.getBitWidth() == I.getBitWidth() &&
331           "Invalid complex int (type mismatch).");
332    assert(isComplexInt() && "Invalid accessor");
333    ((ComplexAPSInt*)(char*)Data)->Real = R;
334    ((ComplexAPSInt*)(char*)Data)->Imag = I;
335  }
336  void setComplexFloat(const APFloat &R, const APFloat &I) {
337    assert(&R.getSemantics() == &I.getSemantics() &&
338           "Invalid complex float (type mismatch).");
339    assert(isComplexFloat() && "Invalid accessor");
340    ((ComplexAPFloat*)(char*)Data)->Real = R;
341    ((ComplexAPFloat*)(char*)Data)->Imag = I;
342  }
343  void setLValue(LValueBase B, const CharUnits &O, NoLValuePath);
344  void setLValue(LValueBase B, const CharUnits &O,
345                 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd);
346  void setUnion(const FieldDecl *Field, const APValue &Value) {
347    assert(isUnion() && "Invalid accessor");
348    ((UnionData*)(char*)Data)->Field = Field;
349    *((UnionData*)(char*)Data)->Value = Value;
350  }
351
352  const APValue &operator=(const APValue &RHS);
353
354private:
355  void MakeUninit();
356  void MakeInt() {
357    assert(isUninit() && "Bad state change");
358    new ((void*)Data) APSInt(1);
359    Kind = Int;
360  }
361  void MakeFloat() {
362    assert(isUninit() && "Bad state change");
363    new ((void*)(char*)Data) APFloat(0.0);
364    Kind = Float;
365  }
366  void MakeVector() {
367    assert(isUninit() && "Bad state change");
368    new ((void*)(char*)Data) Vec();
369    Kind = Vector;
370  }
371  void MakeComplexInt() {
372    assert(isUninit() && "Bad state change");
373    new ((void*)(char*)Data) ComplexAPSInt();
374    Kind = ComplexInt;
375  }
376  void MakeComplexFloat() {
377    assert(isUninit() && "Bad state change");
378    new ((void*)(char*)Data) ComplexAPFloat();
379    Kind = ComplexFloat;
380  }
381  void MakeLValue();
382  void MakeArray(unsigned InitElts, unsigned Size);
383  void MakeStruct(unsigned B, unsigned M) {
384    assert(isUninit() && "Bad state change");
385    new ((void*)(char*)Data) StructData(B, M);
386    Kind = Struct;
387  }
388  void MakeUnion() {
389    assert(isUninit() && "Bad state change");
390    new ((void*)(char*)Data) UnionData();
391    Kind = Union;
392  }
393  void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
394                         ArrayRef<const CXXRecordDecl*> Path);
395};
396
397inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) {
398  V.print(OS);
399  return OS;
400}
401
402// Writes a concise representation of V to DB, in a single << operation.
403const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
404                                    const APValue &V);
405
406} // end namespace clang.
407
408#endif
409