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/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 NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const { 202 switch (getKind()) { 203 case Identifier: { 204 // Identifier specifiers always represent dependent types 205 auto F = NestedNameSpecifierDependence::Dependent | 206 NestedNameSpecifierDependence::Instantiation; 207 // Prefix can contain unexpanded template parameters. 208 if (getPrefix()) 209 return F | getPrefix()->getDependence(); 210 return F; 211 } 212 213 case Namespace: 214 case NamespaceAlias: 215 case Global: 216 return NestedNameSpecifierDependence::None; 217 218 case Super: { 219 CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier); 220 for (const auto &Base : RD->bases()) 221 if (Base.getType()->isDependentType()) 222 // FIXME: must also be instantiation-dependent. 223 return NestedNameSpecifierDependence::Dependent; 224 return NestedNameSpecifierDependence::None; 225 } 226 227 case TypeSpec: 228 case TypeSpecWithTemplate: 229 return toNestedNameSpecifierDependendence(getAsType()->getDependence()); 230 } 231 llvm_unreachable("Invalid NNS Kind!"); 232 } 233 234 bool NestedNameSpecifier::isDependent() const { 235 return getDependence() & NestedNameSpecifierDependence::Dependent; 236 } 237 238 bool NestedNameSpecifier::isInstantiationDependent() const { 239 return getDependence() & NestedNameSpecifierDependence::Instantiation; 240 } 241 242 bool NestedNameSpecifier::containsUnexpandedParameterPack() const { 243 return getDependence() & NestedNameSpecifierDependence::UnexpandedPack; 244 } 245 246 bool NestedNameSpecifier::containsErrors() const { 247 return getDependence() & NestedNameSpecifierDependence::Error; 248 } 249 250 /// Print this nested name specifier to the given output 251 /// stream. 252 void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, 253 bool ResolveTemplateArguments) const { 254 if (getPrefix()) 255 getPrefix()->print(OS, Policy); 256 257 switch (getKind()) { 258 case Identifier: 259 OS << getAsIdentifier()->getName(); 260 break; 261 262 case Namespace: 263 if (getAsNamespace()->isAnonymousNamespace()) 264 return; 265 266 OS << getAsNamespace()->getName(); 267 break; 268 269 case NamespaceAlias: 270 OS << getAsNamespaceAlias()->getName(); 271 break; 272 273 case Global: 274 break; 275 276 case Super: 277 OS << "__super"; 278 break; 279 280 case TypeSpecWithTemplate: 281 OS << "template "; 282 // Fall through to print the type. 283 LLVM_FALLTHROUGH; 284 285 case TypeSpec: { 286 const auto *Record = 287 dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl()); 288 if (ResolveTemplateArguments && Record) { 289 // Print the type trait with resolved template parameters. 290 Record->printName(OS); 291 printTemplateArgumentList( 292 OS, Record->getTemplateArgs().asArray(), Policy, 293 Record->getSpecializedTemplate()->getTemplateParameters()); 294 break; 295 } 296 const Type *T = getAsType(); 297 298 PrintingPolicy InnerPolicy(Policy); 299 InnerPolicy.SuppressScope = true; 300 301 // Nested-name-specifiers are intended to contain minimally-qualified 302 // types. An actual ElaboratedType will not occur, since we'll store 303 // just the type that is referred to in the nested-name-specifier (e.g., 304 // a TypedefType, TagType, etc.). However, when we are dealing with 305 // dependent template-id types (e.g., Outer<T>::template Inner<U>), 306 // the type requires its own nested-name-specifier for uniqueness, so we 307 // suppress that nested-name-specifier during printing. 308 assert(!isa<ElaboratedType>(T) && 309 "Elaborated type in nested-name-specifier"); 310 if (const TemplateSpecializationType *SpecType 311 = dyn_cast<TemplateSpecializationType>(T)) { 312 // Print the template name without its corresponding 313 // nested-name-specifier. 314 SpecType->getTemplateName().print(OS, InnerPolicy, 315 TemplateName::Qualified::None); 316 317 // Print the template argument list. 318 printTemplateArgumentList(OS, SpecType->template_arguments(), 319 InnerPolicy); 320 } else if (const auto *DepSpecType = 321 dyn_cast<DependentTemplateSpecializationType>(T)) { 322 // Print the template name without its corresponding 323 // nested-name-specifier. 324 OS << DepSpecType->getIdentifier()->getName(); 325 // Print the template argument list. 326 printTemplateArgumentList(OS, DepSpecType->template_arguments(), 327 InnerPolicy); 328 } else { 329 // Print the type normally 330 QualType(T, 0).print(OS, InnerPolicy); 331 } 332 break; 333 } 334 } 335 336 OS << "::"; 337 } 338 339 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { 340 dump(llvm::errs(), LO); 341 } 342 343 LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); } 344 345 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const { 346 LangOptions LO; 347 dump(OS, LO); 348 } 349 350 LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS, 351 const LangOptions &LO) const { 352 print(OS, PrintingPolicy(LO)); 353 } 354 355 unsigned 356 NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 357 assert(Qualifier && "Expected a non-NULL qualifier"); 358 359 // Location of the trailing '::'. 360 unsigned Length = sizeof(SourceLocation::UIntTy); 361 362 switch (Qualifier->getKind()) { 363 case NestedNameSpecifier::Global: 364 // Nothing more to add. 365 break; 366 367 case NestedNameSpecifier::Identifier: 368 case NestedNameSpecifier::Namespace: 369 case NestedNameSpecifier::NamespaceAlias: 370 case NestedNameSpecifier::Super: 371 // The location of the identifier or namespace name. 372 Length += sizeof(SourceLocation::UIntTy); 373 break; 374 375 case NestedNameSpecifier::TypeSpecWithTemplate: 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::getSourceRange() const { 411 if (!Qualifier) 412 return SourceRange(); 413 414 NestedNameSpecifierLoc First = *this; 415 while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 416 First = Prefix; 417 418 return SourceRange(First.getLocalSourceRange().getBegin(), 419 getLocalSourceRange().getEnd()); 420 } 421 422 SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 423 if (!Qualifier) 424 return SourceRange(); 425 426 unsigned Offset = getDataLength(Qualifier->getPrefix()); 427 switch (Qualifier->getKind()) { 428 case NestedNameSpecifier::Global: 429 return LoadSourceLocation(Data, Offset); 430 431 case NestedNameSpecifier::Identifier: 432 case NestedNameSpecifier::Namespace: 433 case NestedNameSpecifier::NamespaceAlias: 434 case NestedNameSpecifier::Super: 435 return SourceRange( 436 LoadSourceLocation(Data, Offset), 437 LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy))); 438 439 case NestedNameSpecifier::TypeSpecWithTemplate: 440 case NestedNameSpecifier::TypeSpec: { 441 // The "void*" that points at the TypeLoc data. 442 // Note: the 'template' keyword is part of the TypeLoc. 443 void *TypeData = LoadPointer(Data, Offset); 444 TypeLoc TL(Qualifier->getAsType(), TypeData); 445 return SourceRange(TL.getBeginLoc(), 446 LoadSourceLocation(Data, Offset + sizeof(void*))); 447 } 448 } 449 450 llvm_unreachable("Invalid NNS Kind!"); 451 } 452 453 TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 454 if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec && 455 Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate) 456 return TypeLoc(); 457 458 // The "void*" that points at the TypeLoc data. 459 unsigned Offset = getDataLength(Qualifier->getPrefix()); 460 void *TypeData = LoadPointer(Data, Offset); 461 return TypeLoc(Qualifier->getAsType(), TypeData); 462 } 463 464 static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 465 unsigned &BufferCapacity) { 466 if (Start == End) 467 return; 468 469 if (BufferSize + (End - Start) > BufferCapacity) { 470 // Reallocate the buffer. 471 unsigned NewCapacity = std::max( 472 (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), 473 (unsigned)(BufferSize + (End - Start))); 474 if (!BufferCapacity) { 475 char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity)); 476 if (Buffer) 477 memcpy(NewBuffer, Buffer, BufferSize); 478 Buffer = NewBuffer; 479 } else { 480 Buffer = static_cast<char *>(llvm::safe_realloc(Buffer, NewCapacity)); 481 } 482 BufferCapacity = NewCapacity; 483 } 484 assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy"); 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 SourceLocation::UIntTy Raw = Loc.getRawEncoding(); 493 Append(reinterpret_cast<char *>(&Raw), 494 reinterpret_cast<char *>(&Raw) + sizeof(Raw), Buffer, BufferSize, 495 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