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