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