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