106f32e7eSjoerg //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg //  This file defines the APValue class.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
1306f32e7eSjoerg #ifndef LLVM_CLANG_AST_APVALUE_H
1406f32e7eSjoerg #define LLVM_CLANG_AST_APVALUE_H
1506f32e7eSjoerg 
1606f32e7eSjoerg #include "clang/Basic/LLVM.h"
17*13fbcb42Sjoerg #include "llvm/ADT/APFixedPoint.h"
1806f32e7eSjoerg #include "llvm/ADT/APFloat.h"
1906f32e7eSjoerg #include "llvm/ADT/APSInt.h"
20*13fbcb42Sjoerg #include "llvm/ADT/FoldingSet.h"
2106f32e7eSjoerg #include "llvm/ADT/PointerIntPair.h"
2206f32e7eSjoerg #include "llvm/ADT/PointerUnion.h"
23*13fbcb42Sjoerg #include "llvm/Support/AlignOf.h"
2406f32e7eSjoerg 
2506f32e7eSjoerg namespace clang {
26*13fbcb42Sjoerg namespace serialization {
27*13fbcb42Sjoerg template <typename T> class BasicReaderBase;
28*13fbcb42Sjoerg } // end namespace serialization
29*13fbcb42Sjoerg 
3006f32e7eSjoerg   class AddrLabelExpr;
3106f32e7eSjoerg   class ASTContext;
3206f32e7eSjoerg   class CharUnits;
3306f32e7eSjoerg   class CXXRecordDecl;
3406f32e7eSjoerg   class Decl;
3506f32e7eSjoerg   class DiagnosticBuilder;
3606f32e7eSjoerg   class Expr;
3706f32e7eSjoerg   class FieldDecl;
3806f32e7eSjoerg   struct PrintingPolicy;
3906f32e7eSjoerg   class Type;
4006f32e7eSjoerg   class ValueDecl;
41*13fbcb42Sjoerg   class QualType;
4206f32e7eSjoerg 
4306f32e7eSjoerg /// Symbolic representation of typeid(T) for some type T.
4406f32e7eSjoerg class TypeInfoLValue {
4506f32e7eSjoerg   const Type *T;
4606f32e7eSjoerg 
4706f32e7eSjoerg public:
TypeInfoLValue()4806f32e7eSjoerg   TypeInfoLValue() : T() {}
4906f32e7eSjoerg   explicit TypeInfoLValue(const Type *T);
5006f32e7eSjoerg 
getType()5106f32e7eSjoerg   const Type *getType() const { return T; }
5206f32e7eSjoerg   explicit operator bool() const { return T; }
5306f32e7eSjoerg 
getOpaqueValue()5406f32e7eSjoerg   void *getOpaqueValue() { return const_cast<Type*>(T); }
getFromOpaqueValue(void * Value)5506f32e7eSjoerg   static TypeInfoLValue getFromOpaqueValue(void *Value) {
5606f32e7eSjoerg     TypeInfoLValue V;
5706f32e7eSjoerg     V.T = reinterpret_cast<const Type*>(Value);
5806f32e7eSjoerg     return V;
5906f32e7eSjoerg   }
6006f32e7eSjoerg 
6106f32e7eSjoerg   void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
6206f32e7eSjoerg };
6306f32e7eSjoerg 
6406f32e7eSjoerg /// Symbolic representation of a dynamic allocation.
6506f32e7eSjoerg class DynamicAllocLValue {
6606f32e7eSjoerg   unsigned Index;
6706f32e7eSjoerg 
6806f32e7eSjoerg public:
DynamicAllocLValue()6906f32e7eSjoerg   DynamicAllocLValue() : Index(0) {}
DynamicAllocLValue(unsigned Index)7006f32e7eSjoerg   explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
getIndex()7106f32e7eSjoerg   unsigned getIndex() { return Index - 1; }
7206f32e7eSjoerg 
7306f32e7eSjoerg   explicit operator bool() const { return Index != 0; }
7406f32e7eSjoerg 
getOpaqueValue()7506f32e7eSjoerg   void *getOpaqueValue() {
7606f32e7eSjoerg     return reinterpret_cast<void *>(static_cast<uintptr_t>(Index)
7706f32e7eSjoerg                                     << NumLowBitsAvailable);
7806f32e7eSjoerg   }
getFromOpaqueValue(void * Value)7906f32e7eSjoerg   static DynamicAllocLValue getFromOpaqueValue(void *Value) {
8006f32e7eSjoerg     DynamicAllocLValue V;
8106f32e7eSjoerg     V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
8206f32e7eSjoerg     return V;
8306f32e7eSjoerg   }
8406f32e7eSjoerg 
getMaxIndex()8506f32e7eSjoerg   static unsigned getMaxIndex() {
8606f32e7eSjoerg     return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
8706f32e7eSjoerg   }
8806f32e7eSjoerg 
8906f32e7eSjoerg   static constexpr int NumLowBitsAvailable = 3;
9006f32e7eSjoerg };
9106f32e7eSjoerg }
9206f32e7eSjoerg 
9306f32e7eSjoerg namespace llvm {
9406f32e7eSjoerg template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
9506f32e7eSjoerg   static void *getAsVoidPointer(clang::TypeInfoLValue V) {
9606f32e7eSjoerg     return V.getOpaqueValue();
9706f32e7eSjoerg   }
9806f32e7eSjoerg   static clang::TypeInfoLValue getFromVoidPointer(void *P) {
9906f32e7eSjoerg     return clang::TypeInfoLValue::getFromOpaqueValue(P);
10006f32e7eSjoerg   }
10106f32e7eSjoerg   // Validated by static_assert in APValue.cpp; hardcoded to avoid needing
10206f32e7eSjoerg   // to include Type.h.
10306f32e7eSjoerg   static constexpr int NumLowBitsAvailable = 3;
10406f32e7eSjoerg };
10506f32e7eSjoerg 
10606f32e7eSjoerg template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
10706f32e7eSjoerg   static void *getAsVoidPointer(clang::DynamicAllocLValue V) {
10806f32e7eSjoerg     return V.getOpaqueValue();
10906f32e7eSjoerg   }
11006f32e7eSjoerg   static clang::DynamicAllocLValue getFromVoidPointer(void *P) {
11106f32e7eSjoerg     return clang::DynamicAllocLValue::getFromOpaqueValue(P);
11206f32e7eSjoerg   }
11306f32e7eSjoerg   static constexpr int NumLowBitsAvailable =
11406f32e7eSjoerg       clang::DynamicAllocLValue::NumLowBitsAvailable;
11506f32e7eSjoerg };
11606f32e7eSjoerg }
11706f32e7eSjoerg 
11806f32e7eSjoerg namespace clang {
11906f32e7eSjoerg /// APValue - This class implements a discriminated union of [uninitialized]
12006f32e7eSjoerg /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
12106f32e7eSjoerg /// [Vector: N * APValue], [Array: N * APValue]
12206f32e7eSjoerg class APValue {
123*13fbcb42Sjoerg   typedef llvm::APFixedPoint APFixedPoint;
12406f32e7eSjoerg   typedef llvm::APSInt APSInt;
12506f32e7eSjoerg   typedef llvm::APFloat APFloat;
12606f32e7eSjoerg public:
12706f32e7eSjoerg   enum ValueKind {
12806f32e7eSjoerg     /// There is no such object (it's outside its lifetime).
12906f32e7eSjoerg     None,
13006f32e7eSjoerg     /// This object has an indeterminate value (C++ [basic.indet]).
13106f32e7eSjoerg     Indeterminate,
13206f32e7eSjoerg     Int,
13306f32e7eSjoerg     Float,
13406f32e7eSjoerg     FixedPoint,
13506f32e7eSjoerg     ComplexInt,
13606f32e7eSjoerg     ComplexFloat,
13706f32e7eSjoerg     LValue,
13806f32e7eSjoerg     Vector,
13906f32e7eSjoerg     Array,
14006f32e7eSjoerg     Struct,
14106f32e7eSjoerg     Union,
14206f32e7eSjoerg     MemberPointer,
14306f32e7eSjoerg     AddrLabelDiff
14406f32e7eSjoerg   };
14506f32e7eSjoerg 
14606f32e7eSjoerg   class LValueBase {
14706f32e7eSjoerg     typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
14806f32e7eSjoerg                                DynamicAllocLValue>
14906f32e7eSjoerg         PtrTy;
15006f32e7eSjoerg 
15106f32e7eSjoerg   public:
15206f32e7eSjoerg     LValueBase() : Local{} {}
15306f32e7eSjoerg     LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
15406f32e7eSjoerg     LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
15506f32e7eSjoerg     static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
15606f32e7eSjoerg     static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
15706f32e7eSjoerg 
158*13fbcb42Sjoerg     void Profile(llvm::FoldingSetNodeID &ID) const;
159*13fbcb42Sjoerg 
16006f32e7eSjoerg     template <class T>
16106f32e7eSjoerg     bool is() const { return Ptr.is<T>(); }
16206f32e7eSjoerg 
16306f32e7eSjoerg     template <class T>
16406f32e7eSjoerg     T get() const { return Ptr.get<T>(); }
16506f32e7eSjoerg 
16606f32e7eSjoerg     template <class T>
16706f32e7eSjoerg     T dyn_cast() const { return Ptr.dyn_cast<T>(); }
16806f32e7eSjoerg 
16906f32e7eSjoerg     void *getOpaqueValue() const;
17006f32e7eSjoerg 
17106f32e7eSjoerg     bool isNull() const;
17206f32e7eSjoerg 
17306f32e7eSjoerg     explicit operator bool() const;
17406f32e7eSjoerg 
17506f32e7eSjoerg     unsigned getCallIndex() const;
17606f32e7eSjoerg     unsigned getVersion() const;
17706f32e7eSjoerg     QualType getTypeInfoType() const;
17806f32e7eSjoerg     QualType getDynamicAllocType() const;
17906f32e7eSjoerg 
180*13fbcb42Sjoerg     QualType getType() const;
181*13fbcb42Sjoerg 
18206f32e7eSjoerg     friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
18306f32e7eSjoerg     friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
18406f32e7eSjoerg       return !(LHS == RHS);
18506f32e7eSjoerg     }
18606f32e7eSjoerg     friend llvm::hash_code hash_value(const LValueBase &Base);
187*13fbcb42Sjoerg     friend struct llvm::DenseMapInfo<LValueBase>;
18806f32e7eSjoerg 
18906f32e7eSjoerg   private:
19006f32e7eSjoerg     PtrTy Ptr;
19106f32e7eSjoerg     struct LocalState {
19206f32e7eSjoerg       unsigned CallIndex, Version;
19306f32e7eSjoerg     };
19406f32e7eSjoerg     union {
19506f32e7eSjoerg       LocalState Local;
19606f32e7eSjoerg       /// The type std::type_info, if this is a TypeInfoLValue.
19706f32e7eSjoerg       void *TypeInfoType;
19806f32e7eSjoerg       /// The QualType, if this is a DynamicAllocLValue.
19906f32e7eSjoerg       void *DynamicAllocType;
20006f32e7eSjoerg     };
20106f32e7eSjoerg   };
20206f32e7eSjoerg 
20306f32e7eSjoerg   /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we
20406f32e7eSjoerg   /// mean a virtual or non-virtual base class subobject.
20506f32e7eSjoerg   typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
20606f32e7eSjoerg 
20706f32e7eSjoerg   /// A non-discriminated union of a base, field, or array index.
20806f32e7eSjoerg   class LValuePathEntry {
20906f32e7eSjoerg     static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
21006f32e7eSjoerg                   "pointer doesn't fit in 64 bits?");
21106f32e7eSjoerg     uint64_t Value;
21206f32e7eSjoerg 
21306f32e7eSjoerg   public:
21406f32e7eSjoerg     LValuePathEntry() : Value() {}
215*13fbcb42Sjoerg     LValuePathEntry(BaseOrMemberType BaseOrMember);
21606f32e7eSjoerg     static LValuePathEntry ArrayIndex(uint64_t Index) {
21706f32e7eSjoerg       LValuePathEntry Result;
21806f32e7eSjoerg       Result.Value = Index;
21906f32e7eSjoerg       return Result;
22006f32e7eSjoerg     }
22106f32e7eSjoerg 
22206f32e7eSjoerg     BaseOrMemberType getAsBaseOrMember() const {
22306f32e7eSjoerg       return BaseOrMemberType::getFromOpaqueValue(
22406f32e7eSjoerg           reinterpret_cast<void *>(Value));
22506f32e7eSjoerg     }
22606f32e7eSjoerg     uint64_t getAsArrayIndex() const { return Value; }
22706f32e7eSjoerg 
228*13fbcb42Sjoerg     void Profile(llvm::FoldingSetNodeID &ID) const;
229*13fbcb42Sjoerg 
23006f32e7eSjoerg     friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
23106f32e7eSjoerg       return A.Value == B.Value;
23206f32e7eSjoerg     }
23306f32e7eSjoerg     friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
23406f32e7eSjoerg       return A.Value != B.Value;
23506f32e7eSjoerg     }
23606f32e7eSjoerg     friend llvm::hash_code hash_value(LValuePathEntry A) {
23706f32e7eSjoerg       return llvm::hash_value(A.Value);
23806f32e7eSjoerg     }
23906f32e7eSjoerg   };
240*13fbcb42Sjoerg   class LValuePathSerializationHelper {
241*13fbcb42Sjoerg     const void *ElemTy;
242*13fbcb42Sjoerg 
243*13fbcb42Sjoerg   public:
244*13fbcb42Sjoerg     ArrayRef<LValuePathEntry> Path;
245*13fbcb42Sjoerg 
246*13fbcb42Sjoerg     LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType);
247*13fbcb42Sjoerg     QualType getType();
248*13fbcb42Sjoerg   };
24906f32e7eSjoerg   struct NoLValuePath {};
25006f32e7eSjoerg   struct UninitArray {};
25106f32e7eSjoerg   struct UninitStruct {};
25206f32e7eSjoerg 
253*13fbcb42Sjoerg   template <typename Impl> friend class clang::serialization::BasicReaderBase;
254*13fbcb42Sjoerg   friend class ASTImporter;
255*13fbcb42Sjoerg   friend class ASTNodeImporter;
25606f32e7eSjoerg 
25706f32e7eSjoerg private:
25806f32e7eSjoerg   ValueKind Kind;
25906f32e7eSjoerg 
26006f32e7eSjoerg   struct ComplexAPSInt {
26106f32e7eSjoerg     APSInt Real, Imag;
26206f32e7eSjoerg     ComplexAPSInt() : Real(1), Imag(1) {}
26306f32e7eSjoerg   };
26406f32e7eSjoerg   struct ComplexAPFloat {
26506f32e7eSjoerg     APFloat Real, Imag;
26606f32e7eSjoerg     ComplexAPFloat() : Real(0.0), Imag(0.0) {}
26706f32e7eSjoerg   };
26806f32e7eSjoerg   struct LV;
26906f32e7eSjoerg   struct Vec {
27006f32e7eSjoerg     APValue *Elts;
27106f32e7eSjoerg     unsigned NumElts;
27206f32e7eSjoerg     Vec() : Elts(nullptr), NumElts(0) {}
27306f32e7eSjoerg     ~Vec() { delete[] Elts; }
27406f32e7eSjoerg   };
27506f32e7eSjoerg   struct Arr {
27606f32e7eSjoerg     APValue *Elts;
27706f32e7eSjoerg     unsigned NumElts, ArrSize;
27806f32e7eSjoerg     Arr(unsigned NumElts, unsigned ArrSize);
27906f32e7eSjoerg     ~Arr();
28006f32e7eSjoerg   };
28106f32e7eSjoerg   struct StructData {
28206f32e7eSjoerg     APValue *Elts;
28306f32e7eSjoerg     unsigned NumBases;
28406f32e7eSjoerg     unsigned NumFields;
28506f32e7eSjoerg     StructData(unsigned NumBases, unsigned NumFields);
28606f32e7eSjoerg     ~StructData();
28706f32e7eSjoerg   };
28806f32e7eSjoerg   struct UnionData {
28906f32e7eSjoerg     const FieldDecl *Field;
29006f32e7eSjoerg     APValue *Value;
29106f32e7eSjoerg     UnionData();
29206f32e7eSjoerg     ~UnionData();
29306f32e7eSjoerg   };
29406f32e7eSjoerg   struct AddrLabelDiffData {
29506f32e7eSjoerg     const AddrLabelExpr* LHSExpr;
29606f32e7eSjoerg     const AddrLabelExpr* RHSExpr;
29706f32e7eSjoerg   };
29806f32e7eSjoerg   struct MemberPointerData;
29906f32e7eSjoerg 
30006f32e7eSjoerg   // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
30106f32e7eSjoerg   typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
30206f32e7eSjoerg                                       ComplexAPFloat, Vec, Arr, StructData,
30306f32e7eSjoerg                                       UnionData, AddrLabelDiffData> DataType;
30406f32e7eSjoerg   static const size_t DataSize = sizeof(DataType);
30506f32e7eSjoerg 
30606f32e7eSjoerg   DataType Data;
30706f32e7eSjoerg 
30806f32e7eSjoerg public:
30906f32e7eSjoerg   APValue() : Kind(None) {}
31006f32e7eSjoerg   explicit APValue(APSInt I) : Kind(None) {
31106f32e7eSjoerg     MakeInt(); setInt(std::move(I));
31206f32e7eSjoerg   }
31306f32e7eSjoerg   explicit APValue(APFloat F) : Kind(None) {
31406f32e7eSjoerg     MakeFloat(); setFloat(std::move(F));
31506f32e7eSjoerg   }
31606f32e7eSjoerg   explicit APValue(APFixedPoint FX) : Kind(None) {
31706f32e7eSjoerg     MakeFixedPoint(std::move(FX));
31806f32e7eSjoerg   }
31906f32e7eSjoerg   explicit APValue(const APValue *E, unsigned N) : Kind(None) {
32006f32e7eSjoerg     MakeVector(); setVector(E, N);
32106f32e7eSjoerg   }
32206f32e7eSjoerg   APValue(APSInt R, APSInt I) : Kind(None) {
32306f32e7eSjoerg     MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
32406f32e7eSjoerg   }
32506f32e7eSjoerg   APValue(APFloat R, APFloat I) : Kind(None) {
32606f32e7eSjoerg     MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
32706f32e7eSjoerg   }
32806f32e7eSjoerg   APValue(const APValue &RHS);
329*13fbcb42Sjoerg   APValue(APValue &&RHS);
33006f32e7eSjoerg   APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
33106f32e7eSjoerg           bool IsNullPtr = false)
33206f32e7eSjoerg       : Kind(None) {
33306f32e7eSjoerg     MakeLValue(); setLValue(B, O, N, IsNullPtr);
33406f32e7eSjoerg   }
33506f32e7eSjoerg   APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
33606f32e7eSjoerg           bool OnePastTheEnd, bool IsNullPtr = false)
33706f32e7eSjoerg       : Kind(None) {
33806f32e7eSjoerg     MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
33906f32e7eSjoerg   }
34006f32e7eSjoerg   APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) {
34106f32e7eSjoerg     MakeArray(InitElts, Size);
34206f32e7eSjoerg   }
34306f32e7eSjoerg   APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) {
34406f32e7eSjoerg     MakeStruct(B, M);
34506f32e7eSjoerg   }
34606f32e7eSjoerg   explicit APValue(const FieldDecl *D, const APValue &V = APValue())
34706f32e7eSjoerg       : Kind(None) {
34806f32e7eSjoerg     MakeUnion(); setUnion(D, V);
34906f32e7eSjoerg   }
35006f32e7eSjoerg   APValue(const ValueDecl *Member, bool IsDerivedMember,
35106f32e7eSjoerg           ArrayRef<const CXXRecordDecl*> Path) : Kind(None) {
35206f32e7eSjoerg     MakeMemberPointer(Member, IsDerivedMember, Path);
35306f32e7eSjoerg   }
35406f32e7eSjoerg   APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
35506f32e7eSjoerg       : Kind(None) {
35606f32e7eSjoerg     MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
35706f32e7eSjoerg   }
35806f32e7eSjoerg   static APValue IndeterminateValue() {
35906f32e7eSjoerg     APValue Result;
36006f32e7eSjoerg     Result.Kind = Indeterminate;
36106f32e7eSjoerg     return Result;
36206f32e7eSjoerg   }
36306f32e7eSjoerg 
364*13fbcb42Sjoerg   APValue &operator=(const APValue &RHS);
365*13fbcb42Sjoerg   APValue &operator=(APValue &&RHS);
366*13fbcb42Sjoerg 
36706f32e7eSjoerg   ~APValue() {
36806f32e7eSjoerg     if (Kind != None && Kind != Indeterminate)
36906f32e7eSjoerg       DestroyDataAndMakeUninit();
37006f32e7eSjoerg   }
37106f32e7eSjoerg 
37206f32e7eSjoerg   /// Returns whether the object performed allocations.
37306f32e7eSjoerg   ///
37406f32e7eSjoerg   /// If APValues are constructed via placement new, \c needsCleanup()
37506f32e7eSjoerg   /// indicates whether the destructor must be called in order to correctly
37606f32e7eSjoerg   /// free all allocated memory.
37706f32e7eSjoerg   bool needsCleanup() const;
37806f32e7eSjoerg 
37906f32e7eSjoerg   /// Swaps the contents of this and the given APValue.
38006f32e7eSjoerg   void swap(APValue &RHS);
38106f32e7eSjoerg 
382*13fbcb42Sjoerg   /// profile this value. There is no guarantee that values of different
383*13fbcb42Sjoerg   /// types will not produce the same profiled value, so the type should
384*13fbcb42Sjoerg   /// typically also be profiled if it's not implied by the context.
385*13fbcb42Sjoerg   void Profile(llvm::FoldingSetNodeID &ID) const;
386*13fbcb42Sjoerg 
38706f32e7eSjoerg   ValueKind getKind() const { return Kind; }
38806f32e7eSjoerg 
38906f32e7eSjoerg   bool isAbsent() const { return Kind == None; }
39006f32e7eSjoerg   bool isIndeterminate() const { return Kind == Indeterminate; }
39106f32e7eSjoerg   bool hasValue() const { return Kind != None && Kind != Indeterminate; }
39206f32e7eSjoerg 
39306f32e7eSjoerg   bool isInt() const { return Kind == Int; }
39406f32e7eSjoerg   bool isFloat() const { return Kind == Float; }
39506f32e7eSjoerg   bool isFixedPoint() const { return Kind == FixedPoint; }
39606f32e7eSjoerg   bool isComplexInt() const { return Kind == ComplexInt; }
39706f32e7eSjoerg   bool isComplexFloat() const { return Kind == ComplexFloat; }
39806f32e7eSjoerg   bool isLValue() const { return Kind == LValue; }
39906f32e7eSjoerg   bool isVector() const { return Kind == Vector; }
40006f32e7eSjoerg   bool isArray() const { return Kind == Array; }
40106f32e7eSjoerg   bool isStruct() const { return Kind == Struct; }
40206f32e7eSjoerg   bool isUnion() const { return Kind == Union; }
40306f32e7eSjoerg   bool isMemberPointer() const { return Kind == MemberPointer; }
40406f32e7eSjoerg   bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
40506f32e7eSjoerg 
40606f32e7eSjoerg   void dump() const;
407*13fbcb42Sjoerg   void dump(raw_ostream &OS, const ASTContext &Context) const;
40806f32e7eSjoerg 
40906f32e7eSjoerg   void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
410*13fbcb42Sjoerg   void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty,
411*13fbcb42Sjoerg                    const ASTContext *Ctx = nullptr) const;
412*13fbcb42Sjoerg 
41306f32e7eSjoerg   std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
41406f32e7eSjoerg 
41506f32e7eSjoerg   APSInt &getInt() {
41606f32e7eSjoerg     assert(isInt() && "Invalid accessor");
417*13fbcb42Sjoerg     return *(APSInt *)(char *)&Data;
41806f32e7eSjoerg   }
41906f32e7eSjoerg   const APSInt &getInt() const {
42006f32e7eSjoerg     return const_cast<APValue*>(this)->getInt();
42106f32e7eSjoerg   }
42206f32e7eSjoerg 
42306f32e7eSjoerg   /// Try to convert this value to an integral constant. This works if it's an
42406f32e7eSjoerg   /// integer, null pointer, or offset from a null pointer. Returns true on
42506f32e7eSjoerg   /// success.
42606f32e7eSjoerg   bool toIntegralConstant(APSInt &Result, QualType SrcTy,
42706f32e7eSjoerg                           const ASTContext &Ctx) const;
42806f32e7eSjoerg 
42906f32e7eSjoerg   APFloat &getFloat() {
43006f32e7eSjoerg     assert(isFloat() && "Invalid accessor");
431*13fbcb42Sjoerg     return *(APFloat *)(char *)&Data;
43206f32e7eSjoerg   }
43306f32e7eSjoerg   const APFloat &getFloat() const {
43406f32e7eSjoerg     return const_cast<APValue*>(this)->getFloat();
43506f32e7eSjoerg   }
43606f32e7eSjoerg 
43706f32e7eSjoerg   APFixedPoint &getFixedPoint() {
43806f32e7eSjoerg     assert(isFixedPoint() && "Invalid accessor");
439*13fbcb42Sjoerg     return *(APFixedPoint *)(char *)&Data;
44006f32e7eSjoerg   }
44106f32e7eSjoerg   const APFixedPoint &getFixedPoint() const {
44206f32e7eSjoerg     return const_cast<APValue *>(this)->getFixedPoint();
44306f32e7eSjoerg   }
44406f32e7eSjoerg 
44506f32e7eSjoerg   APSInt &getComplexIntReal() {
44606f32e7eSjoerg     assert(isComplexInt() && "Invalid accessor");
447*13fbcb42Sjoerg     return ((ComplexAPSInt *)(char *)&Data)->Real;
44806f32e7eSjoerg   }
44906f32e7eSjoerg   const APSInt &getComplexIntReal() const {
45006f32e7eSjoerg     return const_cast<APValue*>(this)->getComplexIntReal();
45106f32e7eSjoerg   }
45206f32e7eSjoerg 
45306f32e7eSjoerg   APSInt &getComplexIntImag() {
45406f32e7eSjoerg     assert(isComplexInt() && "Invalid accessor");
455*13fbcb42Sjoerg     return ((ComplexAPSInt *)(char *)&Data)->Imag;
45606f32e7eSjoerg   }
45706f32e7eSjoerg   const APSInt &getComplexIntImag() const {
45806f32e7eSjoerg     return const_cast<APValue*>(this)->getComplexIntImag();
45906f32e7eSjoerg   }
46006f32e7eSjoerg 
46106f32e7eSjoerg   APFloat &getComplexFloatReal() {
46206f32e7eSjoerg     assert(isComplexFloat() && "Invalid accessor");
463*13fbcb42Sjoerg     return ((ComplexAPFloat *)(char *)&Data)->Real;
46406f32e7eSjoerg   }
46506f32e7eSjoerg   const APFloat &getComplexFloatReal() const {
46606f32e7eSjoerg     return const_cast<APValue*>(this)->getComplexFloatReal();
46706f32e7eSjoerg   }
46806f32e7eSjoerg 
46906f32e7eSjoerg   APFloat &getComplexFloatImag() {
47006f32e7eSjoerg     assert(isComplexFloat() && "Invalid accessor");
471*13fbcb42Sjoerg     return ((ComplexAPFloat *)(char *)&Data)->Imag;
47206f32e7eSjoerg   }
47306f32e7eSjoerg   const APFloat &getComplexFloatImag() const {
47406f32e7eSjoerg     return const_cast<APValue*>(this)->getComplexFloatImag();
47506f32e7eSjoerg   }
47606f32e7eSjoerg 
47706f32e7eSjoerg   const LValueBase getLValueBase() const;
47806f32e7eSjoerg   CharUnits &getLValueOffset();
47906f32e7eSjoerg   const CharUnits &getLValueOffset() const {
48006f32e7eSjoerg     return const_cast<APValue*>(this)->getLValueOffset();
48106f32e7eSjoerg   }
48206f32e7eSjoerg   bool isLValueOnePastTheEnd() const;
48306f32e7eSjoerg   bool hasLValuePath() const;
48406f32e7eSjoerg   ArrayRef<LValuePathEntry> getLValuePath() const;
48506f32e7eSjoerg   unsigned getLValueCallIndex() const;
48606f32e7eSjoerg   unsigned getLValueVersion() const;
48706f32e7eSjoerg   bool isNullPointer() const;
48806f32e7eSjoerg 
48906f32e7eSjoerg   APValue &getVectorElt(unsigned I) {
49006f32e7eSjoerg     assert(isVector() && "Invalid accessor");
49106f32e7eSjoerg     assert(I < getVectorLength() && "Index out of range");
492*13fbcb42Sjoerg     return ((Vec *)(char *)&Data)->Elts[I];
49306f32e7eSjoerg   }
49406f32e7eSjoerg   const APValue &getVectorElt(unsigned I) const {
49506f32e7eSjoerg     return const_cast<APValue*>(this)->getVectorElt(I);
49606f32e7eSjoerg   }
49706f32e7eSjoerg   unsigned getVectorLength() const {
49806f32e7eSjoerg     assert(isVector() && "Invalid accessor");
499*13fbcb42Sjoerg     return ((const Vec *)(const void *)&Data)->NumElts;
50006f32e7eSjoerg   }
50106f32e7eSjoerg 
50206f32e7eSjoerg   APValue &getArrayInitializedElt(unsigned I) {
50306f32e7eSjoerg     assert(isArray() && "Invalid accessor");
50406f32e7eSjoerg     assert(I < getArrayInitializedElts() && "Index out of range");
505*13fbcb42Sjoerg     return ((Arr *)(char *)&Data)->Elts[I];
50606f32e7eSjoerg   }
50706f32e7eSjoerg   const APValue &getArrayInitializedElt(unsigned I) const {
50806f32e7eSjoerg     return const_cast<APValue*>(this)->getArrayInitializedElt(I);
50906f32e7eSjoerg   }
51006f32e7eSjoerg   bool hasArrayFiller() const {
51106f32e7eSjoerg     return getArrayInitializedElts() != getArraySize();
51206f32e7eSjoerg   }
51306f32e7eSjoerg   APValue &getArrayFiller() {
51406f32e7eSjoerg     assert(isArray() && "Invalid accessor");
51506f32e7eSjoerg     assert(hasArrayFiller() && "No array filler");
516*13fbcb42Sjoerg     return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()];
51706f32e7eSjoerg   }
51806f32e7eSjoerg   const APValue &getArrayFiller() const {
51906f32e7eSjoerg     return const_cast<APValue*>(this)->getArrayFiller();
52006f32e7eSjoerg   }
52106f32e7eSjoerg   unsigned getArrayInitializedElts() const {
52206f32e7eSjoerg     assert(isArray() && "Invalid accessor");
523*13fbcb42Sjoerg     return ((const Arr *)(const void *)&Data)->NumElts;
52406f32e7eSjoerg   }
52506f32e7eSjoerg   unsigned getArraySize() const {
52606f32e7eSjoerg     assert(isArray() && "Invalid accessor");
527*13fbcb42Sjoerg     return ((const Arr *)(const void *)&Data)->ArrSize;
52806f32e7eSjoerg   }
52906f32e7eSjoerg 
53006f32e7eSjoerg   unsigned getStructNumBases() const {
53106f32e7eSjoerg     assert(isStruct() && "Invalid accessor");
532*13fbcb42Sjoerg     return ((const StructData *)(const char *)&Data)->NumBases;
53306f32e7eSjoerg   }
53406f32e7eSjoerg   unsigned getStructNumFields() const {
53506f32e7eSjoerg     assert(isStruct() && "Invalid accessor");
536*13fbcb42Sjoerg     return ((const StructData *)(const char *)&Data)->NumFields;
53706f32e7eSjoerg   }
53806f32e7eSjoerg   APValue &getStructBase(unsigned i) {
53906f32e7eSjoerg     assert(isStruct() && "Invalid accessor");
540*13fbcb42Sjoerg     assert(i < getStructNumBases() && "base class index OOB");
541*13fbcb42Sjoerg     return ((StructData *)(char *)&Data)->Elts[i];
54206f32e7eSjoerg   }
54306f32e7eSjoerg   APValue &getStructField(unsigned i) {
54406f32e7eSjoerg     assert(isStruct() && "Invalid accessor");
545*13fbcb42Sjoerg     assert(i < getStructNumFields() && "field index OOB");
546*13fbcb42Sjoerg     return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i];
54706f32e7eSjoerg   }
54806f32e7eSjoerg   const APValue &getStructBase(unsigned i) const {
54906f32e7eSjoerg     return const_cast<APValue*>(this)->getStructBase(i);
55006f32e7eSjoerg   }
55106f32e7eSjoerg   const APValue &getStructField(unsigned i) const {
55206f32e7eSjoerg     return const_cast<APValue*>(this)->getStructField(i);
55306f32e7eSjoerg   }
55406f32e7eSjoerg 
55506f32e7eSjoerg   const FieldDecl *getUnionField() const {
55606f32e7eSjoerg     assert(isUnion() && "Invalid accessor");
557*13fbcb42Sjoerg     return ((const UnionData *)(const char *)&Data)->Field;
55806f32e7eSjoerg   }
55906f32e7eSjoerg   APValue &getUnionValue() {
56006f32e7eSjoerg     assert(isUnion() && "Invalid accessor");
561*13fbcb42Sjoerg     return *((UnionData *)(char *)&Data)->Value;
56206f32e7eSjoerg   }
56306f32e7eSjoerg   const APValue &getUnionValue() const {
56406f32e7eSjoerg     return const_cast<APValue*>(this)->getUnionValue();
56506f32e7eSjoerg   }
56606f32e7eSjoerg 
56706f32e7eSjoerg   const ValueDecl *getMemberPointerDecl() const;
56806f32e7eSjoerg   bool isMemberPointerToDerivedMember() const;
56906f32e7eSjoerg   ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
57006f32e7eSjoerg 
57106f32e7eSjoerg   const AddrLabelExpr* getAddrLabelDiffLHS() const {
57206f32e7eSjoerg     assert(isAddrLabelDiff() && "Invalid accessor");
573*13fbcb42Sjoerg     return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr;
57406f32e7eSjoerg   }
57506f32e7eSjoerg   const AddrLabelExpr* getAddrLabelDiffRHS() const {
57606f32e7eSjoerg     assert(isAddrLabelDiff() && "Invalid accessor");
577*13fbcb42Sjoerg     return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr;
57806f32e7eSjoerg   }
57906f32e7eSjoerg 
58006f32e7eSjoerg   void setInt(APSInt I) {
58106f32e7eSjoerg     assert(isInt() && "Invalid accessor");
582*13fbcb42Sjoerg     *(APSInt *)(char *)&Data = std::move(I);
58306f32e7eSjoerg   }
58406f32e7eSjoerg   void setFloat(APFloat F) {
58506f32e7eSjoerg     assert(isFloat() && "Invalid accessor");
586*13fbcb42Sjoerg     *(APFloat *)(char *)&Data = std::move(F);
58706f32e7eSjoerg   }
58806f32e7eSjoerg   void setFixedPoint(APFixedPoint FX) {
58906f32e7eSjoerg     assert(isFixedPoint() && "Invalid accessor");
590*13fbcb42Sjoerg     *(APFixedPoint *)(char *)&Data = std::move(FX);
59106f32e7eSjoerg   }
59206f32e7eSjoerg   void setVector(const APValue *E, unsigned N) {
593*13fbcb42Sjoerg     MutableArrayRef<APValue> InternalElts = setVectorUninit(N);
59406f32e7eSjoerg     for (unsigned i = 0; i != N; ++i)
595*13fbcb42Sjoerg       InternalElts[i] = E[i];
59606f32e7eSjoerg   }
59706f32e7eSjoerg   void setComplexInt(APSInt R, APSInt I) {
59806f32e7eSjoerg     assert(R.getBitWidth() == I.getBitWidth() &&
59906f32e7eSjoerg            "Invalid complex int (type mismatch).");
60006f32e7eSjoerg     assert(isComplexInt() && "Invalid accessor");
601*13fbcb42Sjoerg     ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R);
602*13fbcb42Sjoerg     ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I);
60306f32e7eSjoerg   }
60406f32e7eSjoerg   void setComplexFloat(APFloat R, APFloat I) {
60506f32e7eSjoerg     assert(&R.getSemantics() == &I.getSemantics() &&
60606f32e7eSjoerg            "Invalid complex float (type mismatch).");
60706f32e7eSjoerg     assert(isComplexFloat() && "Invalid accessor");
608*13fbcb42Sjoerg     ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R);
609*13fbcb42Sjoerg     ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I);
61006f32e7eSjoerg   }
61106f32e7eSjoerg   void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
61206f32e7eSjoerg                  bool IsNullPtr);
61306f32e7eSjoerg   void setLValue(LValueBase B, const CharUnits &O,
61406f32e7eSjoerg                  ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
61506f32e7eSjoerg                  bool IsNullPtr);
616*13fbcb42Sjoerg   void setUnion(const FieldDecl *Field, const APValue &Value);
61706f32e7eSjoerg   void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
61806f32e7eSjoerg                         const AddrLabelExpr* RHSExpr) {
619*13fbcb42Sjoerg     ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr;
620*13fbcb42Sjoerg     ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr;
62106f32e7eSjoerg   }
62206f32e7eSjoerg 
62306f32e7eSjoerg private:
62406f32e7eSjoerg   void DestroyDataAndMakeUninit();
62506f32e7eSjoerg   void MakeInt() {
62606f32e7eSjoerg     assert(isAbsent() && "Bad state change");
627*13fbcb42Sjoerg     new ((void *)&Data) APSInt(1);
62806f32e7eSjoerg     Kind = Int;
62906f32e7eSjoerg   }
63006f32e7eSjoerg   void MakeFloat() {
63106f32e7eSjoerg     assert(isAbsent() && "Bad state change");
632*13fbcb42Sjoerg     new ((void *)(char *)&Data) APFloat(0.0);
63306f32e7eSjoerg     Kind = Float;
63406f32e7eSjoerg   }
63506f32e7eSjoerg   void MakeFixedPoint(APFixedPoint &&FX) {
63606f32e7eSjoerg     assert(isAbsent() && "Bad state change");
637*13fbcb42Sjoerg     new ((void *)(char *)&Data) APFixedPoint(std::move(FX));
63806f32e7eSjoerg     Kind = FixedPoint;
63906f32e7eSjoerg   }
64006f32e7eSjoerg   void MakeVector() {
64106f32e7eSjoerg     assert(isAbsent() && "Bad state change");
642*13fbcb42Sjoerg     new ((void *)(char *)&Data) Vec();
64306f32e7eSjoerg     Kind = Vector;
64406f32e7eSjoerg   }
64506f32e7eSjoerg   void MakeComplexInt() {
64606f32e7eSjoerg     assert(isAbsent() && "Bad state change");
647*13fbcb42Sjoerg     new ((void *)(char *)&Data) ComplexAPSInt();
64806f32e7eSjoerg     Kind = ComplexInt;
64906f32e7eSjoerg   }
65006f32e7eSjoerg   void MakeComplexFloat() {
65106f32e7eSjoerg     assert(isAbsent() && "Bad state change");
652*13fbcb42Sjoerg     new ((void *)(char *)&Data) ComplexAPFloat();
65306f32e7eSjoerg     Kind = ComplexFloat;
65406f32e7eSjoerg   }
65506f32e7eSjoerg   void MakeLValue();
65606f32e7eSjoerg   void MakeArray(unsigned InitElts, unsigned Size);
65706f32e7eSjoerg   void MakeStruct(unsigned B, unsigned M) {
65806f32e7eSjoerg     assert(isAbsent() && "Bad state change");
659*13fbcb42Sjoerg     new ((void *)(char *)&Data) StructData(B, M);
66006f32e7eSjoerg     Kind = Struct;
66106f32e7eSjoerg   }
66206f32e7eSjoerg   void MakeUnion() {
66306f32e7eSjoerg     assert(isAbsent() && "Bad state change");
664*13fbcb42Sjoerg     new ((void *)(char *)&Data) UnionData();
66506f32e7eSjoerg     Kind = Union;
66606f32e7eSjoerg   }
66706f32e7eSjoerg   void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
66806f32e7eSjoerg                          ArrayRef<const CXXRecordDecl*> Path);
66906f32e7eSjoerg   void MakeAddrLabelDiff() {
67006f32e7eSjoerg     assert(isAbsent() && "Bad state change");
671*13fbcb42Sjoerg     new ((void *)(char *)&Data) AddrLabelDiffData();
67206f32e7eSjoerg     Kind = AddrLabelDiff;
67306f32e7eSjoerg   }
674*13fbcb42Sjoerg 
675*13fbcb42Sjoerg private:
676*13fbcb42Sjoerg   /// The following functions are used as part of initialization, during
677*13fbcb42Sjoerg   /// deserialization and importing. Reserve the space so that it can be
678*13fbcb42Sjoerg   /// filled in by those steps.
679*13fbcb42Sjoerg   MutableArrayRef<APValue> setVectorUninit(unsigned N) {
680*13fbcb42Sjoerg     assert(isVector() && "Invalid accessor");
681*13fbcb42Sjoerg     Vec *V = ((Vec *)(char *)&Data);
682*13fbcb42Sjoerg     V->Elts = new APValue[N];
683*13fbcb42Sjoerg     V->NumElts = N;
684*13fbcb42Sjoerg     return {V->Elts, V->NumElts};
685*13fbcb42Sjoerg   }
686*13fbcb42Sjoerg   MutableArrayRef<LValuePathEntry>
687*13fbcb42Sjoerg   setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size,
688*13fbcb42Sjoerg                   bool OnePastTheEnd, bool IsNullPtr);
689*13fbcb42Sjoerg   MutableArrayRef<const CXXRecordDecl *>
690*13fbcb42Sjoerg   setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
691*13fbcb42Sjoerg                          unsigned Size);
69206f32e7eSjoerg };
69306f32e7eSjoerg 
69406f32e7eSjoerg } // end namespace clang.
69506f32e7eSjoerg 
69606f32e7eSjoerg namespace llvm {
69706f32e7eSjoerg template<> struct DenseMapInfo<clang::APValue::LValueBase> {
69806f32e7eSjoerg   static clang::APValue::LValueBase getEmptyKey();
69906f32e7eSjoerg   static clang::APValue::LValueBase getTombstoneKey();
70006f32e7eSjoerg   static unsigned getHashValue(const clang::APValue::LValueBase &Base);
70106f32e7eSjoerg   static bool isEqual(const clang::APValue::LValueBase &LHS,
70206f32e7eSjoerg                       const clang::APValue::LValueBase &RHS);
70306f32e7eSjoerg };
70406f32e7eSjoerg }
70506f32e7eSjoerg 
70606f32e7eSjoerg #endif
707