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