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