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