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 /// 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 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 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { 343 dump(llvm::errs(), LO); 344 } 345 346 LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); } 347 348 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const { 349 LangOptions LO; 350 dump(OS, LO); 351 } 352 353 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS, 354 const LangOptions &LO) const { 355 print(OS, PrintingPolicy(LO)); 356 } 357 358 unsigned 359 NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 360 assert(Qualifier && "Expected a non-NULL qualifier"); 361 362 // Location of the trailing '::'. 363 unsigned Length = sizeof(unsigned); 364 365 switch (Qualifier->getKind()) { 366 case NestedNameSpecifier::Global: 367 // Nothing more to add. 368 break; 369 370 case NestedNameSpecifier::Identifier: 371 case NestedNameSpecifier::Namespace: 372 case NestedNameSpecifier::NamespaceAlias: 373 case NestedNameSpecifier::Super: 374 // The location of the identifier or namespace name. 375 Length += sizeof(unsigned); 376 break; 377 378 case NestedNameSpecifier::TypeSpecWithTemplate: 379 case NestedNameSpecifier::TypeSpec: 380 // The "void*" that points at the TypeLoc data. 381 // Note: the 'template' keyword is part of the TypeLoc. 382 Length += sizeof(void *); 383 break; 384 } 385 386 return Length; 387 } 388 389 unsigned 390 NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 391 unsigned Length = 0; 392 for (; Qualifier; Qualifier = Qualifier->getPrefix()) 393 Length += getLocalDataLength(Qualifier); 394 return Length; 395 } 396 397 /// Load a (possibly unaligned) source location from a given address 398 /// and offset. 399 static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 400 unsigned Raw; 401 memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 402 return SourceLocation::getFromRawEncoding(Raw); 403 } 404 405 /// Load a (possibly unaligned) pointer from a given address and 406 /// offset. 407 static void *LoadPointer(void *Data, unsigned Offset) { 408 void *Result; 409 memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 410 return Result; 411 } 412 413 SourceRange NestedNameSpecifierLoc::getSourceRange() const { 414 if (!Qualifier) 415 return SourceRange(); 416 417 NestedNameSpecifierLoc First = *this; 418 while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 419 First = Prefix; 420 421 return SourceRange(First.getLocalSourceRange().getBegin(), 422 getLocalSourceRange().getEnd()); 423 } 424 425 SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 426 if (!Qualifier) 427 return SourceRange(); 428 429 unsigned Offset = getDataLength(Qualifier->getPrefix()); 430 switch (Qualifier->getKind()) { 431 case NestedNameSpecifier::Global: 432 return LoadSourceLocation(Data, Offset); 433 434 case NestedNameSpecifier::Identifier: 435 case NestedNameSpecifier::Namespace: 436 case NestedNameSpecifier::NamespaceAlias: 437 case NestedNameSpecifier::Super: 438 return SourceRange(LoadSourceLocation(Data, Offset), 439 LoadSourceLocation(Data, Offset + sizeof(unsigned))); 440 441 case NestedNameSpecifier::TypeSpecWithTemplate: 442 case NestedNameSpecifier::TypeSpec: { 443 // The "void*" that points at the TypeLoc data. 444 // Note: the 'template' keyword is part of the TypeLoc. 445 void *TypeData = LoadPointer(Data, Offset); 446 TypeLoc TL(Qualifier->getAsType(), TypeData); 447 return SourceRange(TL.getBeginLoc(), 448 LoadSourceLocation(Data, Offset + sizeof(void*))); 449 } 450 } 451 452 llvm_unreachable("Invalid NNS Kind!"); 453 } 454 455 TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 456 assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || 457 Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && 458 "Nested-name-specifier location is not a type"); 459 460 // The "void*" that points at the TypeLoc data. 461 unsigned Offset = getDataLength(Qualifier->getPrefix()); 462 void *TypeData = LoadPointer(Data, Offset); 463 return TypeLoc(Qualifier->getAsType(), TypeData); 464 } 465 466 static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 467 unsigned &BufferCapacity) { 468 if (Start == End) 469 return; 470 471 if (BufferSize + (End - Start) > BufferCapacity) { 472 // Reallocate the buffer. 473 unsigned NewCapacity = std::max( 474 (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), 475 (unsigned)(BufferSize + (End - Start))); 476 char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity)); 477 if (BufferCapacity) { 478 memcpy(NewBuffer, Buffer, BufferSize); 479 free(Buffer); 480 } 481 Buffer = NewBuffer; 482 BufferCapacity = NewCapacity; 483 } 484 485 memcpy(Buffer + BufferSize, Start, End - Start); 486 BufferSize += End-Start; 487 } 488 489 /// Save a source location to the given buffer. 490 static void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 491 unsigned &BufferSize, unsigned &BufferCapacity) { 492 unsigned Raw = Loc.getRawEncoding(); 493 Append(reinterpret_cast<char *>(&Raw), 494 reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 495 Buffer, BufferSize, BufferCapacity); 496 } 497 498 /// Save a pointer to the given buffer. 499 static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 500 unsigned &BufferCapacity) { 501 Append(reinterpret_cast<char *>(&Ptr), 502 reinterpret_cast<char *>(&Ptr) + sizeof(void *), 503 Buffer, BufferSize, BufferCapacity); 504 } 505 506 NestedNameSpecifierLocBuilder:: 507 NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 508 : Representation(Other.Representation) { 509 if (!Other.Buffer) 510 return; 511 512 if (Other.BufferCapacity == 0) { 513 // Shallow copy is okay. 514 Buffer = Other.Buffer; 515 BufferSize = Other.BufferSize; 516 return; 517 } 518 519 // Deep copy 520 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 521 BufferCapacity); 522 } 523 524 NestedNameSpecifierLocBuilder & 525 NestedNameSpecifierLocBuilder:: 526 operator=(const NestedNameSpecifierLocBuilder &Other) { 527 Representation = Other.Representation; 528 529 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 530 // Re-use our storage. 531 BufferSize = Other.BufferSize; 532 memcpy(Buffer, Other.Buffer, BufferSize); 533 return *this; 534 } 535 536 // Free our storage, if we have any. 537 if (BufferCapacity) { 538 free(Buffer); 539 BufferCapacity = 0; 540 } 541 542 if (!Other.Buffer) { 543 // Empty. 544 Buffer = nullptr; 545 BufferSize = 0; 546 return *this; 547 } 548 549 if (Other.BufferCapacity == 0) { 550 // Shallow copy is okay. 551 Buffer = Other.Buffer; 552 BufferSize = Other.BufferSize; 553 return *this; 554 } 555 556 // Deep copy. 557 BufferSize = 0; 558 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 559 BufferCapacity); 560 return *this; 561 } 562 563 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 564 SourceLocation TemplateKWLoc, 565 TypeLoc TL, 566 SourceLocation ColonColonLoc) { 567 Representation = NestedNameSpecifier::Create(Context, Representation, 568 TemplateKWLoc.isValid(), 569 TL.getTypePtr()); 570 571 // Push source-location info into the buffer. 572 SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 573 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 574 } 575 576 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 577 IdentifierInfo *Identifier, 578 SourceLocation IdentifierLoc, 579 SourceLocation ColonColonLoc) { 580 Representation = NestedNameSpecifier::Create(Context, Representation, 581 Identifier); 582 583 // Push source-location info into the buffer. 584 SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 585 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 586 } 587 588 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 589 NamespaceDecl *Namespace, 590 SourceLocation NamespaceLoc, 591 SourceLocation ColonColonLoc) { 592 Representation = NestedNameSpecifier::Create(Context, Representation, 593 Namespace); 594 595 // Push source-location info into the buffer. 596 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 597 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 598 } 599 600 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 601 NamespaceAliasDecl *Alias, 602 SourceLocation AliasLoc, 603 SourceLocation ColonColonLoc) { 604 Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 605 606 // Push source-location info into the buffer. 607 SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 608 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 609 } 610 611 void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 612 SourceLocation ColonColonLoc) { 613 assert(!Representation && "Already have a nested-name-specifier!?"); 614 Representation = NestedNameSpecifier::GlobalSpecifier(Context); 615 616 // Push source-location info into the buffer. 617 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 618 } 619 620 void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, 621 CXXRecordDecl *RD, 622 SourceLocation SuperLoc, 623 SourceLocation ColonColonLoc) { 624 Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); 625 626 // Push source-location info into the buffer. 627 SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); 628 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 629 } 630 631 void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 632 NestedNameSpecifier *Qualifier, 633 SourceRange R) { 634 Representation = Qualifier; 635 636 // Construct bogus (but well-formed) source information for the 637 // nested-name-specifier. 638 BufferSize = 0; 639 SmallVector<NestedNameSpecifier *, 4> Stack; 640 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 641 Stack.push_back(NNS); 642 while (!Stack.empty()) { 643 NestedNameSpecifier *NNS = Stack.pop_back_val(); 644 switch (NNS->getKind()) { 645 case NestedNameSpecifier::Identifier: 646 case NestedNameSpecifier::Namespace: 647 case NestedNameSpecifier::NamespaceAlias: 648 SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 649 break; 650 651 case NestedNameSpecifier::TypeSpec: 652 case NestedNameSpecifier::TypeSpecWithTemplate: { 653 TypeSourceInfo *TSInfo 654 = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 655 R.getBegin()); 656 SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 657 BufferCapacity); 658 break; 659 } 660 661 case NestedNameSpecifier::Global: 662 case NestedNameSpecifier::Super: 663 break; 664 } 665 666 // Save the location of the '::'. 667 SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 668 Buffer, BufferSize, BufferCapacity); 669 } 670 } 671 672 void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 673 if (BufferCapacity) 674 free(Buffer); 675 676 if (!Other) { 677 Representation = nullptr; 678 BufferSize = 0; 679 return; 680 } 681 682 // Rather than copying the data (which is wasteful), "adopt" the 683 // pointer (which points into the ASTContext) but set the capacity to zero to 684 // indicate that we don't own it. 685 Representation = Other.getNestedNameSpecifier(); 686 Buffer = static_cast<char *>(Other.getOpaqueData()); 687 BufferSize = Other.getDataLength(); 688 BufferCapacity = 0; 689 } 690 691 NestedNameSpecifierLoc 692 NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 693 if (!Representation) 694 return NestedNameSpecifierLoc(); 695 696 // If we adopted our data pointer from elsewhere in the AST context, there's 697 // no need to copy the memory. 698 if (BufferCapacity == 0) 699 return NestedNameSpecifierLoc(Representation, Buffer); 700 701 // FIXME: After copying the source-location information, should we free 702 // our (temporary) buffer and adopt the ASTContext-allocated memory? 703 // Doing so would optimize repeated calls to getWithLocInContext(). 704 void *Mem = Context.Allocate(BufferSize, alignof(void *)); 705 memcpy(Mem, Buffer, BufferSize); 706 return NestedNameSpecifierLoc(Representation, Mem); 707 } 708