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