1 //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===// 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 implements the APValue class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/APValue.h" 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/CharUnits.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/Expr.h" 18 #include "clang/AST/Type.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/raw_ostream.h" 21 using namespace clang; 22 23 namespace { 24 struct LVBase { 25 APValue::LValueBase Base; 26 CharUnits Offset; 27 unsigned PathLength; 28 bool IsNullPtr : 1; 29 bool IsOnePastTheEnd : 1; 30 }; 31 } 32 33 void *APValue::LValueBase::getOpaqueValue() const { 34 return Ptr.getOpaqueValue(); 35 } 36 37 bool APValue::LValueBase::isNull() const { 38 return Ptr.isNull(); 39 } 40 41 APValue::LValueBase::operator bool () const { 42 return static_cast<bool>(Ptr); 43 } 44 45 clang::APValue::LValueBase 46 llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() { 47 return clang::APValue::LValueBase( 48 DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey(), 49 DenseMapInfo<unsigned>::getEmptyKey(), 50 DenseMapInfo<unsigned>::getEmptyKey()); 51 } 52 53 clang::APValue::LValueBase 54 llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { 55 return clang::APValue::LValueBase( 56 DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey(), 57 DenseMapInfo<unsigned>::getTombstoneKey(), 58 DenseMapInfo<unsigned>::getTombstoneKey()); 59 } 60 61 namespace clang { 62 llvm::hash_code hash_value(const APValue::LValueBase &Base) { 63 return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(), 64 Base.getVersion()); 65 } 66 } 67 68 unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue( 69 const clang::APValue::LValueBase &Base) { 70 return hash_value(Base); 71 } 72 73 bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual( 74 const clang::APValue::LValueBase &LHS, 75 const clang::APValue::LValueBase &RHS) { 76 return LHS == RHS; 77 } 78 79 struct APValue::LV : LVBase { 80 static const unsigned InlinePathSpace = 81 (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); 82 83 /// Path - The sequence of base classes, fields and array indices to follow to 84 /// walk from Base to the subobject. When performing GCC-style folding, there 85 /// may not be such a path. 86 union { 87 LValuePathEntry Path[InlinePathSpace]; 88 LValuePathEntry *PathPtr; 89 }; 90 91 LV() { PathLength = (unsigned)-1; } 92 ~LV() { resizePath(0); } 93 94 void resizePath(unsigned Length) { 95 if (Length == PathLength) 96 return; 97 if (hasPathPtr()) 98 delete [] PathPtr; 99 PathLength = Length; 100 if (hasPathPtr()) 101 PathPtr = new LValuePathEntry[Length]; 102 } 103 104 bool hasPath() const { return PathLength != (unsigned)-1; } 105 bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; } 106 107 LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; } 108 const LValuePathEntry *getPath() const { 109 return hasPathPtr() ? PathPtr : Path; 110 } 111 }; 112 113 namespace { 114 struct MemberPointerBase { 115 llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember; 116 unsigned PathLength; 117 }; 118 } 119 120 struct APValue::MemberPointerData : MemberPointerBase { 121 static const unsigned InlinePathSpace = 122 (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); 123 typedef const CXXRecordDecl *PathElem; 124 union { 125 PathElem Path[InlinePathSpace]; 126 PathElem *PathPtr; 127 }; 128 129 MemberPointerData() { PathLength = 0; } 130 ~MemberPointerData() { resizePath(0); } 131 132 void resizePath(unsigned Length) { 133 if (Length == PathLength) 134 return; 135 if (hasPathPtr()) 136 delete [] PathPtr; 137 PathLength = Length; 138 if (hasPathPtr()) 139 PathPtr = new PathElem[Length]; 140 } 141 142 bool hasPathPtr() const { return PathLength > InlinePathSpace; } 143 144 PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; } 145 const PathElem *getPath() const { 146 return hasPathPtr() ? PathPtr : Path; 147 } 148 }; 149 150 // FIXME: Reduce the malloc traffic here. 151 152 APValue::Arr::Arr(unsigned NumElts, unsigned Size) : 153 Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]), 154 NumElts(NumElts), ArrSize(Size) {} 155 APValue::Arr::~Arr() { delete [] Elts; } 156 157 APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) : 158 Elts(new APValue[NumBases+NumFields]), 159 NumBases(NumBases), NumFields(NumFields) {} 160 APValue::StructData::~StructData() { 161 delete [] Elts; 162 } 163 164 APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {} 165 APValue::UnionData::~UnionData () { 166 delete Value; 167 } 168 169 APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { 170 switch (RHS.getKind()) { 171 case Uninitialized: 172 break; 173 case Int: 174 MakeInt(); 175 setInt(RHS.getInt()); 176 break; 177 case Float: 178 MakeFloat(); 179 setFloat(RHS.getFloat()); 180 break; 181 case FixedPoint: { 182 APFixedPoint FXCopy = RHS.getFixedPoint(); 183 MakeFixedPoint(std::move(FXCopy)); 184 break; 185 } 186 case Vector: 187 MakeVector(); 188 setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, 189 RHS.getVectorLength()); 190 break; 191 case ComplexInt: 192 MakeComplexInt(); 193 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); 194 break; 195 case ComplexFloat: 196 MakeComplexFloat(); 197 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); 198 break; 199 case LValue: 200 MakeLValue(); 201 if (RHS.hasLValuePath()) 202 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), 203 RHS.isLValueOnePastTheEnd(), RHS.isNullPointer()); 204 else 205 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), 206 RHS.isNullPointer()); 207 break; 208 case Array: 209 MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); 210 for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) 211 getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); 212 if (RHS.hasArrayFiller()) 213 getArrayFiller() = RHS.getArrayFiller(); 214 break; 215 case Struct: 216 MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); 217 for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I) 218 getStructBase(I) = RHS.getStructBase(I); 219 for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I) 220 getStructField(I) = RHS.getStructField(I); 221 break; 222 case Union: 223 MakeUnion(); 224 setUnion(RHS.getUnionField(), RHS.getUnionValue()); 225 break; 226 case MemberPointer: 227 MakeMemberPointer(RHS.getMemberPointerDecl(), 228 RHS.isMemberPointerToDerivedMember(), 229 RHS.getMemberPointerPath()); 230 break; 231 case AddrLabelDiff: 232 MakeAddrLabelDiff(); 233 setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); 234 break; 235 } 236 } 237 238 void APValue::DestroyDataAndMakeUninit() { 239 if (Kind == Int) 240 ((APSInt*)(char*)Data.buffer)->~APSInt(); 241 else if (Kind == Float) 242 ((APFloat*)(char*)Data.buffer)->~APFloat(); 243 else if (Kind == FixedPoint) 244 ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); 245 else if (Kind == Vector) 246 ((Vec*)(char*)Data.buffer)->~Vec(); 247 else if (Kind == ComplexInt) 248 ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); 249 else if (Kind == ComplexFloat) 250 ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); 251 else if (Kind == LValue) 252 ((LV*)(char*)Data.buffer)->~LV(); 253 else if (Kind == Array) 254 ((Arr*)(char*)Data.buffer)->~Arr(); 255 else if (Kind == Struct) 256 ((StructData*)(char*)Data.buffer)->~StructData(); 257 else if (Kind == Union) 258 ((UnionData*)(char*)Data.buffer)->~UnionData(); 259 else if (Kind == MemberPointer) 260 ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); 261 else if (Kind == AddrLabelDiff) 262 ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); 263 Kind = Uninitialized; 264 } 265 266 bool APValue::needsCleanup() const { 267 switch (getKind()) { 268 case Uninitialized: 269 case AddrLabelDiff: 270 return false; 271 case Struct: 272 case Union: 273 case Array: 274 case Vector: 275 return true; 276 case Int: 277 return getInt().needsCleanup(); 278 case Float: 279 return getFloat().needsCleanup(); 280 case FixedPoint: 281 return getFixedPoint().getValue().needsCleanup(); 282 case ComplexFloat: 283 assert(getComplexFloatImag().needsCleanup() == 284 getComplexFloatReal().needsCleanup() && 285 "In _Complex float types, real and imaginary values always have the " 286 "same size."); 287 return getComplexFloatReal().needsCleanup(); 288 case ComplexInt: 289 assert(getComplexIntImag().needsCleanup() == 290 getComplexIntReal().needsCleanup() && 291 "In _Complex int types, real and imaginary values must have the " 292 "same size."); 293 return getComplexIntReal().needsCleanup(); 294 case LValue: 295 return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); 296 case MemberPointer: 297 return reinterpret_cast<const MemberPointerData *>(Data.buffer) 298 ->hasPathPtr(); 299 } 300 llvm_unreachable("Unknown APValue kind!"); 301 } 302 303 void APValue::swap(APValue &RHS) { 304 std::swap(Kind, RHS.Kind); 305 char TmpData[DataSize]; 306 memcpy(TmpData, Data.buffer, DataSize); 307 memcpy(Data.buffer, RHS.Data.buffer, DataSize); 308 memcpy(RHS.Data.buffer, TmpData, DataSize); 309 } 310 311 LLVM_DUMP_METHOD void APValue::dump() const { 312 dump(llvm::errs()); 313 llvm::errs() << '\n'; 314 } 315 316 static double GetApproxValue(const llvm::APFloat &F) { 317 llvm::APFloat V = F; 318 bool ignored; 319 V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, 320 &ignored); 321 return V.convertToDouble(); 322 } 323 324 void APValue::dump(raw_ostream &OS) const { 325 switch (getKind()) { 326 case Uninitialized: 327 OS << "Uninitialized"; 328 return; 329 case Int: 330 OS << "Int: " << getInt(); 331 return; 332 case Float: 333 OS << "Float: " << GetApproxValue(getFloat()); 334 return; 335 case FixedPoint: 336 OS << "FixedPoint : " << getFixedPoint(); 337 return; 338 case Vector: 339 OS << "Vector: "; 340 getVectorElt(0).dump(OS); 341 for (unsigned i = 1; i != getVectorLength(); ++i) { 342 OS << ", "; 343 getVectorElt(i).dump(OS); 344 } 345 return; 346 case ComplexInt: 347 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag(); 348 return; 349 case ComplexFloat: 350 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal()) 351 << ", " << GetApproxValue(getComplexFloatImag()); 352 return; 353 case LValue: 354 OS << "LValue: <todo>"; 355 return; 356 case Array: 357 OS << "Array: "; 358 for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) { 359 getArrayInitializedElt(I).dump(OS); 360 if (I != getArraySize() - 1) OS << ", "; 361 } 362 if (hasArrayFiller()) { 363 OS << getArraySize() - getArrayInitializedElts() << " x "; 364 getArrayFiller().dump(OS); 365 } 366 return; 367 case Struct: 368 OS << "Struct "; 369 if (unsigned N = getStructNumBases()) { 370 OS << " bases: "; 371 getStructBase(0).dump(OS); 372 for (unsigned I = 1; I != N; ++I) { 373 OS << ", "; 374 getStructBase(I).dump(OS); 375 } 376 } 377 if (unsigned N = getStructNumFields()) { 378 OS << " fields: "; 379 getStructField(0).dump(OS); 380 for (unsigned I = 1; I != N; ++I) { 381 OS << ", "; 382 getStructField(I).dump(OS); 383 } 384 } 385 return; 386 case Union: 387 OS << "Union: "; 388 getUnionValue().dump(OS); 389 return; 390 case MemberPointer: 391 OS << "MemberPointer: <todo>"; 392 return; 393 case AddrLabelDiff: 394 OS << "AddrLabelDiff: <todo>"; 395 return; 396 } 397 llvm_unreachable("Unknown APValue kind!"); 398 } 399 400 void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ 401 switch (getKind()) { 402 case APValue::Uninitialized: 403 Out << "<uninitialized>"; 404 return; 405 case APValue::Int: 406 if (Ty->isBooleanType()) 407 Out << (getInt().getBoolValue() ? "true" : "false"); 408 else 409 Out << getInt(); 410 return; 411 case APValue::Float: 412 Out << GetApproxValue(getFloat()); 413 return; 414 case APValue::FixedPoint: 415 Out << getFixedPoint(); 416 return; 417 case APValue::Vector: { 418 Out << '{'; 419 QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); 420 getVectorElt(0).printPretty(Out, Ctx, ElemTy); 421 for (unsigned i = 1; i != getVectorLength(); ++i) { 422 Out << ", "; 423 getVectorElt(i).printPretty(Out, Ctx, ElemTy); 424 } 425 Out << '}'; 426 return; 427 } 428 case APValue::ComplexInt: 429 Out << getComplexIntReal() << "+" << getComplexIntImag() << "i"; 430 return; 431 case APValue::ComplexFloat: 432 Out << GetApproxValue(getComplexFloatReal()) << "+" 433 << GetApproxValue(getComplexFloatImag()) << "i"; 434 return; 435 case APValue::LValue: { 436 bool IsReference = Ty->isReferenceType(); 437 QualType InnerTy 438 = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); 439 if (InnerTy.isNull()) 440 InnerTy = Ty; 441 442 LValueBase Base = getLValueBase(); 443 if (!Base) { 444 if (isNullPointer()) { 445 Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); 446 } else if (IsReference) { 447 Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" 448 << getLValueOffset().getQuantity(); 449 } else { 450 Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" 451 << getLValueOffset().getQuantity(); 452 } 453 return; 454 } 455 456 if (!hasLValuePath()) { 457 // No lvalue path: just print the offset. 458 CharUnits O = getLValueOffset(); 459 CharUnits S = Ctx.getTypeSizeInChars(InnerTy); 460 if (!O.isZero()) { 461 if (IsReference) 462 Out << "*("; 463 if (O % S) { 464 Out << "(char*)"; 465 S = CharUnits::One(); 466 } 467 Out << '&'; 468 } else if (!IsReference) 469 Out << '&'; 470 471 if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) 472 Out << *VD; 473 else { 474 assert(Base.get<const Expr *>() != nullptr && 475 "Expecting non-null Expr"); 476 Base.get<const Expr*>()->printPretty(Out, nullptr, 477 Ctx.getPrintingPolicy()); 478 } 479 480 if (!O.isZero()) { 481 Out << " + " << (O / S); 482 if (IsReference) 483 Out << ')'; 484 } 485 return; 486 } 487 488 // We have an lvalue path. Print it out nicely. 489 if (!IsReference) 490 Out << '&'; 491 else if (isLValueOnePastTheEnd()) 492 Out << "*(&"; 493 494 QualType ElemTy; 495 if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { 496 Out << *VD; 497 ElemTy = VD->getType(); 498 } else { 499 const Expr *E = Base.get<const Expr*>(); 500 assert(E != nullptr && "Expecting non-null Expr"); 501 E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); 502 ElemTy = E->getType(); 503 } 504 505 ArrayRef<LValuePathEntry> Path = getLValuePath(); 506 const CXXRecordDecl *CastToBase = nullptr; 507 for (unsigned I = 0, N = Path.size(); I != N; ++I) { 508 if (ElemTy->getAs<RecordType>()) { 509 // The lvalue refers to a class type, so the next path entry is a base 510 // or member. 511 const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); 512 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { 513 CastToBase = RD; 514 ElemTy = Ctx.getRecordType(RD); 515 } else { 516 const ValueDecl *VD = cast<ValueDecl>(BaseOrMember); 517 Out << "."; 518 if (CastToBase) 519 Out << *CastToBase << "::"; 520 Out << *VD; 521 ElemTy = VD->getType(); 522 } 523 } else { 524 // The lvalue must refer to an array. 525 Out << '[' << Path[I].getAsArrayIndex() << ']'; 526 ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); 527 } 528 } 529 530 // Handle formatting of one-past-the-end lvalues. 531 if (isLValueOnePastTheEnd()) { 532 // FIXME: If CastToBase is non-0, we should prefix the output with 533 // "(CastToBase*)". 534 Out << " + 1"; 535 if (IsReference) 536 Out << ')'; 537 } 538 return; 539 } 540 case APValue::Array: { 541 const ArrayType *AT = Ctx.getAsArrayType(Ty); 542 QualType ElemTy = AT->getElementType(); 543 Out << '{'; 544 if (unsigned N = getArrayInitializedElts()) { 545 getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); 546 for (unsigned I = 1; I != N; ++I) { 547 Out << ", "; 548 if (I == 10) { 549 // Avoid printing out the entire contents of large arrays. 550 Out << "..."; 551 break; 552 } 553 getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); 554 } 555 } 556 Out << '}'; 557 return; 558 } 559 case APValue::Struct: { 560 Out << '{'; 561 const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); 562 bool First = true; 563 if (unsigned N = getStructNumBases()) { 564 const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD); 565 CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); 566 for (unsigned I = 0; I != N; ++I, ++BI) { 567 assert(BI != CD->bases_end()); 568 if (!First) 569 Out << ", "; 570 getStructBase(I).printPretty(Out, Ctx, BI->getType()); 571 First = false; 572 } 573 } 574 for (const auto *FI : RD->fields()) { 575 if (!First) 576 Out << ", "; 577 if (FI->isUnnamedBitfield()) continue; 578 getStructField(FI->getFieldIndex()). 579 printPretty(Out, Ctx, FI->getType()); 580 First = false; 581 } 582 Out << '}'; 583 return; 584 } 585 case APValue::Union: 586 Out << '{'; 587 if (const FieldDecl *FD = getUnionField()) { 588 Out << "." << *FD << " = "; 589 getUnionValue().printPretty(Out, Ctx, FD->getType()); 590 } 591 Out << '}'; 592 return; 593 case APValue::MemberPointer: 594 // FIXME: This is not enough to unambiguously identify the member in a 595 // multiple-inheritance scenario. 596 if (const ValueDecl *VD = getMemberPointerDecl()) { 597 Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD; 598 return; 599 } 600 Out << "0"; 601 return; 602 case APValue::AddrLabelDiff: 603 Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName(); 604 Out << " - "; 605 Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); 606 return; 607 } 608 llvm_unreachable("Unknown APValue kind!"); 609 } 610 611 std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { 612 std::string Result; 613 llvm::raw_string_ostream Out(Result); 614 printPretty(Out, Ctx, Ty); 615 Out.flush(); 616 return Result; 617 } 618 619 bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, 620 const ASTContext &Ctx) const { 621 if (isInt()) { 622 Result = getInt(); 623 return true; 624 } 625 626 if (isLValue() && isNullPointer()) { 627 Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); 628 return true; 629 } 630 631 if (isLValue() && !getLValueBase()) { 632 Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); 633 return true; 634 } 635 636 return false; 637 } 638 639 const APValue::LValueBase APValue::getLValueBase() const { 640 assert(isLValue() && "Invalid accessor"); 641 return ((const LV*)(const void*)Data.buffer)->Base; 642 } 643 644 bool APValue::isLValueOnePastTheEnd() const { 645 assert(isLValue() && "Invalid accessor"); 646 return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd; 647 } 648 649 CharUnits &APValue::getLValueOffset() { 650 assert(isLValue() && "Invalid accessor"); 651 return ((LV*)(void*)Data.buffer)->Offset; 652 } 653 654 bool APValue::hasLValuePath() const { 655 assert(isLValue() && "Invalid accessor"); 656 return ((const LV*)(const char*)Data.buffer)->hasPath(); 657 } 658 659 ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { 660 assert(isLValue() && hasLValuePath() && "Invalid accessor"); 661 const LV &LVal = *((const LV*)(const char*)Data.buffer); 662 return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength); 663 } 664 665 unsigned APValue::getLValueCallIndex() const { 666 assert(isLValue() && "Invalid accessor"); 667 return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex(); 668 } 669 670 unsigned APValue::getLValueVersion() const { 671 assert(isLValue() && "Invalid accessor"); 672 return ((const LV*)(const char*)Data.buffer)->Base.getVersion(); 673 } 674 675 bool APValue::isNullPointer() const { 676 assert(isLValue() && "Invalid usage"); 677 return ((const LV*)(const char*)Data.buffer)->IsNullPtr; 678 } 679 680 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, 681 bool IsNullPtr) { 682 assert(isLValue() && "Invalid accessor"); 683 LV &LVal = *((LV*)(char*)Data.buffer); 684 LVal.Base = B; 685 LVal.IsOnePastTheEnd = false; 686 LVal.Offset = O; 687 LVal.resizePath((unsigned)-1); 688 LVal.IsNullPtr = IsNullPtr; 689 } 690 691 void APValue::setLValue(LValueBase B, const CharUnits &O, 692 ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, 693 bool IsNullPtr) { 694 assert(isLValue() && "Invalid accessor"); 695 LV &LVal = *((LV*)(char*)Data.buffer); 696 LVal.Base = B; 697 LVal.IsOnePastTheEnd = IsOnePastTheEnd; 698 LVal.Offset = O; 699 LVal.resizePath(Path.size()); 700 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); 701 LVal.IsNullPtr = IsNullPtr; 702 } 703 704 const ValueDecl *APValue::getMemberPointerDecl() const { 705 assert(isMemberPointer() && "Invalid accessor"); 706 const MemberPointerData &MPD = 707 *((const MemberPointerData *)(const char *)Data.buffer); 708 return MPD.MemberAndIsDerivedMember.getPointer(); 709 } 710 711 bool APValue::isMemberPointerToDerivedMember() const { 712 assert(isMemberPointer() && "Invalid accessor"); 713 const MemberPointerData &MPD = 714 *((const MemberPointerData *)(const char *)Data.buffer); 715 return MPD.MemberAndIsDerivedMember.getInt(); 716 } 717 718 ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { 719 assert(isMemberPointer() && "Invalid accessor"); 720 const MemberPointerData &MPD = 721 *((const MemberPointerData *)(const char *)Data.buffer); 722 return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength); 723 } 724 725 void APValue::MakeLValue() { 726 assert(isUninit() && "Bad state change"); 727 static_assert(sizeof(LV) <= DataSize, "LV too big"); 728 new ((void*)(char*)Data.buffer) LV(); 729 Kind = LValue; 730 } 731 732 void APValue::MakeArray(unsigned InitElts, unsigned Size) { 733 assert(isUninit() && "Bad state change"); 734 new ((void*)(char*)Data.buffer) Arr(InitElts, Size); 735 Kind = Array; 736 } 737 738 void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, 739 ArrayRef<const CXXRecordDecl*> Path) { 740 assert(isUninit() && "Bad state change"); 741 MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; 742 Kind = MemberPointer; 743 MPD->MemberAndIsDerivedMember.setPointer(Member); 744 MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); 745 MPD->resizePath(Path.size()); 746 memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); 747 } 748