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