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