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