1 //===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the APValue class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_APVALUE_H 14 #define LLVM_CLANG_AST_APVALUE_H 15 16 #include "clang/Basic/LLVM.h" 17 #include "llvm/ADT/APFixedPoint.h" 18 #include "llvm/ADT/APFloat.h" 19 #include "llvm/ADT/APSInt.h" 20 #include "llvm/ADT/FoldingSet.h" 21 #include "llvm/ADT/PointerIntPair.h" 22 #include "llvm/ADT/PointerUnion.h" 23 #include "llvm/Support/AlignOf.h" 24 25 namespace clang { 26 namespace serialization { 27 template <typename T> class BasicReaderBase; 28 } // end namespace serialization 29 30 class AddrLabelExpr; 31 class ASTContext; 32 class CharUnits; 33 class CXXRecordDecl; 34 class Decl; 35 class DiagnosticBuilder; 36 class Expr; 37 class FieldDecl; 38 struct PrintingPolicy; 39 class Type; 40 class ValueDecl; 41 class QualType; 42 43 /// Symbolic representation of typeid(T) for some type T. 44 class TypeInfoLValue { 45 const Type *T; 46 47 public: 48 TypeInfoLValue() : T() {} 49 explicit TypeInfoLValue(const Type *T); 50 51 const Type *getType() const { return T; } 52 explicit operator bool() const { return T; } 53 54 void *getOpaqueValue() { return const_cast<Type*>(T); } 55 static TypeInfoLValue getFromOpaqueValue(void *Value) { 56 TypeInfoLValue V; 57 V.T = reinterpret_cast<const Type*>(Value); 58 return V; 59 } 60 61 void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const; 62 }; 63 64 /// Symbolic representation of a dynamic allocation. 65 class DynamicAllocLValue { 66 unsigned Index; 67 68 public: 69 DynamicAllocLValue() : Index(0) {} 70 explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {} 71 unsigned getIndex() { return Index - 1; } 72 73 explicit operator bool() const { return Index != 0; } 74 75 void *getOpaqueValue() { 76 return reinterpret_cast<void *>(static_cast<uintptr_t>(Index) 77 << NumLowBitsAvailable); 78 } 79 static DynamicAllocLValue getFromOpaqueValue(void *Value) { 80 DynamicAllocLValue V; 81 V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable; 82 return V; 83 } 84 85 static unsigned getMaxIndex() { 86 return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1; 87 } 88 89 static constexpr int NumLowBitsAvailable = 3; 90 }; 91 } 92 93 namespace llvm { 94 template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> { 95 static void *getAsVoidPointer(clang::TypeInfoLValue V) { 96 return V.getOpaqueValue(); 97 } 98 static clang::TypeInfoLValue getFromVoidPointer(void *P) { 99 return clang::TypeInfoLValue::getFromOpaqueValue(P); 100 } 101 // Validated by static_assert in APValue.cpp; hardcoded to avoid needing 102 // to include Type.h. 103 static constexpr int NumLowBitsAvailable = 3; 104 }; 105 106 template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> { 107 static void *getAsVoidPointer(clang::DynamicAllocLValue V) { 108 return V.getOpaqueValue(); 109 } 110 static clang::DynamicAllocLValue getFromVoidPointer(void *P) { 111 return clang::DynamicAllocLValue::getFromOpaqueValue(P); 112 } 113 static constexpr int NumLowBitsAvailable = 114 clang::DynamicAllocLValue::NumLowBitsAvailable; 115 }; 116 } 117 118 namespace clang { 119 /// APValue - This class implements a discriminated union of [uninitialized] 120 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], 121 /// [Vector: N * APValue], [Array: N * APValue] 122 class APValue { 123 typedef llvm::APFixedPoint APFixedPoint; 124 typedef llvm::APSInt APSInt; 125 typedef llvm::APFloat APFloat; 126 public: 127 enum ValueKind { 128 /// There is no such object (it's outside its lifetime). 129 None, 130 /// This object has an indeterminate value (C++ [basic.indet]). 131 Indeterminate, 132 Int, 133 Float, 134 FixedPoint, 135 ComplexInt, 136 ComplexFloat, 137 LValue, 138 Vector, 139 Array, 140 Struct, 141 Union, 142 MemberPointer, 143 AddrLabelDiff 144 }; 145 146 class LValueBase { 147 typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue, 148 DynamicAllocLValue> 149 PtrTy; 150 151 public: 152 LValueBase() : Local{} {} 153 LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0); 154 LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0); 155 static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type); 156 static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); 157 158 void Profile(llvm::FoldingSetNodeID &ID) const; 159 160 template <class T> bool is() const { return isa<T>(Ptr); } 161 162 template <class T> T get() const { return cast<T>(Ptr); } 163 164 template <class T> T dyn_cast() const { 165 return dyn_cast_if_present<T>(Ptr); 166 } 167 168 void *getOpaqueValue() const; 169 170 bool isNull() const; 171 172 explicit operator bool() const; 173 174 unsigned getCallIndex() const; 175 unsigned getVersion() const; 176 QualType getTypeInfoType() const; 177 QualType getDynamicAllocType() const; 178 179 QualType getType() const; 180 181 friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); 182 friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { 183 return !(LHS == RHS); 184 } 185 friend llvm::hash_code hash_value(const LValueBase &Base); 186 friend struct llvm::DenseMapInfo<LValueBase>; 187 188 private: 189 PtrTy Ptr; 190 struct LocalState { 191 unsigned CallIndex, Version; 192 }; 193 union { 194 LocalState Local; 195 /// The type std::type_info, if this is a TypeInfoLValue. 196 void *TypeInfoType; 197 /// The QualType, if this is a DynamicAllocLValue. 198 void *DynamicAllocType; 199 }; 200 }; 201 202 /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we 203 /// mean a virtual or non-virtual base class subobject. 204 typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; 205 206 /// A non-discriminated union of a base, field, or array index. 207 class LValuePathEntry { 208 static_assert(sizeof(uintptr_t) <= sizeof(uint64_t), 209 "pointer doesn't fit in 64 bits?"); 210 uint64_t Value; 211 212 public: 213 LValuePathEntry() : Value() {} 214 LValuePathEntry(BaseOrMemberType BaseOrMember); 215 static LValuePathEntry ArrayIndex(uint64_t Index) { 216 LValuePathEntry Result; 217 Result.Value = Index; 218 return Result; 219 } 220 221 BaseOrMemberType getAsBaseOrMember() const { 222 return BaseOrMemberType::getFromOpaqueValue( 223 reinterpret_cast<void *>(Value)); 224 } 225 uint64_t getAsArrayIndex() const { return Value; } 226 227 void Profile(llvm::FoldingSetNodeID &ID) const; 228 229 friend bool operator==(LValuePathEntry A, LValuePathEntry B) { 230 return A.Value == B.Value; 231 } 232 friend bool operator!=(LValuePathEntry A, LValuePathEntry B) { 233 return A.Value != B.Value; 234 } 235 friend llvm::hash_code hash_value(LValuePathEntry A) { 236 return llvm::hash_value(A.Value); 237 } 238 }; 239 class LValuePathSerializationHelper { 240 const void *Ty; 241 242 public: 243 ArrayRef<LValuePathEntry> Path; 244 245 LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType); 246 QualType getType(); 247 }; 248 struct NoLValuePath {}; 249 struct UninitArray {}; 250 struct UninitStruct {}; 251 struct ConstexprUnknown {}; 252 253 template <typename Impl> friend class clang::serialization::BasicReaderBase; 254 friend class ASTImporter; 255 friend class ASTNodeImporter; 256 257 private: 258 ValueKind Kind; 259 bool AllowConstexprUnknown : 1; 260 261 struct ComplexAPSInt { 262 APSInt Real, Imag; 263 ComplexAPSInt() : Real(1), Imag(1) {} 264 }; 265 struct ComplexAPFloat { 266 APFloat Real, Imag; 267 ComplexAPFloat() : Real(0.0), Imag(0.0) {} 268 }; 269 struct LV; 270 struct Vec { 271 APValue *Elts = nullptr; 272 unsigned NumElts = 0; 273 Vec() = default; 274 Vec(const Vec &) = delete; 275 Vec &operator=(const Vec &) = delete; 276 ~Vec() { delete[] Elts; } 277 }; 278 struct Arr { 279 APValue *Elts; 280 unsigned NumElts, ArrSize; 281 Arr(unsigned NumElts, unsigned ArrSize); 282 Arr(const Arr &) = delete; 283 Arr &operator=(const Arr &) = delete; 284 ~Arr(); 285 }; 286 struct StructData { 287 APValue *Elts; 288 unsigned NumBases; 289 unsigned NumFields; 290 StructData(unsigned NumBases, unsigned NumFields); 291 StructData(const StructData &) = delete; 292 StructData &operator=(const StructData &) = delete; 293 ~StructData(); 294 }; 295 struct UnionData { 296 const FieldDecl *Field; 297 APValue *Value; 298 UnionData(); 299 UnionData(const UnionData &) = delete; 300 UnionData &operator=(const UnionData &) = delete; 301 ~UnionData(); 302 }; 303 struct AddrLabelDiffData { 304 const AddrLabelExpr* LHSExpr; 305 const AddrLabelExpr* RHSExpr; 306 }; 307 struct MemberPointerData; 308 309 // We ensure elsewhere that Data is big enough for LV and MemberPointerData. 310 typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt, 311 ComplexAPFloat, Vec, Arr, StructData, 312 UnionData, AddrLabelDiffData> DataType; 313 static const size_t DataSize = sizeof(DataType); 314 315 DataType Data; 316 317 public: 318 bool allowConstexprUnknown() const { return AllowConstexprUnknown; } 319 320 void setConstexprUnknown(bool IsConstexprUnknown = true) { 321 AllowConstexprUnknown = IsConstexprUnknown; 322 } 323 324 /// Creates an empty APValue of type None. 325 APValue() : Kind(None), AllowConstexprUnknown(false) {} 326 /// Creates an integer APValue holding the given value. 327 explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) { 328 MakeInt(); setInt(std::move(I)); 329 } 330 /// Creates a float APValue holding the given value. 331 explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) { 332 MakeFloat(); setFloat(std::move(F)); 333 } 334 /// Creates a fixed-point APValue holding the given value. 335 explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) { 336 MakeFixedPoint(std::move(FX)); 337 } 338 /// Creates a vector APValue with \p N elements. The elements 339 /// are read from \p E. 340 explicit APValue(const APValue *E, unsigned N) 341 : Kind(None), AllowConstexprUnknown(false) { 342 MakeVector(); setVector(E, N); 343 } 344 /// Creates an integer complex APValue with the given real and imaginary 345 /// values. 346 APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) { 347 MakeComplexInt(); setComplexInt(std::move(R), std::move(I)); 348 } 349 /// Creates a float complex APValue with the given real and imaginary values. 350 APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) { 351 MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I)); 352 } 353 APValue(const APValue &RHS); 354 APValue(APValue &&RHS); 355 /// Creates an lvalue APValue without an lvalue path. 356 /// \param Base The base of the lvalue. 357 /// \param Offset The offset of the lvalue. 358 /// \param IsNullPtr Whether this lvalue is a null pointer. 359 APValue(LValueBase Base, const CharUnits &Offset, NoLValuePath, 360 bool IsNullPtr = false) 361 : Kind(None), AllowConstexprUnknown(false) { 362 MakeLValue(); 363 setLValue(Base, Offset, NoLValuePath{}, IsNullPtr); 364 } 365 /// Creates an lvalue APValue with an lvalue path. 366 /// \param Base The base of the lvalue. 367 /// \param Offset The offset of the lvalue. 368 /// \param Path The lvalue path. 369 /// \param OnePastTheEnd Whether this lvalue is one-past-the-end of the 370 /// subobject it points to. 371 /// \param IsNullPtr Whether this lvalue is a null pointer. 372 APValue(LValueBase Base, const CharUnits &Offset, 373 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, 374 bool IsNullPtr = false) 375 : Kind(None), AllowConstexprUnknown(false) { 376 MakeLValue(); 377 setLValue(Base, Offset, Path, OnePastTheEnd, IsNullPtr); 378 } 379 /// Creates a constexpr unknown lvalue APValue. 380 /// \param Base The base of the lvalue. 381 /// \param Offset The offset of the lvalue. 382 /// \param IsNullPtr Whether this lvalue is a null pointer. 383 APValue(LValueBase Base, const CharUnits &Offset, ConstexprUnknown, 384 bool IsNullPtr = false) 385 : Kind(None), AllowConstexprUnknown(true) { 386 MakeLValue(); 387 setLValue(Base, Offset, NoLValuePath{}, IsNullPtr); 388 } 389 390 /// Creates a new array APValue. 391 /// \param UninitArray Marker. Pass an empty UninitArray. 392 /// \param InitElts Number of elements you're going to initialize in the 393 /// array. 394 /// \param Size Full size of the array. 395 APValue(UninitArray, unsigned InitElts, unsigned Size) 396 : Kind(None), AllowConstexprUnknown(false) { 397 MakeArray(InitElts, Size); 398 } 399 /// Creates a new struct APValue. 400 /// \param UninitStruct Marker. Pass an empty UninitStruct. 401 /// \param NumBases Number of bases. 402 /// \param NumMembers Number of members. 403 APValue(UninitStruct, unsigned NumBases, unsigned NumMembers) 404 : Kind(None), AllowConstexprUnknown(false) { 405 MakeStruct(NumBases, NumMembers); 406 } 407 /// Creates a new union APValue. 408 /// \param ActiveDecl The FieldDecl of the active union member. 409 /// \param ActiveValue The value of the active union member. 410 explicit APValue(const FieldDecl *ActiveDecl, 411 const APValue &ActiveValue = APValue()) 412 : Kind(None), AllowConstexprUnknown(false) { 413 MakeUnion(); 414 setUnion(ActiveDecl, ActiveValue); 415 } 416 /// Creates a new member pointer APValue. 417 /// \param Member Declaration of the member 418 /// \param IsDerivedMember Whether member is a derived one. 419 /// \param Path The path of the member. 420 APValue(const ValueDecl *Member, bool IsDerivedMember, 421 ArrayRef<const CXXRecordDecl *> Path) 422 : Kind(None), AllowConstexprUnknown(false) { 423 MakeMemberPointer(Member, IsDerivedMember, Path); 424 } 425 /// Creates a new address label diff APValue. 426 /// \param LHSExpr The left-hand side of the difference. 427 /// \param RHSExpr The right-hand side of the difference. 428 APValue(const AddrLabelExpr *LHSExpr, const AddrLabelExpr *RHSExpr) 429 : Kind(None), AllowConstexprUnknown(false) { 430 MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); 431 } 432 static APValue IndeterminateValue() { 433 APValue Result; 434 Result.Kind = Indeterminate; 435 return Result; 436 } 437 438 APValue &operator=(const APValue &RHS); 439 APValue &operator=(APValue &&RHS); 440 441 ~APValue() { 442 if (Kind != None && Kind != Indeterminate) 443 DestroyDataAndMakeUninit(); 444 } 445 446 /// Returns whether the object performed allocations. 447 /// 448 /// If APValues are constructed via placement new, \c needsCleanup() 449 /// indicates whether the destructor must be called in order to correctly 450 /// free all allocated memory. 451 bool needsCleanup() const; 452 453 /// Swaps the contents of this and the given APValue. 454 void swap(APValue &RHS); 455 456 /// profile this value. There is no guarantee that values of different 457 /// types will not produce the same profiled value, so the type should 458 /// typically also be profiled if it's not implied by the context. 459 void Profile(llvm::FoldingSetNodeID &ID) const; 460 461 ValueKind getKind() const { return Kind; } 462 463 bool isAbsent() const { return Kind == None; } 464 bool isIndeterminate() const { return Kind == Indeterminate; } 465 bool hasValue() const { return Kind != None && Kind != Indeterminate; } 466 467 bool isInt() const { return Kind == Int; } 468 bool isFloat() const { return Kind == Float; } 469 bool isFixedPoint() const { return Kind == FixedPoint; } 470 bool isComplexInt() const { return Kind == ComplexInt; } 471 bool isComplexFloat() const { return Kind == ComplexFloat; } 472 bool isLValue() const { return Kind == LValue; } 473 bool isVector() const { return Kind == Vector; } 474 bool isArray() const { return Kind == Array; } 475 bool isStruct() const { return Kind == Struct; } 476 bool isUnion() const { return Kind == Union; } 477 bool isMemberPointer() const { return Kind == MemberPointer; } 478 bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } 479 480 void dump() const; 481 void dump(raw_ostream &OS, const ASTContext &Context) const; 482 483 void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; 484 void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty, 485 const ASTContext *Ctx = nullptr) const; 486 487 std::string getAsString(const ASTContext &Ctx, QualType Ty) const; 488 489 APSInt &getInt() { 490 assert(isInt() && "Invalid accessor"); 491 return *(APSInt *)(char *)&Data; 492 } 493 const APSInt &getInt() const { 494 return const_cast<APValue*>(this)->getInt(); 495 } 496 497 /// Try to convert this value to an integral constant. This works if it's an 498 /// integer, null pointer, or offset from a null pointer. Returns true on 499 /// success. 500 bool toIntegralConstant(APSInt &Result, QualType SrcTy, 501 const ASTContext &Ctx) const; 502 503 APFloat &getFloat() { 504 assert(isFloat() && "Invalid accessor"); 505 return *(APFloat *)(char *)&Data; 506 } 507 const APFloat &getFloat() const { 508 return const_cast<APValue*>(this)->getFloat(); 509 } 510 511 APFixedPoint &getFixedPoint() { 512 assert(isFixedPoint() && "Invalid accessor"); 513 return *(APFixedPoint *)(char *)&Data; 514 } 515 const APFixedPoint &getFixedPoint() const { 516 return const_cast<APValue *>(this)->getFixedPoint(); 517 } 518 519 APSInt &getComplexIntReal() { 520 assert(isComplexInt() && "Invalid accessor"); 521 return ((ComplexAPSInt *)(char *)&Data)->Real; 522 } 523 const APSInt &getComplexIntReal() const { 524 return const_cast<APValue*>(this)->getComplexIntReal(); 525 } 526 527 APSInt &getComplexIntImag() { 528 assert(isComplexInt() && "Invalid accessor"); 529 return ((ComplexAPSInt *)(char *)&Data)->Imag; 530 } 531 const APSInt &getComplexIntImag() const { 532 return const_cast<APValue*>(this)->getComplexIntImag(); 533 } 534 535 APFloat &getComplexFloatReal() { 536 assert(isComplexFloat() && "Invalid accessor"); 537 return ((ComplexAPFloat *)(char *)&Data)->Real; 538 } 539 const APFloat &getComplexFloatReal() const { 540 return const_cast<APValue*>(this)->getComplexFloatReal(); 541 } 542 543 APFloat &getComplexFloatImag() { 544 assert(isComplexFloat() && "Invalid accessor"); 545 return ((ComplexAPFloat *)(char *)&Data)->Imag; 546 } 547 const APFloat &getComplexFloatImag() const { 548 return const_cast<APValue*>(this)->getComplexFloatImag(); 549 } 550 551 const LValueBase getLValueBase() const; 552 CharUnits &getLValueOffset(); 553 const CharUnits &getLValueOffset() const { 554 return const_cast<APValue*>(this)->getLValueOffset(); 555 } 556 bool isLValueOnePastTheEnd() const; 557 bool hasLValuePath() const; 558 ArrayRef<LValuePathEntry> getLValuePath() const; 559 unsigned getLValueCallIndex() const; 560 unsigned getLValueVersion() const; 561 bool isNullPointer() const; 562 563 APValue &getVectorElt(unsigned I) { 564 assert(isVector() && "Invalid accessor"); 565 assert(I < getVectorLength() && "Index out of range"); 566 return ((Vec *)(char *)&Data)->Elts[I]; 567 } 568 const APValue &getVectorElt(unsigned I) const { 569 return const_cast<APValue*>(this)->getVectorElt(I); 570 } 571 unsigned getVectorLength() const { 572 assert(isVector() && "Invalid accessor"); 573 return ((const Vec *)(const void *)&Data)->NumElts; 574 } 575 576 APValue &getArrayInitializedElt(unsigned I) { 577 assert(isArray() && "Invalid accessor"); 578 assert(I < getArrayInitializedElts() && "Index out of range"); 579 return ((Arr *)(char *)&Data)->Elts[I]; 580 } 581 const APValue &getArrayInitializedElt(unsigned I) const { 582 return const_cast<APValue*>(this)->getArrayInitializedElt(I); 583 } 584 bool hasArrayFiller() const { 585 return getArrayInitializedElts() != getArraySize(); 586 } 587 APValue &getArrayFiller() { 588 assert(isArray() && "Invalid accessor"); 589 assert(hasArrayFiller() && "No array filler"); 590 return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()]; 591 } 592 const APValue &getArrayFiller() const { 593 return const_cast<APValue*>(this)->getArrayFiller(); 594 } 595 unsigned getArrayInitializedElts() const { 596 assert(isArray() && "Invalid accessor"); 597 return ((const Arr *)(const void *)&Data)->NumElts; 598 } 599 unsigned getArraySize() const { 600 assert(isArray() && "Invalid accessor"); 601 return ((const Arr *)(const void *)&Data)->ArrSize; 602 } 603 604 unsigned getStructNumBases() const { 605 assert(isStruct() && "Invalid accessor"); 606 return ((const StructData *)(const char *)&Data)->NumBases; 607 } 608 unsigned getStructNumFields() const { 609 assert(isStruct() && "Invalid accessor"); 610 return ((const StructData *)(const char *)&Data)->NumFields; 611 } 612 APValue &getStructBase(unsigned i) { 613 assert(isStruct() && "Invalid accessor"); 614 assert(i < getStructNumBases() && "base class index OOB"); 615 return ((StructData *)(char *)&Data)->Elts[i]; 616 } 617 APValue &getStructField(unsigned i) { 618 assert(isStruct() && "Invalid accessor"); 619 assert(i < getStructNumFields() && "field index OOB"); 620 return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i]; 621 } 622 const APValue &getStructBase(unsigned i) const { 623 return const_cast<APValue*>(this)->getStructBase(i); 624 } 625 const APValue &getStructField(unsigned i) const { 626 return const_cast<APValue*>(this)->getStructField(i); 627 } 628 629 const FieldDecl *getUnionField() const { 630 assert(isUnion() && "Invalid accessor"); 631 return ((const UnionData *)(const char *)&Data)->Field; 632 } 633 APValue &getUnionValue() { 634 assert(isUnion() && "Invalid accessor"); 635 return *((UnionData *)(char *)&Data)->Value; 636 } 637 const APValue &getUnionValue() const { 638 return const_cast<APValue*>(this)->getUnionValue(); 639 } 640 641 const ValueDecl *getMemberPointerDecl() const; 642 bool isMemberPointerToDerivedMember() const; 643 ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; 644 645 const AddrLabelExpr* getAddrLabelDiffLHS() const { 646 assert(isAddrLabelDiff() && "Invalid accessor"); 647 return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr; 648 } 649 const AddrLabelExpr* getAddrLabelDiffRHS() const { 650 assert(isAddrLabelDiff() && "Invalid accessor"); 651 return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr; 652 } 653 654 void setInt(APSInt I) { 655 assert(isInt() && "Invalid accessor"); 656 *(APSInt *)(char *)&Data = std::move(I); 657 } 658 void setFloat(APFloat F) { 659 assert(isFloat() && "Invalid accessor"); 660 *(APFloat *)(char *)&Data = std::move(F); 661 } 662 void setFixedPoint(APFixedPoint FX) { 663 assert(isFixedPoint() && "Invalid accessor"); 664 *(APFixedPoint *)(char *)&Data = std::move(FX); 665 } 666 void setVector(const APValue *E, unsigned N) { 667 MutableArrayRef<APValue> InternalElts = setVectorUninit(N); 668 for (unsigned i = 0; i != N; ++i) 669 InternalElts[i] = E[i]; 670 } 671 void setComplexInt(APSInt R, APSInt I) { 672 assert(R.getBitWidth() == I.getBitWidth() && 673 "Invalid complex int (type mismatch)."); 674 assert(isComplexInt() && "Invalid accessor"); 675 ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R); 676 ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I); 677 } 678 void setComplexFloat(APFloat R, APFloat I) { 679 assert(&R.getSemantics() == &I.getSemantics() && 680 "Invalid complex float (type mismatch)."); 681 assert(isComplexFloat() && "Invalid accessor"); 682 ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R); 683 ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I); 684 } 685 void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, 686 bool IsNullPtr); 687 void setLValue(LValueBase B, const CharUnits &O, 688 ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, 689 bool IsNullPtr); 690 void setUnion(const FieldDecl *Field, const APValue &Value); 691 void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, 692 const AddrLabelExpr* RHSExpr) { 693 ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr; 694 ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr; 695 } 696 697 private: 698 void DestroyDataAndMakeUninit(); 699 void MakeInt() { 700 assert(isAbsent() && "Bad state change"); 701 new ((void *)&Data) APSInt(1); 702 Kind = Int; 703 } 704 void MakeFloat() { 705 assert(isAbsent() && "Bad state change"); 706 new ((void *)(char *)&Data) APFloat(0.0); 707 Kind = Float; 708 } 709 void MakeFixedPoint(APFixedPoint &&FX) { 710 assert(isAbsent() && "Bad state change"); 711 new ((void *)(char *)&Data) APFixedPoint(std::move(FX)); 712 Kind = FixedPoint; 713 } 714 void MakeVector() { 715 assert(isAbsent() && "Bad state change"); 716 new ((void *)(char *)&Data) Vec(); 717 Kind = Vector; 718 } 719 void MakeComplexInt() { 720 assert(isAbsent() && "Bad state change"); 721 new ((void *)(char *)&Data) ComplexAPSInt(); 722 Kind = ComplexInt; 723 } 724 void MakeComplexFloat() { 725 assert(isAbsent() && "Bad state change"); 726 new ((void *)(char *)&Data) ComplexAPFloat(); 727 Kind = ComplexFloat; 728 } 729 void MakeLValue(); 730 void MakeArray(unsigned InitElts, unsigned Size); 731 void MakeStruct(unsigned B, unsigned M) { 732 assert(isAbsent() && "Bad state change"); 733 new ((void *)(char *)&Data) StructData(B, M); 734 Kind = Struct; 735 } 736 void MakeUnion() { 737 assert(isAbsent() && "Bad state change"); 738 new ((void *)(char *)&Data) UnionData(); 739 Kind = Union; 740 } 741 void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, 742 ArrayRef<const CXXRecordDecl*> Path); 743 void MakeAddrLabelDiff() { 744 assert(isAbsent() && "Bad state change"); 745 new ((void *)(char *)&Data) AddrLabelDiffData(); 746 Kind = AddrLabelDiff; 747 } 748 749 private: 750 /// The following functions are used as part of initialization, during 751 /// deserialization and importing. Reserve the space so that it can be 752 /// filled in by those steps. 753 MutableArrayRef<APValue> setVectorUninit(unsigned N) { 754 assert(isVector() && "Invalid accessor"); 755 Vec *V = ((Vec *)(char *)&Data); 756 V->Elts = new APValue[N]; 757 V->NumElts = N; 758 return {V->Elts, V->NumElts}; 759 } 760 MutableArrayRef<LValuePathEntry> 761 setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, 762 bool OnePastTheEnd, bool IsNullPtr); 763 MutableArrayRef<const CXXRecordDecl *> 764 setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, 765 unsigned Size); 766 }; 767 768 } // end namespace clang. 769 770 namespace llvm { 771 template<> struct DenseMapInfo<clang::APValue::LValueBase> { 772 static clang::APValue::LValueBase getEmptyKey(); 773 static clang::APValue::LValueBase getTombstoneKey(); 774 static unsigned getHashValue(const clang::APValue::LValueBase &Base); 775 static bool isEqual(const clang::APValue::LValueBase &LHS, 776 const clang::APValue::LValueBase &RHS); 777 }; 778 } 779 780 #endif 781