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