1 //===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the NestedNameSpecifier class, which represents 10 // a C++ nested-name-specifier. 11 // 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/DeclTemplate.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 /// 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 /// 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 /// 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 /// 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 /// 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 /// Print this nested name specifier to the given output 272 /// stream. 273 void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, 274 bool ResolveTemplateArguments) const { 275 if (getPrefix()) 276 getPrefix()->print(OS, Policy); 277 278 switch (getKind()) { 279 case Identifier: 280 OS << getAsIdentifier()->getName(); 281 break; 282 283 case Namespace: 284 if (getAsNamespace()->isAnonymousNamespace()) 285 return; 286 287 OS << getAsNamespace()->getName(); 288 break; 289 290 case NamespaceAlias: 291 OS << getAsNamespaceAlias()->getName(); 292 break; 293 294 case Global: 295 break; 296 297 case Super: 298 OS << "__super"; 299 break; 300 301 case TypeSpecWithTemplate: 302 OS << "template "; 303 // Fall through to print the type. 304 LLVM_FALLTHROUGH; 305 306 case TypeSpec: { 307 const auto *Record = 308 dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl()); 309 if (ResolveTemplateArguments && Record) { 310 // Print the type trait with resolved template parameters. 311 Record->printName(OS); 312 printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(), 313 Policy); 314 break; 315 } 316 const Type *T = getAsType(); 317 318 PrintingPolicy InnerPolicy(Policy); 319 InnerPolicy.SuppressScope = true; 320 321 // Nested-name-specifiers are intended to contain minimally-qualified 322 // types. An actual ElaboratedType will not occur, since we'll store 323 // just the type that is referred to in the nested-name-specifier (e.g., 324 // a TypedefType, TagType, etc.). However, when we are dealing with 325 // dependent template-id types (e.g., Outer<T>::template Inner<U>), 326 // the type requires its own nested-name-specifier for uniqueness, so we 327 // suppress that nested-name-specifier during printing. 328 assert(!isa<ElaboratedType>(T) && 329 "Elaborated type in nested-name-specifier"); 330 if (const TemplateSpecializationType *SpecType 331 = dyn_cast<TemplateSpecializationType>(T)) { 332 // Print the template name without its corresponding 333 // nested-name-specifier. 334 SpecType->getTemplateName().print(OS, InnerPolicy, true); 335 336 // Print the template argument list. 337 printTemplateArgumentList(OS, SpecType->template_arguments(), 338 InnerPolicy); 339 } else { 340 // Print the type normally 341 QualType(T, 0).print(OS, InnerPolicy); 342 } 343 break; 344 } 345 } 346 347 OS << "::"; 348 } 349 350 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { 351 dump(llvm::errs(), LO); 352 } 353 354 LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); } 355 356 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const { 357 LangOptions LO; 358 dump(OS, LO); 359 } 360 361 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS, 362 const LangOptions &LO) const { 363 print(OS, PrintingPolicy(LO)); 364 } 365 366 unsigned 367 NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 368 assert(Qualifier && "Expected a non-NULL qualifier"); 369 370 // Location of the trailing '::'. 371 unsigned Length = sizeof(unsigned); 372 373 switch (Qualifier->getKind()) { 374 case NestedNameSpecifier::Global: 375 // Nothing more to add. 376 break; 377 378 case NestedNameSpecifier::Identifier: 379 case NestedNameSpecifier::Namespace: 380 case NestedNameSpecifier::NamespaceAlias: 381 case NestedNameSpecifier::Super: 382 // The location of the identifier or namespace name. 383 Length += sizeof(unsigned); 384 break; 385 386 case NestedNameSpecifier::TypeSpecWithTemplate: 387 case NestedNameSpecifier::TypeSpec: 388 // The "void*" that points at the TypeLoc data. 389 // Note: the 'template' keyword is part of the TypeLoc. 390 Length += sizeof(void *); 391 break; 392 } 393 394 return Length; 395 } 396 397 unsigned 398 NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 399 unsigned Length = 0; 400 for (; Qualifier; Qualifier = Qualifier->getPrefix()) 401 Length += getLocalDataLength(Qualifier); 402 return Length; 403 } 404 405 /// Load a (possibly unaligned) source location from a given address 406 /// and offset. 407 static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 408 unsigned Raw; 409 memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 410 return SourceLocation::getFromRawEncoding(Raw); 411 } 412 413 /// Load a (possibly unaligned) pointer from a given address and 414 /// offset. 415 static void *LoadPointer(void *Data, unsigned Offset) { 416 void *Result; 417 memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 418 return Result; 419 } 420 421 SourceRange NestedNameSpecifierLoc::getSourceRange() const { 422 if (!Qualifier) 423 return SourceRange(); 424 425 NestedNameSpecifierLoc First = *this; 426 while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 427 First = Prefix; 428 429 return SourceRange(First.getLocalSourceRange().getBegin(), 430 getLocalSourceRange().getEnd()); 431 } 432 433 SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 434 if (!Qualifier) 435 return SourceRange(); 436 437 unsigned Offset = getDataLength(Qualifier->getPrefix()); 438 switch (Qualifier->getKind()) { 439 case NestedNameSpecifier::Global: 440 return LoadSourceLocation(Data, Offset); 441 442 case NestedNameSpecifier::Identifier: 443 case NestedNameSpecifier::Namespace: 444 case NestedNameSpecifier::NamespaceAlias: 445 case NestedNameSpecifier::Super: 446 return SourceRange(LoadSourceLocation(Data, Offset), 447 LoadSourceLocation(Data, Offset + sizeof(unsigned))); 448 449 case NestedNameSpecifier::TypeSpecWithTemplate: 450 case NestedNameSpecifier::TypeSpec: { 451 // The "void*" that points at the TypeLoc data. 452 // Note: the 'template' keyword is part of the TypeLoc. 453 void *TypeData = LoadPointer(Data, Offset); 454 TypeLoc TL(Qualifier->getAsType(), TypeData); 455 return SourceRange(TL.getBeginLoc(), 456 LoadSourceLocation(Data, Offset + sizeof(void*))); 457 } 458 } 459 460 llvm_unreachable("Invalid NNS Kind!"); 461 } 462 463 TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 464 if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec && 465 Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate) 466 return TypeLoc(); 467 468 // The "void*" that points at the TypeLoc data. 469 unsigned Offset = getDataLength(Qualifier->getPrefix()); 470 void *TypeData = LoadPointer(Data, Offset); 471 return TypeLoc(Qualifier->getAsType(), TypeData); 472 } 473 474 static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 475 unsigned &BufferCapacity) { 476 if (Start == End) 477 return; 478 479 if (BufferSize + (End - Start) > BufferCapacity) { 480 // Reallocate the buffer. 481 unsigned NewCapacity = std::max( 482 (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), 483 (unsigned)(BufferSize + (End - Start))); 484 char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity)); 485 if (BufferCapacity) { 486 memcpy(NewBuffer, Buffer, BufferSize); 487 free(Buffer); 488 } 489 Buffer = NewBuffer; 490 BufferCapacity = NewCapacity; 491 } 492 assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy"); 493 memcpy(Buffer + BufferSize, Start, End - Start); 494 BufferSize += End - Start; 495 } 496 497 /// Save a source location to the given buffer. 498 static void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 499 unsigned &BufferSize, unsigned &BufferCapacity) { 500 unsigned Raw = Loc.getRawEncoding(); 501 Append(reinterpret_cast<char *>(&Raw), 502 reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 503 Buffer, BufferSize, BufferCapacity); 504 } 505 506 /// Save a pointer to the given buffer. 507 static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 508 unsigned &BufferCapacity) { 509 Append(reinterpret_cast<char *>(&Ptr), 510 reinterpret_cast<char *>(&Ptr) + sizeof(void *), 511 Buffer, BufferSize, BufferCapacity); 512 } 513 514 NestedNameSpecifierLocBuilder:: 515 NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 516 : Representation(Other.Representation) { 517 if (!Other.Buffer) 518 return; 519 520 if (Other.BufferCapacity == 0) { 521 // Shallow copy is okay. 522 Buffer = Other.Buffer; 523 BufferSize = Other.BufferSize; 524 return; 525 } 526 527 // Deep copy 528 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 529 BufferCapacity); 530 } 531 532 NestedNameSpecifierLocBuilder & 533 NestedNameSpecifierLocBuilder:: 534 operator=(const NestedNameSpecifierLocBuilder &Other) { 535 Representation = Other.Representation; 536 537 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 538 // Re-use our storage. 539 BufferSize = Other.BufferSize; 540 memcpy(Buffer, Other.Buffer, BufferSize); 541 return *this; 542 } 543 544 // Free our storage, if we have any. 545 if (BufferCapacity) { 546 free(Buffer); 547 BufferCapacity = 0; 548 } 549 550 if (!Other.Buffer) { 551 // Empty. 552 Buffer = nullptr; 553 BufferSize = 0; 554 return *this; 555 } 556 557 if (Other.BufferCapacity == 0) { 558 // Shallow copy is okay. 559 Buffer = Other.Buffer; 560 BufferSize = Other.BufferSize; 561 return *this; 562 } 563 564 // Deep copy. 565 BufferSize = 0; 566 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 567 BufferCapacity); 568 return *this; 569 } 570 571 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 572 SourceLocation TemplateKWLoc, 573 TypeLoc TL, 574 SourceLocation ColonColonLoc) { 575 Representation = NestedNameSpecifier::Create(Context, Representation, 576 TemplateKWLoc.isValid(), 577 TL.getTypePtr()); 578 579 // Push source-location info into the buffer. 580 SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 581 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 582 } 583 584 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 585 IdentifierInfo *Identifier, 586 SourceLocation IdentifierLoc, 587 SourceLocation ColonColonLoc) { 588 Representation = NestedNameSpecifier::Create(Context, Representation, 589 Identifier); 590 591 // Push source-location info into the buffer. 592 SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 593 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 594 } 595 596 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 597 NamespaceDecl *Namespace, 598 SourceLocation NamespaceLoc, 599 SourceLocation ColonColonLoc) { 600 Representation = NestedNameSpecifier::Create(Context, Representation, 601 Namespace); 602 603 // Push source-location info into the buffer. 604 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 605 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 606 } 607 608 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 609 NamespaceAliasDecl *Alias, 610 SourceLocation AliasLoc, 611 SourceLocation ColonColonLoc) { 612 Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 613 614 // Push source-location info into the buffer. 615 SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 616 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 617 } 618 619 void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 620 SourceLocation ColonColonLoc) { 621 assert(!Representation && "Already have a nested-name-specifier!?"); 622 Representation = NestedNameSpecifier::GlobalSpecifier(Context); 623 624 // Push source-location info into the buffer. 625 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 626 } 627 628 void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, 629 CXXRecordDecl *RD, 630 SourceLocation SuperLoc, 631 SourceLocation ColonColonLoc) { 632 Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); 633 634 // Push source-location info into the buffer. 635 SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); 636 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 637 } 638 639 void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 640 NestedNameSpecifier *Qualifier, 641 SourceRange R) { 642 Representation = Qualifier; 643 644 // Construct bogus (but well-formed) source information for the 645 // nested-name-specifier. 646 BufferSize = 0; 647 SmallVector<NestedNameSpecifier *, 4> Stack; 648 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 649 Stack.push_back(NNS); 650 while (!Stack.empty()) { 651 NestedNameSpecifier *NNS = Stack.pop_back_val(); 652 switch (NNS->getKind()) { 653 case NestedNameSpecifier::Identifier: 654 case NestedNameSpecifier::Namespace: 655 case NestedNameSpecifier::NamespaceAlias: 656 SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 657 break; 658 659 case NestedNameSpecifier::TypeSpec: 660 case NestedNameSpecifier::TypeSpecWithTemplate: { 661 TypeSourceInfo *TSInfo 662 = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 663 R.getBegin()); 664 SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 665 BufferCapacity); 666 break; 667 } 668 669 case NestedNameSpecifier::Global: 670 case NestedNameSpecifier::Super: 671 break; 672 } 673 674 // Save the location of the '::'. 675 SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 676 Buffer, BufferSize, BufferCapacity); 677 } 678 } 679 680 void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 681 if (BufferCapacity) 682 free(Buffer); 683 684 if (!Other) { 685 Representation = nullptr; 686 BufferSize = 0; 687 return; 688 } 689 690 // Rather than copying the data (which is wasteful), "adopt" the 691 // pointer (which points into the ASTContext) but set the capacity to zero to 692 // indicate that we don't own it. 693 Representation = Other.getNestedNameSpecifier(); 694 Buffer = static_cast<char *>(Other.getOpaqueData()); 695 BufferSize = Other.getDataLength(); 696 BufferCapacity = 0; 697 } 698 699 NestedNameSpecifierLoc 700 NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 701 if (!Representation) 702 return NestedNameSpecifierLoc(); 703 704 // If we adopted our data pointer from elsewhere in the AST context, there's 705 // no need to copy the memory. 706 if (BufferCapacity == 0) 707 return NestedNameSpecifierLoc(Representation, Buffer); 708 709 // FIXME: After copying the source-location information, should we free 710 // our (temporary) buffer and adopt the ASTContext-allocated memory? 711 // Doing so would optimize repeated calls to getWithLocInContext(). 712 void *Mem = Context.Allocate(BufferSize, alignof(void *)); 713 memcpy(Mem, Buffer, BufferSize); 714 return NestedNameSpecifierLoc(Representation, Mem); 715 } 716