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