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