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