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