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) { 322 print(llvm::errs(), PrintingPolicy(LO)); 323} 324 325unsigned 326NestedNameSpecifierLoc::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 356unsigned 357NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 358 unsigned Length = 0; 359 for (; Qualifier; Qualifier = Qualifier->getPrefix()) 360 Length += getLocalDataLength(Qualifier); 361 return Length; 362} 363 364namespace { 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 382SourceRange 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 394SourceRange 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 424TypeLoc 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 435namespace { 436 void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 437 unsigned &BufferCapacity) { 438 if (Start == End) 439 return; 440 441 if (BufferSize + (End - Start) > BufferCapacity) { 442 // Reallocate the buffer. 443 unsigned NewCapacity = std::max( 444 (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), 445 (unsigned)(BufferSize + (End - Start))); 446 char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); 447 if (BufferCapacity) { 448 memcpy(NewBuffer, Buffer, BufferSize); 449 free(Buffer); 450 } 451 Buffer = NewBuffer; 452 BufferCapacity = NewCapacity; 453 } 454 455 memcpy(Buffer + BufferSize, Start, End - Start); 456 BufferSize += End-Start; 457 } 458 459 /// \brief Save a source location to the given buffer. 460 void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 461 unsigned &BufferSize, unsigned &BufferCapacity) { 462 unsigned Raw = Loc.getRawEncoding(); 463 Append(reinterpret_cast<char *>(&Raw), 464 reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 465 Buffer, BufferSize, BufferCapacity); 466 } 467 468 /// \brief Save a pointer to the given buffer. 469 void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 470 unsigned &BufferCapacity) { 471 Append(reinterpret_cast<char *>(&Ptr), 472 reinterpret_cast<char *>(&Ptr) + sizeof(void *), 473 Buffer, BufferSize, BufferCapacity); 474 } 475} 476 477NestedNameSpecifierLocBuilder:: 478NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 479 : Representation(Other.Representation), Buffer(nullptr), 480 BufferSize(0), BufferCapacity(0) 481{ 482 if (!Other.Buffer) 483 return; 484 485 if (Other.BufferCapacity == 0) { 486 // Shallow copy is okay. 487 Buffer = Other.Buffer; 488 BufferSize = Other.BufferSize; 489 return; 490 } 491 492 // Deep copy 493 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 494 BufferCapacity); 495} 496 497NestedNameSpecifierLocBuilder & 498NestedNameSpecifierLocBuilder:: 499operator=(const NestedNameSpecifierLocBuilder &Other) { 500 Representation = Other.Representation; 501 502 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 503 // Re-use our storage. 504 BufferSize = Other.BufferSize; 505 memcpy(Buffer, Other.Buffer, BufferSize); 506 return *this; 507 } 508 509 // Free our storage, if we have any. 510 if (BufferCapacity) { 511 free(Buffer); 512 BufferCapacity = 0; 513 } 514 515 if (!Other.Buffer) { 516 // Empty. 517 Buffer = nullptr; 518 BufferSize = 0; 519 return *this; 520 } 521 522 if (Other.BufferCapacity == 0) { 523 // Shallow copy is okay. 524 Buffer = Other.Buffer; 525 BufferSize = Other.BufferSize; 526 return *this; 527 } 528 529 // Deep copy. 530 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 531 BufferCapacity); 532 return *this; 533} 534 535void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 536 SourceLocation TemplateKWLoc, 537 TypeLoc TL, 538 SourceLocation ColonColonLoc) { 539 Representation = NestedNameSpecifier::Create(Context, Representation, 540 TemplateKWLoc.isValid(), 541 TL.getTypePtr()); 542 543 // Push source-location info into the buffer. 544 SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 545 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 546} 547 548void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 549 IdentifierInfo *Identifier, 550 SourceLocation IdentifierLoc, 551 SourceLocation ColonColonLoc) { 552 Representation = NestedNameSpecifier::Create(Context, Representation, 553 Identifier); 554 555 // Push source-location info into the buffer. 556 SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 557 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 558} 559 560void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 561 NamespaceDecl *Namespace, 562 SourceLocation NamespaceLoc, 563 SourceLocation ColonColonLoc) { 564 Representation = NestedNameSpecifier::Create(Context, Representation, 565 Namespace); 566 567 // Push source-location info into the buffer. 568 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 569 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 570} 571 572void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 573 NamespaceAliasDecl *Alias, 574 SourceLocation AliasLoc, 575 SourceLocation ColonColonLoc) { 576 Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 577 578 // Push source-location info into the buffer. 579 SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 580 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 581} 582 583void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 584 SourceLocation ColonColonLoc) { 585 assert(!Representation && "Already have a nested-name-specifier!?"); 586 Representation = NestedNameSpecifier::GlobalSpecifier(Context); 587 588 // Push source-location info into the buffer. 589 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 590} 591 592void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, 593 CXXRecordDecl *RD, 594 SourceLocation SuperLoc, 595 SourceLocation ColonColonLoc) { 596 Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); 597 598 // Push source-location info into the buffer. 599 SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); 600 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 601} 602 603void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 604 NestedNameSpecifier *Qualifier, 605 SourceRange R) { 606 Representation = Qualifier; 607 608 // Construct bogus (but well-formed) source information for the 609 // nested-name-specifier. 610 BufferSize = 0; 611 SmallVector<NestedNameSpecifier *, 4> Stack; 612 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 613 Stack.push_back(NNS); 614 while (!Stack.empty()) { 615 NestedNameSpecifier *NNS = Stack.pop_back_val(); 616 switch (NNS->getKind()) { 617 case NestedNameSpecifier::Identifier: 618 case NestedNameSpecifier::Namespace: 619 case NestedNameSpecifier::NamespaceAlias: 620 SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 621 break; 622 623 case NestedNameSpecifier::TypeSpec: 624 case NestedNameSpecifier::TypeSpecWithTemplate: { 625 TypeSourceInfo *TSInfo 626 = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 627 R.getBegin()); 628 SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 629 BufferCapacity); 630 break; 631 } 632 633 case NestedNameSpecifier::Global: 634 case NestedNameSpecifier::Super: 635 break; 636 } 637 638 // Save the location of the '::'. 639 SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 640 Buffer, BufferSize, BufferCapacity); 641 } 642} 643 644void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 645 if (BufferCapacity) 646 free(Buffer); 647 648 if (!Other) { 649 Representation = nullptr; 650 BufferSize = 0; 651 return; 652 } 653 654 // Rather than copying the data (which is wasteful), "adopt" the 655 // pointer (which points into the ASTContext) but set the capacity to zero to 656 // indicate that we don't own it. 657 Representation = Other.getNestedNameSpecifier(); 658 Buffer = static_cast<char *>(Other.getOpaqueData()); 659 BufferSize = Other.getDataLength(); 660 BufferCapacity = 0; 661} 662 663NestedNameSpecifierLoc 664NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 665 if (!Representation) 666 return NestedNameSpecifierLoc(); 667 668 // If we adopted our data pointer from elsewhere in the AST context, there's 669 // no need to copy the memory. 670 if (BufferCapacity == 0) 671 return NestedNameSpecifierLoc(Representation, Buffer); 672 673 // FIXME: After copying the source-location information, should we free 674 // our (temporary) buffer and adopt the ASTContext-allocated memory? 675 // Doing so would optimize repeated calls to getWithLocInContext(). 676 void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); 677 memcpy(Mem, Buffer, BufferSize); 678 return NestedNameSpecifierLoc(Representation, Mem); 679} 680