APValue.h revision 8cc488fefb2fb04bc8d5398da29f0182f97934cf
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
21namespace clang {
22  class CharUnits;
23  class DiagnosticBuilder;
24  class Expr;
25
26/// APValue - This class implements a discriminated union of [uninitialized]
27/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset].
28class APValue {
29  typedef llvm::APSInt APSInt;
30  typedef llvm::APFloat APFloat;
31public:
32  enum ValueKind {
33    Uninitialized,
34    Int,
35    Float,
36    ComplexInt,
37    ComplexFloat,
38    LValue,
39    Vector
40  };
41private:
42  ValueKind Kind;
43
44  struct ComplexAPSInt {
45    APSInt Real, Imag;
46    ComplexAPSInt() : Real(1), Imag(1) {}
47  };
48  struct ComplexAPFloat {
49    APFloat Real, Imag;
50    ComplexAPFloat() : Real(0.0), Imag(0.0) {}
51  };
52
53  struct Vec {
54    APValue *Elts;
55    unsigned NumElts;
56    Vec() : Elts(0), NumElts(0) {}
57    ~Vec() { delete[] Elts; }
58  };
59
60  enum {
61    MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
62               sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
63  };
64
65  union {
66    void *Aligner;
67    char Data[MaxSize];
68  };
69
70public:
71  APValue() : Kind(Uninitialized) {}
72  explicit APValue(const APSInt &I) : Kind(Uninitialized) {
73    MakeInt(); setInt(I);
74  }
75  explicit APValue(const APFloat &F) : Kind(Uninitialized) {
76    MakeFloat(); setFloat(F);
77  }
78  explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
79    MakeVector(); setVector(E, N);
80  }
81  APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
82    MakeComplexInt(); setComplexInt(R, I);
83  }
84  APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
85    MakeComplexFloat(); setComplexFloat(R, I);
86  }
87  APValue(const APValue &RHS) : Kind(Uninitialized) {
88    *this = RHS;
89  }
90  APValue(const Expr* B, const CharUnits &O) : Kind(Uninitialized) {
91    MakeLValue(); setLValue(B, O);
92  }
93  APValue(const Expr* B);
94
95  ~APValue() {
96    MakeUninit();
97  }
98
99  ValueKind getKind() const { return Kind; }
100  bool isUninit() const { return Kind == Uninitialized; }
101  bool isInt() const { return Kind == Int; }
102  bool isFloat() const { return Kind == Float; }
103  bool isComplexInt() const { return Kind == ComplexInt; }
104  bool isComplexFloat() const { return Kind == ComplexFloat; }
105  bool isLValue() const { return Kind == LValue; }
106  bool isVector() const { return Kind == Vector; }
107
108  void print(raw_ostream &OS) const;
109  void dump() const;
110
111  APSInt &getInt() {
112    assert(isInt() && "Invalid accessor");
113    return *(APSInt*)(char*)Data;
114  }
115  const APSInt &getInt() const {
116    return const_cast<APValue*>(this)->getInt();
117  }
118
119  APFloat &getFloat() {
120    assert(isFloat() && "Invalid accessor");
121    return *(APFloat*)(char*)Data;
122  }
123  const APFloat &getFloat() const {
124    return const_cast<APValue*>(this)->getFloat();
125  }
126
127  APValue &getVectorElt(unsigned i) {
128    assert(isVector() && "Invalid accessor");
129    return ((Vec*)(char*)Data)->Elts[i];
130  }
131  const APValue &getVectorElt(unsigned i) const {
132    assert(isVector() && "Invalid accessor");
133    return ((const Vec*)(const char*)Data)->Elts[i];
134  }
135  unsigned getVectorLength() const {
136    assert(isVector() && "Invalid accessor");
137    return ((const Vec*)(const void *)Data)->NumElts;
138  }
139
140  APSInt &getComplexIntReal() {
141    assert(isComplexInt() && "Invalid accessor");
142    return ((ComplexAPSInt*)(char*)Data)->Real;
143  }
144  const APSInt &getComplexIntReal() const {
145    return const_cast<APValue*>(this)->getComplexIntReal();
146  }
147
148  APSInt &getComplexIntImag() {
149    assert(isComplexInt() && "Invalid accessor");
150    return ((ComplexAPSInt*)(char*)Data)->Imag;
151  }
152  const APSInt &getComplexIntImag() const {
153    return const_cast<APValue*>(this)->getComplexIntImag();
154  }
155
156  APFloat &getComplexFloatReal() {
157    assert(isComplexFloat() && "Invalid accessor");
158    return ((ComplexAPFloat*)(char*)Data)->Real;
159  }
160  const APFloat &getComplexFloatReal() const {
161    return const_cast<APValue*>(this)->getComplexFloatReal();
162  }
163
164  APFloat &getComplexFloatImag() {
165    assert(isComplexFloat() && "Invalid accessor");
166    return ((ComplexAPFloat*)(char*)Data)->Imag;
167  }
168  const APFloat &getComplexFloatImag() const {
169    return const_cast<APValue*>(this)->getComplexFloatImag();
170  }
171
172  const Expr* getLValueBase() const;
173  CharUnits getLValueOffset() const;
174
175  void setInt(const APSInt &I) {
176    assert(isInt() && "Invalid accessor");
177    *(APSInt*)(char*)Data = I;
178  }
179  void setFloat(const APFloat &F) {
180    assert(isFloat() && "Invalid accessor");
181    *(APFloat*)(char*)Data = F;
182  }
183  void setVector(const APValue *E, unsigned N) {
184    assert(isVector() && "Invalid accessor");
185    ((Vec*)(char*)Data)->Elts = new APValue[N];
186    ((Vec*)(char*)Data)->NumElts = N;
187    for (unsigned i = 0; i != N; ++i)
188      ((Vec*)(char*)Data)->Elts[i] = E[i];
189  }
190  void setComplexInt(const APSInt &R, const APSInt &I) {
191    assert(R.getBitWidth() == I.getBitWidth() &&
192           "Invalid complex int (type mismatch).");
193    assert(isComplexInt() && "Invalid accessor");
194    ((ComplexAPSInt*)(char*)Data)->Real = R;
195    ((ComplexAPSInt*)(char*)Data)->Imag = I;
196  }
197  void setComplexFloat(const APFloat &R, const APFloat &I) {
198    assert(&R.getSemantics() == &I.getSemantics() &&
199           "Invalid complex float (type mismatch).");
200    assert(isComplexFloat() && "Invalid accessor");
201    ((ComplexAPFloat*)(char*)Data)->Real = R;
202    ((ComplexAPFloat*)(char*)Data)->Imag = I;
203  }
204  void setLValue(const Expr *B, const CharUnits &O);
205
206  const APValue &operator=(const APValue &RHS);
207
208private:
209  void MakeUninit();
210  void MakeInt() {
211    assert(isUninit() && "Bad state change");
212    new ((void*)Data) APSInt(1);
213    Kind = Int;
214  }
215  void MakeFloat() {
216    assert(isUninit() && "Bad state change");
217    new ((void*)(char*)Data) APFloat(0.0);
218    Kind = Float;
219  }
220  void MakeVector() {
221    assert(isUninit() && "Bad state change");
222    new ((void*)(char*)Data) Vec();
223    Kind = Vector;
224  }
225  void MakeComplexInt() {
226    assert(isUninit() && "Bad state change");
227    new ((void*)(char*)Data) ComplexAPSInt();
228    Kind = ComplexInt;
229  }
230  void MakeComplexFloat() {
231    assert(isUninit() && "Bad state change");
232    new ((void*)(char*)Data) ComplexAPFloat();
233    Kind = ComplexFloat;
234  }
235  void MakeLValue();
236};
237
238inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) {
239  V.print(OS);
240  return OS;
241}
242
243// Writes a concise representation of V to DB, in a single << operation.
244const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
245                                    const APValue &V);
246
247} // end namespace clang.
248
249#endif
250