1 //===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=// 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 defines the NestedNameSpecifier class, which represents 11 // a C++ nested-name-specifier. 12 // 13 //===----------------------------------------------------------------------===// 14 #include "clang/AST/NestedNameSpecifier.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/Decl.h" 17 #include "clang/AST/DeclCXX.h" 18 #include "clang/AST/PrettyPrinter.h" 19 #include "clang/AST/Type.h" 20 #include "clang/AST/TypeLoc.h" 21 #include "llvm/Support/AlignOf.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <cassert> 24 25 using namespace clang; 26 27 NestedNameSpecifier * 28 NestedNameSpecifier::FindOrInsert(const ASTContext &Context, 29 const NestedNameSpecifier &Mockup) { 30 llvm::FoldingSetNodeID ID; 31 Mockup.Profile(ID); 32 33 void *InsertPos = nullptr; 34 NestedNameSpecifier *NNS 35 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 36 if (!NNS) { 37 NNS = new (Context, llvm::alignOf<NestedNameSpecifier>()) 38 NestedNameSpecifier(Mockup); 39 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 40 } 41 42 return NNS; 43 } 44 45 NestedNameSpecifier * 46 NestedNameSpecifier::Create(const ASTContext &Context, 47 NestedNameSpecifier *Prefix, IdentifierInfo *II) { 48 assert(II && "Identifier cannot be NULL"); 49 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 50 51 NestedNameSpecifier Mockup; 52 Mockup.Prefix.setPointer(Prefix); 53 Mockup.Prefix.setInt(StoredIdentifier); 54 Mockup.Specifier = II; 55 return FindOrInsert(Context, Mockup); 56 } 57 58 NestedNameSpecifier * 59 NestedNameSpecifier::Create(const ASTContext &Context, 60 NestedNameSpecifier *Prefix, 61 const NamespaceDecl *NS) { 62 assert(NS && "Namespace cannot be NULL"); 63 assert((!Prefix || 64 (Prefix->getAsType() == nullptr && 65 Prefix->getAsIdentifier() == nullptr)) && 66 "Broken nested name specifier"); 67 NestedNameSpecifier Mockup; 68 Mockup.Prefix.setPointer(Prefix); 69 Mockup.Prefix.setInt(StoredDecl); 70 Mockup.Specifier = const_cast<NamespaceDecl *>(NS); 71 return FindOrInsert(Context, Mockup); 72 } 73 74 NestedNameSpecifier * 75 NestedNameSpecifier::Create(const ASTContext &Context, 76 NestedNameSpecifier *Prefix, 77 NamespaceAliasDecl *Alias) { 78 assert(Alias && "Namespace alias cannot be NULL"); 79 assert((!Prefix || 80 (Prefix->getAsType() == nullptr && 81 Prefix->getAsIdentifier() == nullptr)) && 82 "Broken nested name specifier"); 83 NestedNameSpecifier Mockup; 84 Mockup.Prefix.setPointer(Prefix); 85 Mockup.Prefix.setInt(StoredDecl); 86 Mockup.Specifier = Alias; 87 return FindOrInsert(Context, Mockup); 88 } 89 90 NestedNameSpecifier * 91 NestedNameSpecifier::Create(const ASTContext &Context, 92 NestedNameSpecifier *Prefix, 93 bool Template, const Type *T) { 94 assert(T && "Type cannot be NULL"); 95 NestedNameSpecifier Mockup; 96 Mockup.Prefix.setPointer(Prefix); 97 Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); 98 Mockup.Specifier = const_cast<Type*>(T); 99 return FindOrInsert(Context, Mockup); 100 } 101 102 NestedNameSpecifier * 103 NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { 104 assert(II && "Identifier cannot be NULL"); 105 NestedNameSpecifier Mockup; 106 Mockup.Prefix.setPointer(nullptr); 107 Mockup.Prefix.setInt(StoredIdentifier); 108 Mockup.Specifier = II; 109 return FindOrInsert(Context, Mockup); 110 } 111 112 NestedNameSpecifier * 113 NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { 114 if (!Context.GlobalNestedNameSpecifier) 115 Context.GlobalNestedNameSpecifier = 116 new (Context, llvm::alignOf<NestedNameSpecifier>()) 117 NestedNameSpecifier(); 118 return Context.GlobalNestedNameSpecifier; 119 } 120 121 NestedNameSpecifier * 122 NestedNameSpecifier::SuperSpecifier(const ASTContext &Context, 123 CXXRecordDecl *RD) { 124 NestedNameSpecifier Mockup; 125 Mockup.Prefix.setPointer(nullptr); 126 Mockup.Prefix.setInt(StoredDecl); 127 Mockup.Specifier = RD; 128 return FindOrInsert(Context, Mockup); 129 } 130 131 NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { 132 if (!Specifier) 133 return Global; 134 135 switch (Prefix.getInt()) { 136 case StoredIdentifier: 137 return Identifier; 138 139 case StoredDecl: { 140 NamedDecl *ND = static_cast<NamedDecl *>(Specifier); 141 if (isa<CXXRecordDecl>(ND)) 142 return Super; 143 return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias; 144 } 145 146 case StoredTypeSpec: 147 return TypeSpec; 148 149 case StoredTypeSpecWithTemplate: 150 return TypeSpecWithTemplate; 151 } 152 153 llvm_unreachable("Invalid NNS Kind!"); 154 } 155 156 /// \brief Retrieve the namespace stored in this nested name specifier. 157 NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { 158 if (Prefix.getInt() == StoredDecl) 159 return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); 160 161 return nullptr; 162 } 163 164 /// \brief Retrieve the namespace alias stored in this nested name specifier. 165 NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { 166 if (Prefix.getInt() == StoredDecl) 167 return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); 168 169 return nullptr; 170 } 171 172 /// \brief Retrieve the record declaration stored in this nested name specifier. 173 CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { 174 switch (Prefix.getInt()) { 175 case StoredIdentifier: 176 return nullptr; 177 178 case StoredDecl: 179 return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier)); 180 181 case StoredTypeSpec: 182 case StoredTypeSpecWithTemplate: 183 return getAsType()->getAsCXXRecordDecl(); 184 } 185 186 llvm_unreachable("Invalid NNS Kind!"); 187 } 188 189 /// \brief Whether this nested name specifier refers to a dependent 190 /// type or not. 191 bool NestedNameSpecifier::isDependent() const { 192 switch (getKind()) { 193 case Identifier: 194 // Identifier specifiers always represent dependent types 195 return true; 196 197 case Namespace: 198 case NamespaceAlias: 199 case Global: 200 return false; 201 202 case Super: { 203 CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier); 204 for (const auto &Base : RD->bases()) 205 if (Base.getType()->isDependentType()) 206 return true; 207 208 return false; 209 } 210 211 case TypeSpec: 212 case TypeSpecWithTemplate: 213 return getAsType()->isDependentType(); 214 } 215 216 llvm_unreachable("Invalid NNS Kind!"); 217 } 218 219 /// \brief Whether this nested name specifier refers to a dependent 220 /// type or not. 221 bool NestedNameSpecifier::isInstantiationDependent() const { 222 switch (getKind()) { 223 case Identifier: 224 // Identifier specifiers always represent dependent types 225 return true; 226 227 case Namespace: 228 case NamespaceAlias: 229 case Global: 230 case Super: 231 return false; 232 233 case TypeSpec: 234 case TypeSpecWithTemplate: 235 return getAsType()->isInstantiationDependentType(); 236 } 237 238 llvm_unreachable("Invalid NNS Kind!"); 239 } 240 241 bool NestedNameSpecifier::containsUnexpandedParameterPack() const { 242 switch (getKind()) { 243 case Identifier: 244 return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); 245 246 case Namespace: 247 case NamespaceAlias: 248 case Global: 249 case Super: 250 return false; 251 252 case TypeSpec: 253 case TypeSpecWithTemplate: 254 return getAsType()->containsUnexpandedParameterPack(); 255 } 256 257 llvm_unreachable("Invalid NNS Kind!"); 258 } 259 260 /// \brief Print this nested name specifier to the given output 261 /// stream. 262 void 263 NestedNameSpecifier::print(raw_ostream &OS, 264 const PrintingPolicy &Policy) const { 265 if (getPrefix()) 266 getPrefix()->print(OS, Policy); 267 268 switch (getKind()) { 269 case Identifier: 270 OS << getAsIdentifier()->getName(); 271 break; 272 273 case Namespace: 274 if (getAsNamespace()->isAnonymousNamespace()) 275 return; 276 277 OS << getAsNamespace()->getName(); 278 break; 279 280 case NamespaceAlias: 281 OS << getAsNamespaceAlias()->getName(); 282 break; 283 284 case Global: 285 break; 286 287 case Super: 288 OS << "__super"; 289 break; 290 291 case TypeSpecWithTemplate: 292 OS << "template "; 293 // Fall through to print the type. 294 295 case TypeSpec: { 296 const Type *T = getAsType(); 297 298 PrintingPolicy InnerPolicy(Policy); 299 InnerPolicy.SuppressScope = true; 300 301 // Nested-name-specifiers are intended to contain minimally-qualified 302 // types. An actual ElaboratedType will not occur, since we'll store 303 // just the type that is referred to in the nested-name-specifier (e.g., 304 // a TypedefType, TagType, etc.). However, when we are dealing with 305 // dependent template-id types (e.g., Outer<T>::template Inner<U>), 306 // the type requires its own nested-name-specifier for uniqueness, so we 307 // suppress that nested-name-specifier during printing. 308 assert(!isa<ElaboratedType>(T) && 309 "Elaborated type in nested-name-specifier"); 310 if (const TemplateSpecializationType *SpecType 311 = dyn_cast<TemplateSpecializationType>(T)) { 312 // Print the template name without its corresponding 313 // nested-name-specifier. 314 SpecType->getTemplateName().print(OS, InnerPolicy, true); 315 316 // Print the template argument list. 317 TemplateSpecializationType::PrintTemplateArgumentList( 318 OS, SpecType->template_arguments(), InnerPolicy); 319 } else { 320 // Print the type normally 321 QualType(T, 0).print(OS, InnerPolicy); 322 } 323 break; 324 } 325 } 326 327 OS << "::"; 328 } 329 330 void NestedNameSpecifier::dump(const LangOptions &LO) const { 331 print(llvm::errs(), PrintingPolicy(LO)); 332 } 333 334 LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { 335 LangOptions LO; 336 print(llvm::errs(), PrintingPolicy(LO)); 337 } 338 339 unsigned 340 NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 341 assert(Qualifier && "Expected a non-NULL qualifier"); 342 343 // Location of the trailing '::'. 344 unsigned Length = sizeof(unsigned); 345 346 switch (Qualifier->getKind()) { 347 case NestedNameSpecifier::Global: 348 // Nothing more to add. 349 break; 350 351 case NestedNameSpecifier::Identifier: 352 case NestedNameSpecifier::Namespace: 353 case NestedNameSpecifier::NamespaceAlias: 354 case NestedNameSpecifier::Super: 355 // The location of the identifier or namespace name. 356 Length += sizeof(unsigned); 357 break; 358 359 case NestedNameSpecifier::TypeSpecWithTemplate: 360 case NestedNameSpecifier::TypeSpec: 361 // The "void*" that points at the TypeLoc data. 362 // Note: the 'template' keyword is part of the TypeLoc. 363 Length += sizeof(void *); 364 break; 365 } 366 367 return Length; 368 } 369 370 unsigned 371 NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 372 unsigned Length = 0; 373 for (; Qualifier; Qualifier = Qualifier->getPrefix()) 374 Length += getLocalDataLength(Qualifier); 375 return Length; 376 } 377 378 namespace { 379 /// \brief Load a (possibly unaligned) source location from a given address 380 /// and offset. 381 SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 382 unsigned Raw; 383 memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 384 return SourceLocation::getFromRawEncoding(Raw); 385 } 386 387 /// \brief Load a (possibly unaligned) pointer from a given address and 388 /// offset. 389 void *LoadPointer(void *Data, unsigned Offset) { 390 void *Result; 391 memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 392 return Result; 393 } 394 } 395 396 SourceRange NestedNameSpecifierLoc::getSourceRange() const { 397 if (!Qualifier) 398 return SourceRange(); 399 400 NestedNameSpecifierLoc First = *this; 401 while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 402 First = Prefix; 403 404 return SourceRange(First.getLocalSourceRange().getBegin(), 405 getLocalSourceRange().getEnd()); 406 } 407 408 SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 409 if (!Qualifier) 410 return SourceRange(); 411 412 unsigned Offset = getDataLength(Qualifier->getPrefix()); 413 switch (Qualifier->getKind()) { 414 case NestedNameSpecifier::Global: 415 return LoadSourceLocation(Data, Offset); 416 417 case NestedNameSpecifier::Identifier: 418 case NestedNameSpecifier::Namespace: 419 case NestedNameSpecifier::NamespaceAlias: 420 case NestedNameSpecifier::Super: 421 return SourceRange(LoadSourceLocation(Data, Offset), 422 LoadSourceLocation(Data, Offset + sizeof(unsigned))); 423 424 case NestedNameSpecifier::TypeSpecWithTemplate: 425 case NestedNameSpecifier::TypeSpec: { 426 // The "void*" that points at the TypeLoc data. 427 // Note: the 'template' keyword is part of the TypeLoc. 428 void *TypeData = LoadPointer(Data, Offset); 429 TypeLoc TL(Qualifier->getAsType(), TypeData); 430 return SourceRange(TL.getBeginLoc(), 431 LoadSourceLocation(Data, Offset + sizeof(void*))); 432 } 433 } 434 435 llvm_unreachable("Invalid NNS Kind!"); 436 } 437 438 TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 439 assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || 440 Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && 441 "Nested-name-specifier location is not a type"); 442 443 // The "void*" that points at the TypeLoc data. 444 unsigned Offset = getDataLength(Qualifier->getPrefix()); 445 void *TypeData = LoadPointer(Data, Offset); 446 return TypeLoc(Qualifier->getAsType(), TypeData); 447 } 448 449 namespace { 450 void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 451 unsigned &BufferCapacity) { 452 if (Start == End) 453 return; 454 455 if (BufferSize + (End - Start) > BufferCapacity) { 456 // Reallocate the buffer. 457 unsigned NewCapacity = std::max( 458 (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), 459 (unsigned)(BufferSize + (End - Start))); 460 char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); 461 if (BufferCapacity) { 462 memcpy(NewBuffer, Buffer, BufferSize); 463 free(Buffer); 464 } 465 Buffer = NewBuffer; 466 BufferCapacity = NewCapacity; 467 } 468 469 memcpy(Buffer + BufferSize, Start, End - Start); 470 BufferSize += End-Start; 471 } 472 473 /// \brief Save a source location to the given buffer. 474 void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 475 unsigned &BufferSize, unsigned &BufferCapacity) { 476 unsigned Raw = Loc.getRawEncoding(); 477 Append(reinterpret_cast<char *>(&Raw), 478 reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 479 Buffer, BufferSize, BufferCapacity); 480 } 481 482 /// \brief Save a pointer to the given buffer. 483 void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 484 unsigned &BufferCapacity) { 485 Append(reinterpret_cast<char *>(&Ptr), 486 reinterpret_cast<char *>(&Ptr) + sizeof(void *), 487 Buffer, BufferSize, BufferCapacity); 488 } 489 } 490 491 NestedNameSpecifierLocBuilder:: 492 NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 493 : Representation(Other.Representation), Buffer(nullptr), 494 BufferSize(0), BufferCapacity(0) 495 { 496 if (!Other.Buffer) 497 return; 498 499 if (Other.BufferCapacity == 0) { 500 // Shallow copy is okay. 501 Buffer = Other.Buffer; 502 BufferSize = Other.BufferSize; 503 return; 504 } 505 506 // Deep copy 507 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 508 BufferCapacity); 509 } 510 511 NestedNameSpecifierLocBuilder & 512 NestedNameSpecifierLocBuilder:: 513 operator=(const NestedNameSpecifierLocBuilder &Other) { 514 Representation = Other.Representation; 515 516 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 517 // Re-use our storage. 518 BufferSize = Other.BufferSize; 519 memcpy(Buffer, Other.Buffer, BufferSize); 520 return *this; 521 } 522 523 // Free our storage, if we have any. 524 if (BufferCapacity) { 525 free(Buffer); 526 BufferCapacity = 0; 527 } 528 529 if (!Other.Buffer) { 530 // Empty. 531 Buffer = nullptr; 532 BufferSize = 0; 533 return *this; 534 } 535 536 if (Other.BufferCapacity == 0) { 537 // Shallow copy is okay. 538 Buffer = Other.Buffer; 539 BufferSize = Other.BufferSize; 540 return *this; 541 } 542 543 // Deep copy. 544 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 545 BufferCapacity); 546 return *this; 547 } 548 549 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 550 SourceLocation TemplateKWLoc, 551 TypeLoc TL, 552 SourceLocation ColonColonLoc) { 553 Representation = NestedNameSpecifier::Create(Context, Representation, 554 TemplateKWLoc.isValid(), 555 TL.getTypePtr()); 556 557 // Push source-location info into the buffer. 558 SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 559 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 560 } 561 562 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 563 IdentifierInfo *Identifier, 564 SourceLocation IdentifierLoc, 565 SourceLocation ColonColonLoc) { 566 Representation = NestedNameSpecifier::Create(Context, Representation, 567 Identifier); 568 569 // Push source-location info into the buffer. 570 SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 571 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 572 } 573 574 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 575 NamespaceDecl *Namespace, 576 SourceLocation NamespaceLoc, 577 SourceLocation ColonColonLoc) { 578 Representation = NestedNameSpecifier::Create(Context, Representation, 579 Namespace); 580 581 // Push source-location info into the buffer. 582 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 583 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 584 } 585 586 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 587 NamespaceAliasDecl *Alias, 588 SourceLocation AliasLoc, 589 SourceLocation ColonColonLoc) { 590 Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 591 592 // Push source-location info into the buffer. 593 SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 594 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 595 } 596 597 void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 598 SourceLocation ColonColonLoc) { 599 assert(!Representation && "Already have a nested-name-specifier!?"); 600 Representation = NestedNameSpecifier::GlobalSpecifier(Context); 601 602 // Push source-location info into the buffer. 603 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 604 } 605 606 void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, 607 CXXRecordDecl *RD, 608 SourceLocation SuperLoc, 609 SourceLocation ColonColonLoc) { 610 Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); 611 612 // Push source-location info into the buffer. 613 SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); 614 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 615 } 616 617 void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 618 NestedNameSpecifier *Qualifier, 619 SourceRange R) { 620 Representation = Qualifier; 621 622 // Construct bogus (but well-formed) source information for the 623 // nested-name-specifier. 624 BufferSize = 0; 625 SmallVector<NestedNameSpecifier *, 4> Stack; 626 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 627 Stack.push_back(NNS); 628 while (!Stack.empty()) { 629 NestedNameSpecifier *NNS = Stack.pop_back_val(); 630 switch (NNS->getKind()) { 631 case NestedNameSpecifier::Identifier: 632 case NestedNameSpecifier::Namespace: 633 case NestedNameSpecifier::NamespaceAlias: 634 SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 635 break; 636 637 case NestedNameSpecifier::TypeSpec: 638 case NestedNameSpecifier::TypeSpecWithTemplate: { 639 TypeSourceInfo *TSInfo 640 = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 641 R.getBegin()); 642 SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 643 BufferCapacity); 644 break; 645 } 646 647 case NestedNameSpecifier::Global: 648 case NestedNameSpecifier::Super: 649 break; 650 } 651 652 // Save the location of the '::'. 653 SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 654 Buffer, BufferSize, BufferCapacity); 655 } 656 } 657 658 void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 659 if (BufferCapacity) 660 free(Buffer); 661 662 if (!Other) { 663 Representation = nullptr; 664 BufferSize = 0; 665 return; 666 } 667 668 // Rather than copying the data (which is wasteful), "adopt" the 669 // pointer (which points into the ASTContext) but set the capacity to zero to 670 // indicate that we don't own it. 671 Representation = Other.getNestedNameSpecifier(); 672 Buffer = static_cast<char *>(Other.getOpaqueData()); 673 BufferSize = Other.getDataLength(); 674 BufferCapacity = 0; 675 } 676 677 NestedNameSpecifierLoc 678 NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 679 if (!Representation) 680 return NestedNameSpecifierLoc(); 681 682 // If we adopted our data pointer from elsewhere in the AST context, there's 683 // no need to copy the memory. 684 if (BufferCapacity == 0) 685 return NestedNameSpecifierLoc(Representation, Buffer); 686 687 // FIXME: After copying the source-location information, should we free 688 // our (temporary) buffer and adopt the ASTContext-allocated memory? 689 // Doing so would optimize repeated calls to getWithLocInContext(). 690 void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); 691 memcpy(Mem, Buffer, BufferSize); 692 return NestedNameSpecifierLoc(Representation, Mem); 693 } 694