1 //===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the NestedNameSpecifier class, which represents
10 // a C++ nested-name-specifier.
12 //===----------------------------------------------------------------------===//
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"
38 using namespace clang
;
41 NestedNameSpecifier::FindOrInsert(const ASTContext
&Context
,
42 const NestedNameSpecifier
&Mockup
) {
43 llvm::FoldingSetNodeID ID
;
46 void *InsertPos
= nullptr;
47 NestedNameSpecifier
*NNS
48 = Context
.NestedNameSpecifiers
.FindNodeOrInsertPos(ID
, InsertPos
);
51 new (Context
, alignof(NestedNameSpecifier
)) NestedNameSpecifier(Mockup
);
52 Context
.NestedNameSpecifiers
.InsertNode(NNS
, InsertPos
);
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");
64 NestedNameSpecifier Mockup
;
65 Mockup
.Prefix
.setPointer(Prefix
);
66 Mockup
.Prefix
.setInt(StoredIdentifier
);
67 Mockup
.Specifier
= II
;
68 return FindOrInsert(Context
, Mockup
);
72 NestedNameSpecifier::Create(const ASTContext
&Context
,
73 NestedNameSpecifier
*Prefix
,
74 const NamespaceDecl
*NS
) {
75 assert(NS
&& "Namespace cannot be NULL");
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
);
88 NestedNameSpecifier::Create(const ASTContext
&Context
,
89 NestedNameSpecifier
*Prefix
,
90 NamespaceAliasDecl
*Alias
) {
91 assert(Alias
&& "Namespace alias cannot be NULL");
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
);
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
);
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
);
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
;
133 NestedNameSpecifier
*
134 NestedNameSpecifier::SuperSpecifier(const ASTContext
&Context
,
136 NestedNameSpecifier Mockup
;
137 Mockup
.Prefix
.setPointer(nullptr);
138 Mockup
.Prefix
.setInt(StoredDecl
);
139 Mockup
.Specifier
= RD
;
140 return FindOrInsert(Context
, Mockup
);
143 NestedNameSpecifier::SpecifierKind
NestedNameSpecifier::getKind() const {
147 switch (Prefix
.getInt()) {
148 case StoredIdentifier
:
152 NamedDecl
*ND
= static_cast<NamedDecl
*>(Specifier
);
153 if (isa
<CXXRecordDecl
>(ND
))
155 return isa
<NamespaceDecl
>(ND
) ? Namespace
: NamespaceAlias
;
161 case StoredTypeSpecWithTemplate
:
162 return TypeSpecWithTemplate
;
165 llvm_unreachable("Invalid NNS Kind!");
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
));
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
));
184 /// Retrieve the record declaration stored in this nested name specifier.
185 CXXRecordDecl
*NestedNameSpecifier::getAsRecordDecl() const {
186 switch (Prefix
.getInt()) {
187 case StoredIdentifier
:
191 return dyn_cast
<CXXRecordDecl
>(static_cast<NamedDecl
*>(Specifier
));
194 case StoredTypeSpecWithTemplate
:
195 return getAsType()->getAsCXXRecordDecl();
198 llvm_unreachable("Invalid NNS Kind!");
201 NestedNameSpecifierDependence
NestedNameSpecifier::getDependence() const {
204 // Identifier specifiers always represent dependent types
205 auto F
= NestedNameSpecifierDependence::Dependent
|
206 NestedNameSpecifierDependence::Instantiation
;
207 // Prefix can contain unexpanded template parameters.
209 return F
| getPrefix()->getDependence();
216 return NestedNameSpecifierDependence::None
;
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
;
228 case TypeSpecWithTemplate
:
229 return toNestedNameSpecifierDependendence(getAsType()->getDependence());
231 llvm_unreachable("Invalid NNS Kind!");
234 bool NestedNameSpecifier::isDependent() const {
235 return getDependence() & NestedNameSpecifierDependence::Dependent
;
238 bool NestedNameSpecifier::isInstantiationDependent() const {
239 return getDependence() & NestedNameSpecifierDependence::Instantiation
;
242 bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
243 return getDependence() & NestedNameSpecifierDependence::UnexpandedPack
;
246 bool NestedNameSpecifier::containsErrors() const {
247 return getDependence() & NestedNameSpecifierDependence::Error
;
250 /// Print this nested name specifier to the given output
252 void NestedNameSpecifier::print(raw_ostream
&OS
, const PrintingPolicy
&Policy
,
253 bool ResolveTemplateArguments
) const {
255 getPrefix()->print(OS
, Policy
);
259 OS
<< getAsIdentifier()->getName();
263 if (getAsNamespace()->isAnonymousNamespace())
266 OS
<< getAsNamespace()->getName();
270 OS
<< getAsNamespaceAlias()->getName();
280 case TypeSpecWithTemplate
:
282 // Fall through to print the type.
287 dyn_cast_or_null
<ClassTemplateSpecializationDecl
>(getAsRecordDecl());
288 if (ResolveTemplateArguments
&& Record
) {
289 // Print the type trait with resolved template parameters.
290 Record
->printName(OS
, Policy
);
291 printTemplateArgumentList(
292 OS
, Record
->getTemplateArgs().asArray(), Policy
,
293 Record
->getSpecializedTemplate()->getTemplateParameters());
296 const Type
*T
= getAsType();
298 PrintingPolicy
InnerPolicy(Policy
);
299 InnerPolicy
.SuppressScope
= true;
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
);
317 // Print the template argument list.
318 printTemplateArgumentList(OS
, SpecType
->template_arguments(),
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(),
329 // Print the type normally
330 QualType(T
, 0).print(OS
, InnerPolicy
);
339 LLVM_DUMP_METHOD
void NestedNameSpecifier::dump(const LangOptions
&LO
) const {
340 dump(llvm::errs(), LO
);
343 LLVM_DUMP_METHOD
void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
345 LLVM_DUMP_METHOD
void NestedNameSpecifier::dump(llvm::raw_ostream
&OS
) const {
350 LLVM_DUMP_METHOD
void NestedNameSpecifier::dump(llvm::raw_ostream
&OS
,
351 const LangOptions
&LO
) const {
352 print(OS
, PrintingPolicy(LO
));
356 NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier
*Qualifier
) {
357 assert(Qualifier
&& "Expected a non-NULL qualifier");
359 // Location of the trailing '::'.
360 unsigned Length
= sizeof(SourceLocation::UIntTy
);
362 switch (Qualifier
->getKind()) {
363 case NestedNameSpecifier::Global
:
364 // Nothing more to add.
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
);
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 *);
387 NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier
*Qualifier
) {
389 for (; Qualifier
; Qualifier
= Qualifier
->getPrefix())
390 Length
+= getLocalDataLength(Qualifier
);
394 /// Load a (possibly unaligned) source location from a given address
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
);
402 /// Load a (possibly unaligned) pointer from a given address and
404 static void *LoadPointer(void *Data
, unsigned Offset
) {
406 memcpy(&Result
, static_cast<char *>(Data
) + Offset
, sizeof(void*));
410 SourceRange
NestedNameSpecifierLoc::getSourceRange() const {
412 return SourceRange();
414 NestedNameSpecifierLoc First
= *this;
415 while (NestedNameSpecifierLoc Prefix
= First
.getPrefix())
418 return SourceRange(First
.getLocalSourceRange().getBegin(),
419 getLocalSourceRange().getEnd());
422 SourceRange
NestedNameSpecifierLoc::getLocalSourceRange() const {
424 return SourceRange();
426 unsigned Offset
= getDataLength(Qualifier
->getPrefix());
427 switch (Qualifier
->getKind()) {
428 case NestedNameSpecifier::Global
:
429 return LoadSourceLocation(Data
, Offset
);
431 case NestedNameSpecifier::Identifier
:
432 case NestedNameSpecifier::Namespace
:
433 case NestedNameSpecifier::NamespaceAlias
:
434 case NestedNameSpecifier::Super
:
436 LoadSourceLocation(Data
, Offset
),
437 LoadSourceLocation(Data
, Offset
+ sizeof(SourceLocation::UIntTy
)));
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*)));
450 llvm_unreachable("Invalid NNS Kind!");
453 TypeLoc
NestedNameSpecifierLoc::getTypeLoc() const {
454 if (Qualifier
->getKind() != NestedNameSpecifier::TypeSpec
&&
455 Qualifier
->getKind() != NestedNameSpecifier::TypeSpecWithTemplate
)
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
);
464 static void Append(char *Start
, char *End
, char *&Buffer
, unsigned &BufferSize
,
465 unsigned &BufferCapacity
) {
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
));
477 memcpy(NewBuffer
, Buffer
, BufferSize
);
480 Buffer
= static_cast<char *>(llvm::safe_realloc(Buffer
, NewCapacity
));
482 BufferCapacity
= NewCapacity
;
484 assert(Buffer
&& Start
&& End
&& End
> Start
&& "Illegal memory buffer copy");
485 memcpy(Buffer
+ BufferSize
, Start
, End
- Start
);
486 BufferSize
+= End
- Start
;
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
,
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
);
506 NestedNameSpecifierLocBuilder::
507 NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder
&Other
)
508 : Representation(Other
.Representation
) {
512 if (Other
.BufferCapacity
== 0) {
513 // Shallow copy is okay.
514 Buffer
= Other
.Buffer
;
515 BufferSize
= Other
.BufferSize
;
520 Append(Other
.Buffer
, Other
.Buffer
+ Other
.BufferSize
, Buffer
, BufferSize
,
524 NestedNameSpecifierLocBuilder
&
525 NestedNameSpecifierLocBuilder::
526 operator=(const NestedNameSpecifierLocBuilder
&Other
) {
527 Representation
= Other
.Representation
;
529 if (Buffer
&& Other
.Buffer
&& BufferCapacity
>= Other
.BufferSize
) {
530 // Re-use our storage.
531 BufferSize
= Other
.BufferSize
;
532 memcpy(Buffer
, Other
.Buffer
, BufferSize
);
536 // Free our storage, if we have any.
537 if (BufferCapacity
) {
549 if (Other
.BufferCapacity
== 0) {
550 // Shallow copy is okay.
551 Buffer
= Other
.Buffer
;
552 BufferSize
= Other
.BufferSize
;
558 Append(Other
.Buffer
, Other
.Buffer
+ Other
.BufferSize
, Buffer
, BufferSize
,
563 void NestedNameSpecifierLocBuilder::Extend(ASTContext
&Context
,
564 SourceLocation TemplateKWLoc
,
566 SourceLocation ColonColonLoc
) {
567 Representation
= NestedNameSpecifier::Create(Context
, Representation
,
568 TemplateKWLoc
.isValid(),
571 // Push source-location info into the buffer.
572 SavePointer(TL
.getOpaqueData(), Buffer
, BufferSize
, BufferCapacity
);
573 SaveSourceLocation(ColonColonLoc
, Buffer
, BufferSize
, BufferCapacity
);
576 void NestedNameSpecifierLocBuilder::Extend(ASTContext
&Context
,
577 IdentifierInfo
*Identifier
,
578 SourceLocation IdentifierLoc
,
579 SourceLocation ColonColonLoc
) {
580 Representation
= NestedNameSpecifier::Create(Context
, Representation
,
583 // Push source-location info into the buffer.
584 SaveSourceLocation(IdentifierLoc
, Buffer
, BufferSize
, BufferCapacity
);
585 SaveSourceLocation(ColonColonLoc
, Buffer
, BufferSize
, BufferCapacity
);
588 void NestedNameSpecifierLocBuilder::Extend(ASTContext
&Context
,
589 NamespaceDecl
*Namespace
,
590 SourceLocation NamespaceLoc
,
591 SourceLocation ColonColonLoc
) {
592 Representation
= NestedNameSpecifier::Create(Context
, Representation
,
595 // Push source-location info into the buffer.
596 SaveSourceLocation(NamespaceLoc
, Buffer
, BufferSize
, BufferCapacity
);
597 SaveSourceLocation(ColonColonLoc
, Buffer
, BufferSize
, BufferCapacity
);
600 void NestedNameSpecifierLocBuilder::Extend(ASTContext
&Context
,
601 NamespaceAliasDecl
*Alias
,
602 SourceLocation AliasLoc
,
603 SourceLocation ColonColonLoc
) {
604 Representation
= NestedNameSpecifier::Create(Context
, Representation
, Alias
);
606 // Push source-location info into the buffer.
607 SaveSourceLocation(AliasLoc
, Buffer
, BufferSize
, BufferCapacity
);
608 SaveSourceLocation(ColonColonLoc
, Buffer
, BufferSize
, BufferCapacity
);
611 void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext
&Context
,
612 SourceLocation ColonColonLoc
) {
613 assert(!Representation
&& "Already have a nested-name-specifier!?");
614 Representation
= NestedNameSpecifier::GlobalSpecifier(Context
);
616 // Push source-location info into the buffer.
617 SaveSourceLocation(ColonColonLoc
, Buffer
, BufferSize
, BufferCapacity
);
620 void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext
&Context
,
622 SourceLocation SuperLoc
,
623 SourceLocation ColonColonLoc
) {
624 Representation
= NestedNameSpecifier::SuperSpecifier(Context
, RD
);
626 // Push source-location info into the buffer.
627 SaveSourceLocation(SuperLoc
, Buffer
, BufferSize
, BufferCapacity
);
628 SaveSourceLocation(ColonColonLoc
, Buffer
, BufferSize
, BufferCapacity
);
631 void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext
&Context
,
632 NestedNameSpecifier
*Qualifier
,
634 Representation
= Qualifier
;
636 // Construct bogus (but well-formed) source information for the
637 // nested-name-specifier.
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
);
651 case NestedNameSpecifier::TypeSpec
:
652 case NestedNameSpecifier::TypeSpecWithTemplate
: {
653 TypeSourceInfo
*TSInfo
654 = Context
.getTrivialTypeSourceInfo(QualType(NNS
->getAsType(), 0),
656 SavePointer(TSInfo
->getTypeLoc().getOpaqueData(), Buffer
, BufferSize
,
661 case NestedNameSpecifier::Global
:
662 case NestedNameSpecifier::Super
:
666 // Save the location of the '::'.
667 SaveSourceLocation(Stack
.empty()? R
.getEnd() : R
.getBegin(),
668 Buffer
, BufferSize
, BufferCapacity
);
672 void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other
) {
677 Representation
= nullptr;
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();
691 NestedNameSpecifierLoc
692 NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext
&Context
) const {
694 return NestedNameSpecifierLoc();
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
);
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
);