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