1193326Sed//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
2193326Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193326Sed//
7193326Sed//===----------------------------------------------------------------------===//
8193326Sed//
9193326Sed//  This file defines the APValue class.
10193326Sed//
11193326Sed//===----------------------------------------------------------------------===//
12193326Sed
13193326Sed#ifndef LLVM_CLANG_AST_APVALUE_H
14193326Sed#define LLVM_CLANG_AST_APVALUE_H
15193326Sed
16353358Sdim#include "clang/Basic/FixedPoint.h"
17226633Sdim#include "clang/Basic/LLVM.h"
18249423Sdim#include "llvm/ADT/APFloat.h"
19193326Sed#include "llvm/ADT/APSInt.h"
20234353Sdim#include "llvm/ADT/PointerIntPair.h"
21234353Sdim#include "llvm/ADT/PointerUnion.h"
22193326Sed
23193326Sednamespace clang {
24234353Sdim  class AddrLabelExpr;
25234353Sdim  class ASTContext;
26202379Srdivacky  class CharUnits;
27353358Sdim  class CXXRecordDecl;
28353358Sdim  class Decl;
29226633Sdim  class DiagnosticBuilder;
30193326Sed  class Expr;
31234353Sdim  class FieldDecl;
32353358Sdim  struct PrintingPolicy;
33353358Sdim  class Type;
34234353Sdim  class ValueDecl;
35193326Sed
36353358Sdim/// Symbolic representation of typeid(T) for some type T.
37353358Sdimclass TypeInfoLValue {
38353358Sdim  const Type *T;
39353358Sdim
40353358Sdimpublic:
41353358Sdim  TypeInfoLValue() : T() {}
42353358Sdim  explicit TypeInfoLValue(const Type *T);
43353358Sdim
44353358Sdim  const Type *getType() const { return T; }
45353358Sdim  explicit operator bool() const { return T; }
46353358Sdim
47353358Sdim  void *getOpaqueValue() { return const_cast<Type*>(T); }
48353358Sdim  static TypeInfoLValue getFromOpaqueValue(void *Value) {
49353358Sdim    TypeInfoLValue V;
50353358Sdim    V.T = reinterpret_cast<const Type*>(Value);
51353358Sdim    return V;
52353358Sdim  }
53353358Sdim
54353358Sdim  void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
55353358Sdim};
56360784Sdim
57360784Sdim/// Symbolic representation of a dynamic allocation.
58360784Sdimclass DynamicAllocLValue {
59360784Sdim  unsigned Index;
60360784Sdim
61360784Sdimpublic:
62360784Sdim  DynamicAllocLValue() : Index(0) {}
63360784Sdim  explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
64360784Sdim  unsigned getIndex() { return Index - 1; }
65360784Sdim
66360784Sdim  explicit operator bool() const { return Index != 0; }
67360784Sdim
68360784Sdim  void *getOpaqueValue() {
69360784Sdim    return reinterpret_cast<void *>(static_cast<uintptr_t>(Index)
70360784Sdim                                    << NumLowBitsAvailable);
71360784Sdim  }
72360784Sdim  static DynamicAllocLValue getFromOpaqueValue(void *Value) {
73360784Sdim    DynamicAllocLValue V;
74360784Sdim    V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
75360784Sdim    return V;
76360784Sdim  }
77360784Sdim
78360784Sdim  static unsigned getMaxIndex() {
79360784Sdim    return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
80360784Sdim  }
81360784Sdim
82360784Sdim  static constexpr int NumLowBitsAvailable = 3;
83360784Sdim};
84353358Sdim}
85353358Sdim
86353358Sdimnamespace llvm {
87353358Sdimtemplate<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
88353358Sdim  static void *getAsVoidPointer(clang::TypeInfoLValue V) {
89353358Sdim    return V.getOpaqueValue();
90353358Sdim  }
91353358Sdim  static clang::TypeInfoLValue getFromVoidPointer(void *P) {
92353358Sdim    return clang::TypeInfoLValue::getFromOpaqueValue(P);
93353358Sdim  }
94353358Sdim  // Validated by static_assert in APValue.cpp; hardcoded to avoid needing
95353358Sdim  // to include Type.h.
96353358Sdim  static constexpr int NumLowBitsAvailable = 3;
97353358Sdim};
98360784Sdim
99360784Sdimtemplate<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
100360784Sdim  static void *getAsVoidPointer(clang::DynamicAllocLValue V) {
101360784Sdim    return V.getOpaqueValue();
102360784Sdim  }
103360784Sdim  static clang::DynamicAllocLValue getFromVoidPointer(void *P) {
104360784Sdim    return clang::DynamicAllocLValue::getFromOpaqueValue(P);
105360784Sdim  }
106360784Sdim  static constexpr int NumLowBitsAvailable =
107360784Sdim      clang::DynamicAllocLValue::NumLowBitsAvailable;
108360784Sdim};
109353358Sdim}
110353358Sdim
111353358Sdimnamespace clang {
112193326Sed/// APValue - This class implements a discriminated union of [uninitialized]
113234353Sdim/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
114234353Sdim/// [Vector: N * APValue], [Array: N * APValue]
115193326Sedclass APValue {
116193326Sed  typedef llvm::APSInt APSInt;
117193326Sed  typedef llvm::APFloat APFloat;
118193326Sedpublic:
119193326Sed  enum ValueKind {
120353358Sdim    /// There is no such object (it's outside its lifetime).
121353358Sdim    None,
122353358Sdim    /// This object has an indeterminate value (C++ [basic.indet]).
123353358Sdim    Indeterminate,
124193326Sed    Int,
125193326Sed    Float,
126353358Sdim    FixedPoint,
127193326Sed    ComplexInt,
128193326Sed    ComplexFloat,
129193326Sed    LValue,
130234353Sdim    Vector,
131234353Sdim    Array,
132234353Sdim    Struct,
133234353Sdim    Union,
134234353Sdim    MemberPointer,
135234353Sdim    AddrLabelDiff
136193326Sed  };
137341825Sdim
138341825Sdim  class LValueBase {
139360784Sdim    typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
140360784Sdim                               DynamicAllocLValue>
141353358Sdim        PtrTy;
142353358Sdim
143341825Sdim  public:
144353358Sdim    LValueBase() : Local{} {}
145353358Sdim    LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
146353358Sdim    LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
147360784Sdim    static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
148353358Sdim    static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
149341825Sdim
150341825Sdim    template <class T>
151341825Sdim    bool is() const { return Ptr.is<T>(); }
152341825Sdim
153341825Sdim    template <class T>
154341825Sdim    T get() const { return Ptr.get<T>(); }
155341825Sdim
156341825Sdim    template <class T>
157341825Sdim    T dyn_cast() const { return Ptr.dyn_cast<T>(); }
158341825Sdim
159341825Sdim    void *getOpaqueValue() const;
160341825Sdim
161341825Sdim    bool isNull() const;
162341825Sdim
163353358Sdim    explicit operator bool() const;
164341825Sdim
165353358Sdim    unsigned getCallIndex() const;
166353358Sdim    unsigned getVersion() const;
167353358Sdim    QualType getTypeInfoType() const;
168360784Sdim    QualType getDynamicAllocType() const;
169341825Sdim
170353358Sdim    friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
171353358Sdim    friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
172353358Sdim      return !(LHS == RHS);
173341825Sdim    }
174353358Sdim    friend llvm::hash_code hash_value(const LValueBase &Base);
175341825Sdim
176353358Sdim  private:
177353358Sdim    PtrTy Ptr;
178353358Sdim    struct LocalState {
179353358Sdim      unsigned CallIndex, Version;
180353358Sdim    };
181353358Sdim    union {
182353358Sdim      LocalState Local;
183353358Sdim      /// The type std::type_info, if this is a TypeInfoLValue.
184353358Sdim      void *TypeInfoType;
185360784Sdim      /// The QualType, if this is a DynamicAllocLValue.
186360784Sdim      void *DynamicAllocType;
187353358Sdim    };
188353358Sdim  };
189353358Sdim
190353358Sdim  /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we
191353358Sdim  /// mean a virtual or non-virtual base class subobject.
192353358Sdim  typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
193353358Sdim
194353358Sdim  /// A non-discriminated union of a base, field, or array index.
195353358Sdim  class LValuePathEntry {
196353358Sdim    static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
197353358Sdim                  "pointer doesn't fit in 64 bits?");
198353358Sdim    uint64_t Value;
199353358Sdim
200353358Sdim  public:
201353358Sdim    LValuePathEntry() : Value() {}
202353358Sdim    LValuePathEntry(BaseOrMemberType BaseOrMember)
203353358Sdim        : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
204353358Sdim    static LValuePathEntry ArrayIndex(uint64_t Index) {
205353358Sdim      LValuePathEntry Result;
206353358Sdim      Result.Value = Index;
207353358Sdim      return Result;
208341825Sdim    }
209341825Sdim
210353358Sdim    BaseOrMemberType getAsBaseOrMember() const {
211353358Sdim      return BaseOrMemberType::getFromOpaqueValue(
212353358Sdim          reinterpret_cast<void *>(Value));
213341825Sdim    }
214353358Sdim    uint64_t getAsArrayIndex() const { return Value; }
215341825Sdim
216353358Sdim    friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
217353358Sdim      return A.Value == B.Value;
218341825Sdim    }
219353358Sdim    friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
220353358Sdim      return A.Value != B.Value;
221353358Sdim    }
222353358Sdim    friend llvm::hash_code hash_value(LValuePathEntry A) {
223353358Sdim      return llvm::hash_value(A.Value);
224353358Sdim    }
225341825Sdim  };
226234353Sdim  struct NoLValuePath {};
227234353Sdim  struct UninitArray {};
228234353Sdim  struct UninitStruct {};
229353358Sdim
230353358Sdim  friend class ASTReader;
231353358Sdim  friend class ASTWriter;
232353358Sdim
233193326Sedprivate:
234193326Sed  ValueKind Kind;
235198092Srdivacky
236198092Srdivacky  struct ComplexAPSInt {
237198092Srdivacky    APSInt Real, Imag;
238193326Sed    ComplexAPSInt() : Real(1), Imag(1) {}
239193326Sed  };
240193326Sed  struct ComplexAPFloat {
241193326Sed    APFloat Real, Imag;
242193326Sed    ComplexAPFloat() : Real(0.0), Imag(0.0) {}
243193326Sed  };
244234353Sdim  struct LV;
245193326Sed  struct Vec {
246193326Sed    APValue *Elts;
247193326Sed    unsigned NumElts;
248276479Sdim    Vec() : Elts(nullptr), NumElts(0) {}
249193326Sed    ~Vec() { delete[] Elts; }
250193326Sed  };
251234353Sdim  struct Arr {
252234353Sdim    APValue *Elts;
253234353Sdim    unsigned NumElts, ArrSize;
254234353Sdim    Arr(unsigned NumElts, unsigned ArrSize);
255234353Sdim    ~Arr();
256234353Sdim  };
257234353Sdim  struct StructData {
258234353Sdim    APValue *Elts;
259234353Sdim    unsigned NumBases;
260234353Sdim    unsigned NumFields;
261234353Sdim    StructData(unsigned NumBases, unsigned NumFields);
262234353Sdim    ~StructData();
263234353Sdim  };
264234353Sdim  struct UnionData {
265234353Sdim    const FieldDecl *Field;
266234353Sdim    APValue *Value;
267234353Sdim    UnionData();
268234353Sdim    ~UnionData();
269234353Sdim  };
270234353Sdim  struct AddrLabelDiffData {
271234353Sdim    const AddrLabelExpr* LHSExpr;
272234353Sdim    const AddrLabelExpr* RHSExpr;
273234353Sdim  };
274234353Sdim  struct MemberPointerData;
275198092Srdivacky
276276479Sdim  // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
277276479Sdim  typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
278276479Sdim                                      ComplexAPFloat, Vec, Arr, StructData,
279276479Sdim                                      UnionData, AddrLabelDiffData> DataType;
280276479Sdim  static const size_t DataSize = sizeof(DataType);
281198092Srdivacky
282276479Sdim  DataType Data;
283198092Srdivacky
284193326Sedpublic:
285353358Sdim  APValue() : Kind(None) {}
286353358Sdim  explicit APValue(APSInt I) : Kind(None) {
287276479Sdim    MakeInt(); setInt(std::move(I));
288193326Sed  }
289353358Sdim  explicit APValue(APFloat F) : Kind(None) {
290276479Sdim    MakeFloat(); setFloat(std::move(F));
291193326Sed  }
292353358Sdim  explicit APValue(APFixedPoint FX) : Kind(None) {
293353358Sdim    MakeFixedPoint(std::move(FX));
294353358Sdim  }
295353358Sdim  explicit APValue(const APValue *E, unsigned N) : Kind(None) {
296193326Sed    MakeVector(); setVector(E, N);
297193326Sed  }
298353358Sdim  APValue(APSInt R, APSInt I) : Kind(None) {
299276479Sdim    MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
300193326Sed  }
301353358Sdim  APValue(APFloat R, APFloat I) : Kind(None) {
302276479Sdim    MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
303193326Sed  }
304234353Sdim  APValue(const APValue &RHS);
305353358Sdim  APValue(APValue &&RHS) : Kind(None) { swap(RHS); }
306341825Sdim  APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
307314564Sdim          bool IsNullPtr = false)
308353358Sdim      : Kind(None) {
309341825Sdim    MakeLValue(); setLValue(B, O, N, IsNullPtr);
310193326Sed  }
311234353Sdim  APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
312341825Sdim          bool OnePastTheEnd, bool IsNullPtr = false)
313353358Sdim      : Kind(None) {
314341825Sdim    MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
315193326Sed  }
316353358Sdim  APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) {
317234353Sdim    MakeArray(InitElts, Size);
318234353Sdim  }
319353358Sdim  APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) {
320234353Sdim    MakeStruct(B, M);
321234353Sdim  }
322234353Sdim  explicit APValue(const FieldDecl *D, const APValue &V = APValue())
323353358Sdim      : Kind(None) {
324234353Sdim    MakeUnion(); setUnion(D, V);
325234353Sdim  }
326234353Sdim  APValue(const ValueDecl *Member, bool IsDerivedMember,
327353358Sdim          ArrayRef<const CXXRecordDecl*> Path) : Kind(None) {
328234353Sdim    MakeMemberPointer(Member, IsDerivedMember, Path);
329234353Sdim  }
330234353Sdim  APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
331353358Sdim      : Kind(None) {
332234353Sdim    MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
333234353Sdim  }
334353358Sdim  static APValue IndeterminateValue() {
335353358Sdim    APValue Result;
336353358Sdim    Result.Kind = Indeterminate;
337353358Sdim    return Result;
338353358Sdim  }
339202379Srdivacky
340193326Sed  ~APValue() {
341353358Sdim    if (Kind != None && Kind != Indeterminate)
342353358Sdim      DestroyDataAndMakeUninit();
343193326Sed  }
344198092Srdivacky
345341825Sdim  /// Returns whether the object performed allocations.
346261991Sdim  ///
347261991Sdim  /// If APValues are constructed via placement new, \c needsCleanup()
348261991Sdim  /// indicates whether the destructor must be called in order to correctly
349261991Sdim  /// free all allocated memory.
350261991Sdim  bool needsCleanup() const;
351261991Sdim
352341825Sdim  /// Swaps the contents of this and the given APValue.
353234353Sdim  void swap(APValue &RHS);
354234353Sdim
355193326Sed  ValueKind getKind() const { return Kind; }
356353358Sdim
357353358Sdim  bool isAbsent() const { return Kind == None; }
358353358Sdim  bool isIndeterminate() const { return Kind == Indeterminate; }
359353358Sdim  bool hasValue() const { return Kind != None && Kind != Indeterminate; }
360353358Sdim
361193326Sed  bool isInt() const { return Kind == Int; }
362193326Sed  bool isFloat() const { return Kind == Float; }
363353358Sdim  bool isFixedPoint() const { return Kind == FixedPoint; }
364193326Sed  bool isComplexInt() const { return Kind == ComplexInt; }
365193326Sed  bool isComplexFloat() const { return Kind == ComplexFloat; }
366193326Sed  bool isLValue() const { return Kind == LValue; }
367193326Sed  bool isVector() const { return Kind == Vector; }
368234353Sdim  bool isArray() const { return Kind == Array; }
369234353Sdim  bool isStruct() const { return Kind == Struct; }
370234353Sdim  bool isUnion() const { return Kind == Union; }
371234353Sdim  bool isMemberPointer() const { return Kind == MemberPointer; }
372234353Sdim  bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
373198092Srdivacky
374193326Sed  void dump() const;
375234353Sdim  void dump(raw_ostream &OS) const;
376198092Srdivacky
377353358Sdim  void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
378353358Sdim  std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
379234353Sdim
380193326Sed  APSInt &getInt() {
381193326Sed    assert(isInt() && "Invalid accessor");
382276479Sdim    return *(APSInt*)(char*)Data.buffer;
383193326Sed  }
384193326Sed  const APSInt &getInt() const {
385193326Sed    return const_cast<APValue*>(this)->getInt();
386193326Sed  }
387198092Srdivacky
388344896Sdim  /// Try to convert this value to an integral constant. This works if it's an
389344896Sdim  /// integer, null pointer, or offset from a null pointer. Returns true on
390344896Sdim  /// success.
391344896Sdim  bool toIntegralConstant(APSInt &Result, QualType SrcTy,
392344896Sdim                          const ASTContext &Ctx) const;
393344896Sdim
394193326Sed  APFloat &getFloat() {
395193326Sed    assert(isFloat() && "Invalid accessor");
396276479Sdim    return *(APFloat*)(char*)Data.buffer;
397193326Sed  }
398193326Sed  const APFloat &getFloat() const {
399193326Sed    return const_cast<APValue*>(this)->getFloat();
400193326Sed  }
401198092Srdivacky
402353358Sdim  APFixedPoint &getFixedPoint() {
403353358Sdim    assert(isFixedPoint() && "Invalid accessor");
404353358Sdim    return *(APFixedPoint *)(char *)Data.buffer;
405353358Sdim  }
406353358Sdim  const APFixedPoint &getFixedPoint() const {
407353358Sdim    return const_cast<APValue *>(this)->getFixedPoint();
408353358Sdim  }
409353358Sdim
410193326Sed  APSInt &getComplexIntReal() {
411193326Sed    assert(isComplexInt() && "Invalid accessor");
412276479Sdim    return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
413193326Sed  }
414193326Sed  const APSInt &getComplexIntReal() const {
415193326Sed    return const_cast<APValue*>(this)->getComplexIntReal();
416193326Sed  }
417198092Srdivacky
418193326Sed  APSInt &getComplexIntImag() {
419193326Sed    assert(isComplexInt() && "Invalid accessor");
420276479Sdim    return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
421193326Sed  }
422193326Sed  const APSInt &getComplexIntImag() const {
423193326Sed    return const_cast<APValue*>(this)->getComplexIntImag();
424193326Sed  }
425198092Srdivacky
426193326Sed  APFloat &getComplexFloatReal() {
427193326Sed    assert(isComplexFloat() && "Invalid accessor");
428276479Sdim    return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
429193326Sed  }
430193326Sed  const APFloat &getComplexFloatReal() const {
431193326Sed    return const_cast<APValue*>(this)->getComplexFloatReal();
432193326Sed  }
433193326Sed
434193326Sed  APFloat &getComplexFloatImag() {
435193326Sed    assert(isComplexFloat() && "Invalid accessor");
436276479Sdim    return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
437193326Sed  }
438193326Sed  const APFloat &getComplexFloatImag() const {
439193326Sed    return const_cast<APValue*>(this)->getComplexFloatImag();
440193326Sed  }
441193326Sed
442234353Sdim  const LValueBase getLValueBase() const;
443234353Sdim  CharUnits &getLValueOffset();
444234353Sdim  const CharUnits &getLValueOffset() const {
445234353Sdim    return const_cast<APValue*>(this)->getLValueOffset();
446234353Sdim  }
447234353Sdim  bool isLValueOnePastTheEnd() const;
448234353Sdim  bool hasLValuePath() const;
449234353Sdim  ArrayRef<LValuePathEntry> getLValuePath() const;
450234353Sdim  unsigned getLValueCallIndex() const;
451341825Sdim  unsigned getLValueVersion() const;
452314564Sdim  bool isNullPointer() const;
453198092Srdivacky
454234353Sdim  APValue &getVectorElt(unsigned I) {
455234353Sdim    assert(isVector() && "Invalid accessor");
456234353Sdim    assert(I < getVectorLength() && "Index out of range");
457276479Sdim    return ((Vec*)(char*)Data.buffer)->Elts[I];
458234353Sdim  }
459234353Sdim  const APValue &getVectorElt(unsigned I) const {
460234353Sdim    return const_cast<APValue*>(this)->getVectorElt(I);
461234353Sdim  }
462234353Sdim  unsigned getVectorLength() const {
463234353Sdim    assert(isVector() && "Invalid accessor");
464276479Sdim    return ((const Vec*)(const void *)Data.buffer)->NumElts;
465234353Sdim  }
466234353Sdim
467234353Sdim  APValue &getArrayInitializedElt(unsigned I) {
468234353Sdim    assert(isArray() && "Invalid accessor");
469234353Sdim    assert(I < getArrayInitializedElts() && "Index out of range");
470276479Sdim    return ((Arr*)(char*)Data.buffer)->Elts[I];
471234353Sdim  }
472234353Sdim  const APValue &getArrayInitializedElt(unsigned I) const {
473234353Sdim    return const_cast<APValue*>(this)->getArrayInitializedElt(I);
474234353Sdim  }
475234353Sdim  bool hasArrayFiller() const {
476234353Sdim    return getArrayInitializedElts() != getArraySize();
477234353Sdim  }
478234353Sdim  APValue &getArrayFiller() {
479234353Sdim    assert(isArray() && "Invalid accessor");
480234353Sdim    assert(hasArrayFiller() && "No array filler");
481276479Sdim    return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
482234353Sdim  }
483234353Sdim  const APValue &getArrayFiller() const {
484234353Sdim    return const_cast<APValue*>(this)->getArrayFiller();
485234353Sdim  }
486234353Sdim  unsigned getArrayInitializedElts() const {
487234353Sdim    assert(isArray() && "Invalid accessor");
488276479Sdim    return ((const Arr*)(const void *)Data.buffer)->NumElts;
489234353Sdim  }
490234353Sdim  unsigned getArraySize() const {
491234353Sdim    assert(isArray() && "Invalid accessor");
492276479Sdim    return ((const Arr*)(const void *)Data.buffer)->ArrSize;
493234353Sdim  }
494234353Sdim
495234353Sdim  unsigned getStructNumBases() const {
496234353Sdim    assert(isStruct() && "Invalid accessor");
497276479Sdim    return ((const StructData*)(const char*)Data.buffer)->NumBases;
498234353Sdim  }
499234353Sdim  unsigned getStructNumFields() const {
500234353Sdim    assert(isStruct() && "Invalid accessor");
501276479Sdim    return ((const StructData*)(const char*)Data.buffer)->NumFields;
502234353Sdim  }
503234353Sdim  APValue &getStructBase(unsigned i) {
504234353Sdim    assert(isStruct() && "Invalid accessor");
505276479Sdim    return ((StructData*)(char*)Data.buffer)->Elts[i];
506234353Sdim  }
507234353Sdim  APValue &getStructField(unsigned i) {
508234353Sdim    assert(isStruct() && "Invalid accessor");
509276479Sdim    return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
510234353Sdim  }
511234353Sdim  const APValue &getStructBase(unsigned i) const {
512234353Sdim    return const_cast<APValue*>(this)->getStructBase(i);
513234353Sdim  }
514234353Sdim  const APValue &getStructField(unsigned i) const {
515234353Sdim    return const_cast<APValue*>(this)->getStructField(i);
516234353Sdim  }
517234353Sdim
518234353Sdim  const FieldDecl *getUnionField() const {
519234353Sdim    assert(isUnion() && "Invalid accessor");
520276479Sdim    return ((const UnionData*)(const char*)Data.buffer)->Field;
521234353Sdim  }
522234353Sdim  APValue &getUnionValue() {
523234353Sdim    assert(isUnion() && "Invalid accessor");
524276479Sdim    return *((UnionData*)(char*)Data.buffer)->Value;
525234353Sdim  }
526234353Sdim  const APValue &getUnionValue() const {
527234353Sdim    return const_cast<APValue*>(this)->getUnionValue();
528234353Sdim  }
529234353Sdim
530234353Sdim  const ValueDecl *getMemberPointerDecl() const;
531234353Sdim  bool isMemberPointerToDerivedMember() const;
532234353Sdim  ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
533234353Sdim
534234353Sdim  const AddrLabelExpr* getAddrLabelDiffLHS() const {
535234353Sdim    assert(isAddrLabelDiff() && "Invalid accessor");
536276479Sdim    return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
537234353Sdim  }
538234353Sdim  const AddrLabelExpr* getAddrLabelDiffRHS() const {
539234353Sdim    assert(isAddrLabelDiff() && "Invalid accessor");
540276479Sdim    return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
541234353Sdim  }
542234353Sdim
543276479Sdim  void setInt(APSInt I) {
544193326Sed    assert(isInt() && "Invalid accessor");
545276479Sdim    *(APSInt *)(char *)Data.buffer = std::move(I);
546193326Sed  }
547276479Sdim  void setFloat(APFloat F) {
548193326Sed    assert(isFloat() && "Invalid accessor");
549276479Sdim    *(APFloat *)(char *)Data.buffer = std::move(F);
550193326Sed  }
551353358Sdim  void setFixedPoint(APFixedPoint FX) {
552353358Sdim    assert(isFixedPoint() && "Invalid accessor");
553353358Sdim    *(APFixedPoint *)(char *)Data.buffer = std::move(FX);
554353358Sdim  }
555193326Sed  void setVector(const APValue *E, unsigned N) {
556193326Sed    assert(isVector() && "Invalid accessor");
557276479Sdim    ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
558276479Sdim    ((Vec*)(char*)Data.buffer)->NumElts = N;
559193326Sed    for (unsigned i = 0; i != N; ++i)
560276479Sdim      ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
561193326Sed  }
562276479Sdim  void setComplexInt(APSInt R, APSInt I) {
563198092Srdivacky    assert(R.getBitWidth() == I.getBitWidth() &&
564193326Sed           "Invalid complex int (type mismatch).");
565193326Sed    assert(isComplexInt() && "Invalid accessor");
566276479Sdim    ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
567276479Sdim    ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
568193326Sed  }
569276479Sdim  void setComplexFloat(APFloat R, APFloat I) {
570198092Srdivacky    assert(&R.getSemantics() == &I.getSemantics() &&
571193326Sed           "Invalid complex float (type mismatch).");
572193326Sed    assert(isComplexFloat() && "Invalid accessor");
573276479Sdim    ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
574276479Sdim    ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
575193326Sed  }
576234353Sdim  void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
577341825Sdim                 bool IsNullPtr);
578234353Sdim  void setLValue(LValueBase B, const CharUnits &O,
579234353Sdim                 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
580341825Sdim                 bool IsNullPtr);
581234353Sdim  void setUnion(const FieldDecl *Field, const APValue &Value) {
582234353Sdim    assert(isUnion() && "Invalid accessor");
583276479Sdim    ((UnionData*)(char*)Data.buffer)->Field = Field;
584276479Sdim    *((UnionData*)(char*)Data.buffer)->Value = Value;
585234353Sdim  }
586234353Sdim  void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
587234353Sdim                        const AddrLabelExpr* RHSExpr) {
588276479Sdim    ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
589276479Sdim    ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
590234353Sdim  }
591198092Srdivacky
592234353Sdim  /// Assign by swapping from a copy of the RHS.
593234353Sdim  APValue &operator=(APValue RHS) {
594234353Sdim    swap(RHS);
595234353Sdim    return *this;
596234353Sdim  }
597198092Srdivacky
598193326Sedprivate:
599234353Sdim  void DestroyDataAndMakeUninit();
600193326Sed  void MakeInt() {
601353358Sdim    assert(isAbsent() && "Bad state change");
602276479Sdim    new ((void*)Data.buffer) APSInt(1);
603193326Sed    Kind = Int;
604193326Sed  }
605193326Sed  void MakeFloat() {
606353358Sdim    assert(isAbsent() && "Bad state change");
607276479Sdim    new ((void*)(char*)Data.buffer) APFloat(0.0);
608193326Sed    Kind = Float;
609193326Sed  }
610353358Sdim  void MakeFixedPoint(APFixedPoint &&FX) {
611353358Sdim    assert(isAbsent() && "Bad state change");
612353358Sdim    new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX));
613353358Sdim    Kind = FixedPoint;
614353358Sdim  }
615193326Sed  void MakeVector() {
616353358Sdim    assert(isAbsent() && "Bad state change");
617276479Sdim    new ((void*)(char*)Data.buffer) Vec();
618193326Sed    Kind = Vector;
619193326Sed  }
620193326Sed  void MakeComplexInt() {
621353358Sdim    assert(isAbsent() && "Bad state change");
622276479Sdim    new ((void*)(char*)Data.buffer) ComplexAPSInt();
623193326Sed    Kind = ComplexInt;
624193326Sed  }
625193326Sed  void MakeComplexFloat() {
626353358Sdim    assert(isAbsent() && "Bad state change");
627276479Sdim    new ((void*)(char*)Data.buffer) ComplexAPFloat();
628193326Sed    Kind = ComplexFloat;
629193326Sed  }
630202379Srdivacky  void MakeLValue();
631234353Sdim  void MakeArray(unsigned InitElts, unsigned Size);
632234353Sdim  void MakeStruct(unsigned B, unsigned M) {
633353358Sdim    assert(isAbsent() && "Bad state change");
634276479Sdim    new ((void*)(char*)Data.buffer) StructData(B, M);
635234353Sdim    Kind = Struct;
636234353Sdim  }
637234353Sdim  void MakeUnion() {
638353358Sdim    assert(isAbsent() && "Bad state change");
639276479Sdim    new ((void*)(char*)Data.buffer) UnionData();
640234353Sdim    Kind = Union;
641234353Sdim  }
642234353Sdim  void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
643234353Sdim                         ArrayRef<const CXXRecordDecl*> Path);
644234353Sdim  void MakeAddrLabelDiff() {
645353358Sdim    assert(isAbsent() && "Bad state change");
646276479Sdim    new ((void*)(char*)Data.buffer) AddrLabelDiffData();
647234353Sdim    Kind = AddrLabelDiff;
648234353Sdim  }
649193326Sed};
650193326Sed
651193326Sed} // end namespace clang.
652193326Sed
653341825Sdimnamespace llvm {
654341825Sdimtemplate<> struct DenseMapInfo<clang::APValue::LValueBase> {
655341825Sdim  static clang::APValue::LValueBase getEmptyKey();
656341825Sdim  static clang::APValue::LValueBase getTombstoneKey();
657341825Sdim  static unsigned getHashValue(const clang::APValue::LValueBase &Base);
658341825Sdim  static bool isEqual(const clang::APValue::LValueBase &LHS,
659341825Sdim                      const clang::APValue::LValueBase &RHS);
660341825Sdim};
661341825Sdim}
662341825Sdim
663193326Sed#endif
664