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