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 LLVM_FALLTHROUGH; 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, alignof(void *)); 691 memcpy(Mem, Buffer, BufferSize); 692 return NestedNameSpecifierLoc(Representation, Mem); 693 } 694