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/APFloat.h"
19#include "llvm/ADT/APSInt.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(nullptr), 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  // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
112  typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
113                                      ComplexAPFloat, Vec, Arr, StructData,
114                                      UnionData, AddrLabelDiffData> DataType;
115  static const size_t DataSize = sizeof(DataType);
116
117  DataType Data;
118
119public:
120  APValue() : Kind(Uninitialized) {}
121  explicit APValue(APSInt I) : Kind(Uninitialized) {
122    MakeInt(); setInt(std::move(I));
123  }
124  explicit APValue(APFloat F) : Kind(Uninitialized) {
125    MakeFloat(); setFloat(std::move(F));
126  }
127  explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
128    MakeVector(); setVector(E, N);
129  }
130  APValue(APSInt R, APSInt I) : Kind(Uninitialized) {
131    MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
132  }
133  APValue(APFloat R, APFloat I) : Kind(Uninitialized) {
134    MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
135  }
136  APValue(const APValue &RHS);
137  APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); }
138  APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex)
139      : Kind(Uninitialized) {
140    MakeLValue(); setLValue(B, O, N, CallIndex);
141  }
142  APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
143          bool OnePastTheEnd, unsigned CallIndex)
144      : Kind(Uninitialized) {
145    MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex);
146  }
147  APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
148    MakeArray(InitElts, Size);
149  }
150  APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
151    MakeStruct(B, M);
152  }
153  explicit APValue(const FieldDecl *D, const APValue &V = APValue())
154      : Kind(Uninitialized) {
155    MakeUnion(); setUnion(D, V);
156  }
157  APValue(const ValueDecl *Member, bool IsDerivedMember,
158          ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
159    MakeMemberPointer(Member, IsDerivedMember, Path);
160  }
161  APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
162      : Kind(Uninitialized) {
163    MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
164  }
165
166  ~APValue() {
167    MakeUninit();
168  }
169
170  /// \brief Returns whether the object performed allocations.
171  ///
172  /// If APValues are constructed via placement new, \c needsCleanup()
173  /// indicates whether the destructor must be called in order to correctly
174  /// free all allocated memory.
175  bool needsCleanup() const;
176
177  /// \brief Swaps the contents of this and the given APValue.
178  void swap(APValue &RHS);
179
180  ValueKind getKind() const { return Kind; }
181  bool isUninit() const { return Kind == Uninitialized; }
182  bool isInt() const { return Kind == Int; }
183  bool isFloat() const { return Kind == Float; }
184  bool isComplexInt() const { return Kind == ComplexInt; }
185  bool isComplexFloat() const { return Kind == ComplexFloat; }
186  bool isLValue() const { return Kind == LValue; }
187  bool isVector() const { return Kind == Vector; }
188  bool isArray() const { return Kind == Array; }
189  bool isStruct() const { return Kind == Struct; }
190  bool isUnion() const { return Kind == Union; }
191  bool isMemberPointer() const { return Kind == MemberPointer; }
192  bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
193
194  void dump() const;
195  void dump(raw_ostream &OS) const;
196
197  void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
198  std::string getAsString(ASTContext &Ctx, QualType Ty) const;
199
200  APSInt &getInt() {
201    assert(isInt() && "Invalid accessor");
202    return *(APSInt*)(char*)Data.buffer;
203  }
204  const APSInt &getInt() const {
205    return const_cast<APValue*>(this)->getInt();
206  }
207
208  APFloat &getFloat() {
209    assert(isFloat() && "Invalid accessor");
210    return *(APFloat*)(char*)Data.buffer;
211  }
212  const APFloat &getFloat() const {
213    return const_cast<APValue*>(this)->getFloat();
214  }
215
216  APSInt &getComplexIntReal() {
217    assert(isComplexInt() && "Invalid accessor");
218    return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
219  }
220  const APSInt &getComplexIntReal() const {
221    return const_cast<APValue*>(this)->getComplexIntReal();
222  }
223
224  APSInt &getComplexIntImag() {
225    assert(isComplexInt() && "Invalid accessor");
226    return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
227  }
228  const APSInt &getComplexIntImag() const {
229    return const_cast<APValue*>(this)->getComplexIntImag();
230  }
231
232  APFloat &getComplexFloatReal() {
233    assert(isComplexFloat() && "Invalid accessor");
234    return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
235  }
236  const APFloat &getComplexFloatReal() const {
237    return const_cast<APValue*>(this)->getComplexFloatReal();
238  }
239
240  APFloat &getComplexFloatImag() {
241    assert(isComplexFloat() && "Invalid accessor");
242    return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
243  }
244  const APFloat &getComplexFloatImag() const {
245    return const_cast<APValue*>(this)->getComplexFloatImag();
246  }
247
248  const LValueBase getLValueBase() const;
249  CharUnits &getLValueOffset();
250  const CharUnits &getLValueOffset() const {
251    return const_cast<APValue*>(this)->getLValueOffset();
252  }
253  bool isLValueOnePastTheEnd() const;
254  bool hasLValuePath() const;
255  ArrayRef<LValuePathEntry> getLValuePath() const;
256  unsigned getLValueCallIndex() const;
257
258  APValue &getVectorElt(unsigned I) {
259    assert(isVector() && "Invalid accessor");
260    assert(I < getVectorLength() && "Index out of range");
261    return ((Vec*)(char*)Data.buffer)->Elts[I];
262  }
263  const APValue &getVectorElt(unsigned I) const {
264    return const_cast<APValue*>(this)->getVectorElt(I);
265  }
266  unsigned getVectorLength() const {
267    assert(isVector() && "Invalid accessor");
268    return ((const Vec*)(const void *)Data.buffer)->NumElts;
269  }
270
271  APValue &getArrayInitializedElt(unsigned I) {
272    assert(isArray() && "Invalid accessor");
273    assert(I < getArrayInitializedElts() && "Index out of range");
274    return ((Arr*)(char*)Data.buffer)->Elts[I];
275  }
276  const APValue &getArrayInitializedElt(unsigned I) const {
277    return const_cast<APValue*>(this)->getArrayInitializedElt(I);
278  }
279  bool hasArrayFiller() const {
280    return getArrayInitializedElts() != getArraySize();
281  }
282  APValue &getArrayFiller() {
283    assert(isArray() && "Invalid accessor");
284    assert(hasArrayFiller() && "No array filler");
285    return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
286  }
287  const APValue &getArrayFiller() const {
288    return const_cast<APValue*>(this)->getArrayFiller();
289  }
290  unsigned getArrayInitializedElts() const {
291    assert(isArray() && "Invalid accessor");
292    return ((const Arr*)(const void *)Data.buffer)->NumElts;
293  }
294  unsigned getArraySize() const {
295    assert(isArray() && "Invalid accessor");
296    return ((const Arr*)(const void *)Data.buffer)->ArrSize;
297  }
298
299  unsigned getStructNumBases() const {
300    assert(isStruct() && "Invalid accessor");
301    return ((const StructData*)(const char*)Data.buffer)->NumBases;
302  }
303  unsigned getStructNumFields() const {
304    assert(isStruct() && "Invalid accessor");
305    return ((const StructData*)(const char*)Data.buffer)->NumFields;
306  }
307  APValue &getStructBase(unsigned i) {
308    assert(isStruct() && "Invalid accessor");
309    return ((StructData*)(char*)Data.buffer)->Elts[i];
310  }
311  APValue &getStructField(unsigned i) {
312    assert(isStruct() && "Invalid accessor");
313    return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
314  }
315  const APValue &getStructBase(unsigned i) const {
316    return const_cast<APValue*>(this)->getStructBase(i);
317  }
318  const APValue &getStructField(unsigned i) const {
319    return const_cast<APValue*>(this)->getStructField(i);
320  }
321
322  const FieldDecl *getUnionField() const {
323    assert(isUnion() && "Invalid accessor");
324    return ((const UnionData*)(const char*)Data.buffer)->Field;
325  }
326  APValue &getUnionValue() {
327    assert(isUnion() && "Invalid accessor");
328    return *((UnionData*)(char*)Data.buffer)->Value;
329  }
330  const APValue &getUnionValue() const {
331    return const_cast<APValue*>(this)->getUnionValue();
332  }
333
334  const ValueDecl *getMemberPointerDecl() const;
335  bool isMemberPointerToDerivedMember() const;
336  ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
337
338  const AddrLabelExpr* getAddrLabelDiffLHS() const {
339    assert(isAddrLabelDiff() && "Invalid accessor");
340    return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
341  }
342  const AddrLabelExpr* getAddrLabelDiffRHS() const {
343    assert(isAddrLabelDiff() && "Invalid accessor");
344    return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
345  }
346
347  void setInt(APSInt I) {
348    assert(isInt() && "Invalid accessor");
349    *(APSInt *)(char *)Data.buffer = std::move(I);
350  }
351  void setFloat(APFloat F) {
352    assert(isFloat() && "Invalid accessor");
353    *(APFloat *)(char *)Data.buffer = std::move(F);
354  }
355  void setVector(const APValue *E, unsigned N) {
356    assert(isVector() && "Invalid accessor");
357    ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
358    ((Vec*)(char*)Data.buffer)->NumElts = N;
359    for (unsigned i = 0; i != N; ++i)
360      ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
361  }
362  void setComplexInt(APSInt R, APSInt I) {
363    assert(R.getBitWidth() == I.getBitWidth() &&
364           "Invalid complex int (type mismatch).");
365    assert(isComplexInt() && "Invalid accessor");
366    ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
367    ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
368  }
369  void setComplexFloat(APFloat R, APFloat I) {
370    assert(&R.getSemantics() == &I.getSemantics() &&
371           "Invalid complex float (type mismatch).");
372    assert(isComplexFloat() && "Invalid accessor");
373    ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
374    ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
375  }
376  void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
377                 unsigned CallIndex);
378  void setLValue(LValueBase B, const CharUnits &O,
379                 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
380                 unsigned CallIndex);
381  void setUnion(const FieldDecl *Field, const APValue &Value) {
382    assert(isUnion() && "Invalid accessor");
383    ((UnionData*)(char*)Data.buffer)->Field = Field;
384    *((UnionData*)(char*)Data.buffer)->Value = Value;
385  }
386  void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
387                        const AddrLabelExpr* RHSExpr) {
388    ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
389    ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
390  }
391
392  /// Assign by swapping from a copy of the RHS.
393  APValue &operator=(APValue RHS) {
394    swap(RHS);
395    return *this;
396  }
397
398private:
399  void DestroyDataAndMakeUninit();
400  void MakeUninit() {
401    if (Kind != Uninitialized)
402      DestroyDataAndMakeUninit();
403  }
404  void MakeInt() {
405    assert(isUninit() && "Bad state change");
406    new ((void*)Data.buffer) APSInt(1);
407    Kind = Int;
408  }
409  void MakeFloat() {
410    assert(isUninit() && "Bad state change");
411    new ((void*)(char*)Data.buffer) APFloat(0.0);
412    Kind = Float;
413  }
414  void MakeVector() {
415    assert(isUninit() && "Bad state change");
416    new ((void*)(char*)Data.buffer) Vec();
417    Kind = Vector;
418  }
419  void MakeComplexInt() {
420    assert(isUninit() && "Bad state change");
421    new ((void*)(char*)Data.buffer) ComplexAPSInt();
422    Kind = ComplexInt;
423  }
424  void MakeComplexFloat() {
425    assert(isUninit() && "Bad state change");
426    new ((void*)(char*)Data.buffer) ComplexAPFloat();
427    Kind = ComplexFloat;
428  }
429  void MakeLValue();
430  void MakeArray(unsigned InitElts, unsigned Size);
431  void MakeStruct(unsigned B, unsigned M) {
432    assert(isUninit() && "Bad state change");
433    new ((void*)(char*)Data.buffer) StructData(B, M);
434    Kind = Struct;
435  }
436  void MakeUnion() {
437    assert(isUninit() && "Bad state change");
438    new ((void*)(char*)Data.buffer) UnionData();
439    Kind = Union;
440  }
441  void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
442                         ArrayRef<const CXXRecordDecl*> Path);
443  void MakeAddrLabelDiff() {
444    assert(isUninit() && "Bad state change");
445    new ((void*)(char*)Data.buffer) AddrLabelDiffData();
446    Kind = AddrLabelDiff;
447  }
448};
449
450} // end namespace clang.
451
452#endif
453