1461a67faSDimitry Andric //===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
2ec2b103cSEd Schouten //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ec2b103cSEd Schouten //
7ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
8ec2b103cSEd Schouten //
9ec2b103cSEd Schouten // This file defines the NestedNameSpecifier class, which represents
10ec2b103cSEd Schouten // a C++ nested-name-specifier.
11ec2b103cSEd Schouten //
12ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
13461a67faSDimitry Andric
14ec2b103cSEd Schouten #include "clang/AST/NestedNameSpecifier.h"
15ec2b103cSEd Schouten #include "clang/AST/ASTContext.h"
16ec2b103cSEd Schouten #include "clang/AST/Decl.h"
17c3b054d2SDimitry Andric #include "clang/AST/DeclCXX.h"
18676fbe81SDimitry Andric #include "clang/AST/DeclTemplate.h"
19cfca06d7SDimitry Andric #include "clang/AST/DependenceFlags.h"
20ec2b103cSEd Schouten #include "clang/AST/PrettyPrinter.h"
21461a67faSDimitry Andric #include "clang/AST/TemplateName.h"
22ec2b103cSEd Schouten #include "clang/AST/Type.h"
23c3b054d2SDimitry Andric #include "clang/AST/TypeLoc.h"
24461a67faSDimitry Andric #include "clang/Basic/LLVM.h"
25461a67faSDimitry Andric #include "clang/Basic/LangOptions.h"
26461a67faSDimitry Andric #include "clang/Basic/SourceLocation.h"
27461a67faSDimitry Andric #include "llvm/ADT/FoldingSet.h"
28461a67faSDimitry Andric #include "llvm/ADT/SmallVector.h"
29461a67faSDimitry Andric #include "llvm/Support/Casting.h"
30461a67faSDimitry Andric #include "llvm/Support/Compiler.h"
31461a67faSDimitry Andric #include "llvm/Support/ErrorHandling.h"
32ec2b103cSEd Schouten #include "llvm/Support/raw_ostream.h"
33461a67faSDimitry Andric #include <algorithm>
34ec2b103cSEd Schouten #include <cassert>
35461a67faSDimitry Andric #include <cstdlib>
36461a67faSDimitry Andric #include <cstring>
37ec2b103cSEd Schouten
38ec2b103cSEd Schouten using namespace clang;
39ec2b103cSEd Schouten
40ec2b103cSEd Schouten NestedNameSpecifier *
FindOrInsert(const ASTContext & Context,const NestedNameSpecifier & Mockup)41bca07a45SDimitry Andric NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
42ec2b103cSEd Schouten const NestedNameSpecifier &Mockup) {
43ec2b103cSEd Schouten llvm::FoldingSetNodeID ID;
44ec2b103cSEd Schouten Mockup.Profile(ID);
45ec2b103cSEd Schouten
469f4dbff6SDimitry Andric void *InsertPos = nullptr;
47ec2b103cSEd Schouten NestedNameSpecifier *NNS
48ec2b103cSEd Schouten = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
49ec2b103cSEd Schouten if (!NNS) {
50bab175ecSDimitry Andric NNS =
51bab175ecSDimitry Andric new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
52ec2b103cSEd Schouten Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
53ec2b103cSEd Schouten }
54ec2b103cSEd Schouten
55ec2b103cSEd Schouten return NNS;
56ec2b103cSEd Schouten }
57ec2b103cSEd Schouten
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,const IdentifierInfo * II)58ac9a064cSDimitry Andric NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
59ac9a064cSDimitry Andric NestedNameSpecifier *Prefix,
60ac9a064cSDimitry Andric const IdentifierInfo *II) {
61ec2b103cSEd Schouten assert(II && "Identifier cannot be NULL");
624c8b2481SRoman Divacky assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
63ec2b103cSEd Schouten
64ec2b103cSEd Schouten NestedNameSpecifier Mockup;
65ec2b103cSEd Schouten Mockup.Prefix.setPointer(Prefix);
66c3b054d2SDimitry Andric Mockup.Prefix.setInt(StoredIdentifier);
67ac9a064cSDimitry Andric Mockup.Specifier = const_cast<IdentifierInfo *>(II);
68ec2b103cSEd Schouten return FindOrInsert(Context, Mockup);
69ec2b103cSEd Schouten }
70ec2b103cSEd Schouten
71ec2b103cSEd Schouten NestedNameSpecifier *
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,const NamespaceDecl * NS)72bca07a45SDimitry Andric NestedNameSpecifier::Create(const ASTContext &Context,
73809500fcSDimitry Andric NestedNameSpecifier *Prefix,
74809500fcSDimitry Andric const NamespaceDecl *NS) {
75ec2b103cSEd Schouten assert(NS && "Namespace cannot be NULL");
76ec2b103cSEd Schouten assert((!Prefix ||
779f4dbff6SDimitry Andric (Prefix->getAsType() == nullptr &&
789f4dbff6SDimitry Andric Prefix->getAsIdentifier() == nullptr)) &&
79ec2b103cSEd Schouten "Broken nested name specifier");
80ec2b103cSEd Schouten NestedNameSpecifier Mockup;
81ec2b103cSEd Schouten Mockup.Prefix.setPointer(Prefix);
8206d4ba38SDimitry Andric Mockup.Prefix.setInt(StoredDecl);
83809500fcSDimitry Andric Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
84ec2b103cSEd Schouten return FindOrInsert(Context, Mockup);
85ec2b103cSEd Schouten }
86ec2b103cSEd Schouten
87ec2b103cSEd Schouten NestedNameSpecifier *
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,const NamespaceAliasDecl * Alias)88bca07a45SDimitry Andric NestedNameSpecifier::Create(const ASTContext &Context,
89bca07a45SDimitry Andric NestedNameSpecifier *Prefix,
90ac9a064cSDimitry Andric const NamespaceAliasDecl *Alias) {
91c3b054d2SDimitry Andric assert(Alias && "Namespace alias cannot be NULL");
92c3b054d2SDimitry Andric assert((!Prefix ||
939f4dbff6SDimitry Andric (Prefix->getAsType() == nullptr &&
949f4dbff6SDimitry Andric Prefix->getAsIdentifier() == nullptr)) &&
95c3b054d2SDimitry Andric "Broken nested name specifier");
96c3b054d2SDimitry Andric NestedNameSpecifier Mockup;
97c3b054d2SDimitry Andric Mockup.Prefix.setPointer(Prefix);
9806d4ba38SDimitry Andric Mockup.Prefix.setInt(StoredDecl);
99ac9a064cSDimitry Andric Mockup.Specifier = const_cast<NamespaceAliasDecl *>(Alias);
100c3b054d2SDimitry Andric return FindOrInsert(Context, Mockup);
101c3b054d2SDimitry Andric }
102c3b054d2SDimitry Andric
103c3b054d2SDimitry Andric NestedNameSpecifier *
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,bool Template,const Type * T)104c3b054d2SDimitry Andric NestedNameSpecifier::Create(const ASTContext &Context,
105c3b054d2SDimitry Andric NestedNameSpecifier *Prefix,
106bca07a45SDimitry Andric bool Template, const Type *T) {
107ec2b103cSEd Schouten assert(T && "Type cannot be NULL");
108ec2b103cSEd Schouten NestedNameSpecifier Mockup;
109ec2b103cSEd Schouten Mockup.Prefix.setPointer(Prefix);
110c3b054d2SDimitry Andric Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
111bca07a45SDimitry Andric Mockup.Specifier = const_cast<Type*>(T);
112ec2b103cSEd Schouten return FindOrInsert(Context, Mockup);
113ec2b103cSEd Schouten }
114ec2b103cSEd Schouten
Create(const ASTContext & Context,const IdentifierInfo * II)115ac9a064cSDimitry Andric NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
116ac9a064cSDimitry Andric const IdentifierInfo *II) {
1174c8b2481SRoman Divacky assert(II && "Identifier cannot be NULL");
1184c8b2481SRoman Divacky NestedNameSpecifier Mockup;
1199f4dbff6SDimitry Andric Mockup.Prefix.setPointer(nullptr);
120c3b054d2SDimitry Andric Mockup.Prefix.setInt(StoredIdentifier);
121ac9a064cSDimitry Andric Mockup.Specifier = const_cast<IdentifierInfo *>(II);
1224c8b2481SRoman Divacky return FindOrInsert(Context, Mockup);
1234c8b2481SRoman Divacky }
1244c8b2481SRoman Divacky
125bca07a45SDimitry Andric NestedNameSpecifier *
GlobalSpecifier(const ASTContext & Context)126bca07a45SDimitry Andric NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
127ec2b103cSEd Schouten if (!Context.GlobalNestedNameSpecifier)
128657bc3d9SDimitry Andric Context.GlobalNestedNameSpecifier =
129bab175ecSDimitry Andric new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
130ec2b103cSEd Schouten return Context.GlobalNestedNameSpecifier;
131ec2b103cSEd Schouten }
132ec2b103cSEd Schouten
13306d4ba38SDimitry Andric NestedNameSpecifier *
SuperSpecifier(const ASTContext & Context,CXXRecordDecl * RD)13406d4ba38SDimitry Andric NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
13506d4ba38SDimitry Andric CXXRecordDecl *RD) {
13606d4ba38SDimitry Andric NestedNameSpecifier Mockup;
13706d4ba38SDimitry Andric Mockup.Prefix.setPointer(nullptr);
13806d4ba38SDimitry Andric Mockup.Prefix.setInt(StoredDecl);
13906d4ba38SDimitry Andric Mockup.Specifier = RD;
14006d4ba38SDimitry Andric return FindOrInsert(Context, Mockup);
14106d4ba38SDimitry Andric }
14206d4ba38SDimitry Andric
getKind() const143c3b054d2SDimitry Andric NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
1449f4dbff6SDimitry Andric if (!Specifier)
145c3b054d2SDimitry Andric return Global;
146c3b054d2SDimitry Andric
147c3b054d2SDimitry Andric switch (Prefix.getInt()) {
148c3b054d2SDimitry Andric case StoredIdentifier:
149c3b054d2SDimitry Andric return Identifier;
150c3b054d2SDimitry Andric
15106d4ba38SDimitry Andric case StoredDecl: {
15206d4ba38SDimitry Andric NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
15306d4ba38SDimitry Andric if (isa<CXXRecordDecl>(ND))
15406d4ba38SDimitry Andric return Super;
15506d4ba38SDimitry Andric return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
15606d4ba38SDimitry Andric }
157c3b054d2SDimitry Andric
158c3b054d2SDimitry Andric case StoredTypeSpec:
159c3b054d2SDimitry Andric return TypeSpec;
160c3b054d2SDimitry Andric
161c3b054d2SDimitry Andric case StoredTypeSpecWithTemplate:
162c3b054d2SDimitry Andric return TypeSpecWithTemplate;
163c3b054d2SDimitry Andric }
164c3b054d2SDimitry Andric
165dbe13110SDimitry Andric llvm_unreachable("Invalid NNS Kind!");
166c3b054d2SDimitry Andric }
167c3b054d2SDimitry Andric
16848675466SDimitry Andric /// Retrieve the namespace stored in this nested name specifier.
getAsNamespace() const169c3b054d2SDimitry Andric NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
17006d4ba38SDimitry Andric if (Prefix.getInt() == StoredDecl)
171c3b054d2SDimitry Andric return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
172c3b054d2SDimitry Andric
1739f4dbff6SDimitry Andric return nullptr;
174c3b054d2SDimitry Andric }
175c3b054d2SDimitry Andric
17648675466SDimitry Andric /// Retrieve the namespace alias stored in this nested name specifier.
getAsNamespaceAlias() const177c3b054d2SDimitry Andric NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
17806d4ba38SDimitry Andric if (Prefix.getInt() == StoredDecl)
179c3b054d2SDimitry Andric return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
180c3b054d2SDimitry Andric
1819f4dbff6SDimitry Andric return nullptr;
182c3b054d2SDimitry Andric }
183c3b054d2SDimitry Andric
18448675466SDimitry Andric /// Retrieve the record declaration stored in this nested name specifier.
getAsRecordDecl() const18506d4ba38SDimitry Andric CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
1862b6b257fSDimitry Andric switch (Prefix.getInt()) {
1872b6b257fSDimitry Andric case StoredIdentifier:
1882b6b257fSDimitry Andric return nullptr;
1892b6b257fSDimitry Andric
1902b6b257fSDimitry Andric case StoredDecl:
19106d4ba38SDimitry Andric return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
19206d4ba38SDimitry Andric
1932b6b257fSDimitry Andric case StoredTypeSpec:
1942b6b257fSDimitry Andric case StoredTypeSpecWithTemplate:
1952b6b257fSDimitry Andric return getAsType()->getAsCXXRecordDecl();
1962b6b257fSDimitry Andric }
1972b6b257fSDimitry Andric
1982b6b257fSDimitry Andric llvm_unreachable("Invalid NNS Kind!");
19906d4ba38SDimitry Andric }
200c3b054d2SDimitry Andric
getDependence() const201cfca06d7SDimitry Andric NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
202ec2b103cSEd Schouten switch (getKind()) {
203cfca06d7SDimitry Andric case Identifier: {
204ec2b103cSEd Schouten // Identifier specifiers always represent dependent types
205cfca06d7SDimitry Andric auto F = NestedNameSpecifierDependence::Dependent |
206cfca06d7SDimitry Andric NestedNameSpecifierDependence::Instantiation;
207cfca06d7SDimitry Andric // Prefix can contain unexpanded template parameters.
208cfca06d7SDimitry Andric if (getPrefix())
209cfca06d7SDimitry Andric return F | getPrefix()->getDependence();
210cfca06d7SDimitry Andric return F;
211cfca06d7SDimitry Andric }
212ec2b103cSEd Schouten
213ec2b103cSEd Schouten case Namespace:
214c3b054d2SDimitry Andric case NamespaceAlias:
215ec2b103cSEd Schouten case Global:
216cfca06d7SDimitry Andric return NestedNameSpecifierDependence::None;
217ec2b103cSEd Schouten
21806d4ba38SDimitry Andric case Super: {
21906d4ba38SDimitry Andric CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
22006d4ba38SDimitry Andric for (const auto &Base : RD->bases())
22106d4ba38SDimitry Andric if (Base.getType()->isDependentType())
222cfca06d7SDimitry Andric // FIXME: must also be instantiation-dependent.
223cfca06d7SDimitry Andric return NestedNameSpecifierDependence::Dependent;
224cfca06d7SDimitry Andric return NestedNameSpecifierDependence::None;
22506d4ba38SDimitry Andric }
22606d4ba38SDimitry Andric
227ec2b103cSEd Schouten case TypeSpec:
228ec2b103cSEd Schouten case TypeSpecWithTemplate:
229cfca06d7SDimitry Andric return toNestedNameSpecifierDependendence(getAsType()->getDependence());
230ec2b103cSEd Schouten }
231dbe13110SDimitry Andric llvm_unreachable("Invalid NNS Kind!");
232ec2b103cSEd Schouten }
233ec2b103cSEd Schouten
isDependent() const234cfca06d7SDimitry Andric bool NestedNameSpecifier::isDependent() const {
235cfca06d7SDimitry Andric return getDependence() & NestedNameSpecifierDependence::Dependent;
236cfca06d7SDimitry Andric }
237cfca06d7SDimitry Andric
isInstantiationDependent() const238180abc3dSDimitry Andric bool NestedNameSpecifier::isInstantiationDependent() const {
239cfca06d7SDimitry Andric return getDependence() & NestedNameSpecifierDependence::Instantiation;
240180abc3dSDimitry Andric }
241180abc3dSDimitry Andric
containsUnexpandedParameterPack() const242bca07a45SDimitry Andric bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
243cfca06d7SDimitry Andric return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
244bca07a45SDimitry Andric }
245bca07a45SDimitry Andric
containsErrors() const246cfca06d7SDimitry Andric bool NestedNameSpecifier::containsErrors() const {
247cfca06d7SDimitry Andric return getDependence() & NestedNameSpecifierDependence::Error;
248bca07a45SDimitry Andric }
249bca07a45SDimitry Andric
25048675466SDimitry Andric /// Print this nested name specifier to the given output
251ec2b103cSEd Schouten /// stream.
print(raw_ostream & OS,const PrintingPolicy & Policy,bool ResolveTemplateArguments) const252676fbe81SDimitry Andric void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
253676fbe81SDimitry Andric bool ResolveTemplateArguments) const {
254ec2b103cSEd Schouten if (getPrefix())
255ec2b103cSEd Schouten getPrefix()->print(OS, Policy);
256ec2b103cSEd Schouten
257ec2b103cSEd Schouten switch (getKind()) {
258ec2b103cSEd Schouten case Identifier:
259ec2b103cSEd Schouten OS << getAsIdentifier()->getName();
260ec2b103cSEd Schouten break;
261ec2b103cSEd Schouten
262ec2b103cSEd Schouten case Namespace:
263dbe13110SDimitry Andric if (getAsNamespace()->isAnonymousNamespace())
264dbe13110SDimitry Andric return;
265dbe13110SDimitry Andric
266c3b054d2SDimitry Andric OS << getAsNamespace()->getName();
267c3b054d2SDimitry Andric break;
268c3b054d2SDimitry Andric
269c3b054d2SDimitry Andric case NamespaceAlias:
270c3b054d2SDimitry Andric OS << getAsNamespaceAlias()->getName();
271ec2b103cSEd Schouten break;
272ec2b103cSEd Schouten
273ec2b103cSEd Schouten case Global:
274ec2b103cSEd Schouten break;
275ec2b103cSEd Schouten
27606d4ba38SDimitry Andric case Super:
27706d4ba38SDimitry Andric OS << "__super";
27806d4ba38SDimitry Andric break;
27906d4ba38SDimitry Andric
280ec2b103cSEd Schouten case TypeSpecWithTemplate:
281ec2b103cSEd Schouten OS << "template ";
282ec2b103cSEd Schouten // Fall through to print the type.
283e3b55780SDimitry Andric [[fallthrough]];
284ec2b103cSEd Schouten
285ec2b103cSEd Schouten case TypeSpec: {
286676fbe81SDimitry Andric const auto *Record =
287676fbe81SDimitry Andric dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
288676fbe81SDimitry Andric if (ResolveTemplateArguments && Record) {
289676fbe81SDimitry Andric // Print the type trait with resolved template parameters.
290e3b55780SDimitry Andric Record->printName(OS, Policy);
291344a3780SDimitry Andric printTemplateArgumentList(
292344a3780SDimitry Andric OS, Record->getTemplateArgs().asArray(), Policy,
293344a3780SDimitry Andric Record->getSpecializedTemplate()->getTemplateParameters());
294676fbe81SDimitry Andric break;
295676fbe81SDimitry Andric }
296bca07a45SDimitry Andric const Type *T = getAsType();
297ec2b103cSEd Schouten
298ec2b103cSEd Schouten PrintingPolicy InnerPolicy(Policy);
2994c8b2481SRoman Divacky InnerPolicy.SuppressScope = true;
3004c8b2481SRoman Divacky
3014c8b2481SRoman Divacky // Nested-name-specifiers are intended to contain minimally-qualified
302d7279c4cSRoman Divacky // types. An actual ElaboratedType will not occur, since we'll store
3034c8b2481SRoman Divacky // just the type that is referred to in the nested-name-specifier (e.g.,
3044c8b2481SRoman Divacky // a TypedefType, TagType, etc.). However, when we are dealing with
3054c8b2481SRoman Divacky // dependent template-id types (e.g., Outer<T>::template Inner<U>),
3064c8b2481SRoman Divacky // the type requires its own nested-name-specifier for uniqueness, so we
3074c8b2481SRoman Divacky // suppress that nested-name-specifier during printing.
308d7279c4cSRoman Divacky assert(!isa<ElaboratedType>(T) &&
309d7279c4cSRoman Divacky "Elaborated type in nested-name-specifier");
3104c8b2481SRoman Divacky if (const TemplateSpecializationType *SpecType
3114c8b2481SRoman Divacky = dyn_cast<TemplateSpecializationType>(T)) {
3124c8b2481SRoman Divacky // Print the template name without its corresponding
3134c8b2481SRoman Divacky // nested-name-specifier.
314c0981da4SDimitry Andric SpecType->getTemplateName().print(OS, InnerPolicy,
315c0981da4SDimitry Andric TemplateName::Qualified::None);
3164c8b2481SRoman Divacky
3174c8b2481SRoman Divacky // Print the template argument list.
318461a67faSDimitry Andric printTemplateArgumentList(OS, SpecType->template_arguments(),
319461a67faSDimitry Andric InnerPolicy);
320cfca06d7SDimitry Andric } else if (const auto *DepSpecType =
321cfca06d7SDimitry Andric dyn_cast<DependentTemplateSpecializationType>(T)) {
322cfca06d7SDimitry Andric // Print the template name without its corresponding
323cfca06d7SDimitry Andric // nested-name-specifier.
324cfca06d7SDimitry Andric OS << DepSpecType->getIdentifier()->getName();
325cfca06d7SDimitry Andric // Print the template argument list.
326cfca06d7SDimitry Andric printTemplateArgumentList(OS, DepSpecType->template_arguments(),
327cfca06d7SDimitry Andric InnerPolicy);
3284c8b2481SRoman Divacky } else {
3294c8b2481SRoman Divacky // Print the type normally
330809500fcSDimitry Andric QualType(T, 0).print(OS, InnerPolicy);
3314c8b2481SRoman Divacky }
332ec2b103cSEd Schouten break;
333ec2b103cSEd Schouten }
334ec2b103cSEd Schouten }
335ec2b103cSEd Schouten
336ec2b103cSEd Schouten OS << "::";
337ec2b103cSEd Schouten }
338ec2b103cSEd Schouten
dump(const LangOptions & LO) const339676fbe81SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
340676fbe81SDimitry Andric dump(llvm::errs(), LO);
34145b53394SDimitry Andric }
34245b53394SDimitry Andric
dump() const343676fbe81SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
344676fbe81SDimitry Andric
dump(llvm::raw_ostream & OS) const345676fbe81SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
34645b53394SDimitry Andric LangOptions LO;
347676fbe81SDimitry Andric dump(OS, LO);
348676fbe81SDimitry Andric }
349676fbe81SDimitry Andric
dump(llvm::raw_ostream & OS,const LangOptions & LO) const350676fbe81SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
351676fbe81SDimitry Andric const LangOptions &LO) const {
352676fbe81SDimitry Andric print(OS, PrintingPolicy(LO));
353ec2b103cSEd Schouten }
354c3b054d2SDimitry Andric
355c3b054d2SDimitry Andric unsigned
getLocalDataLength(NestedNameSpecifier * Qualifier)356c3b054d2SDimitry Andric NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
357c3b054d2SDimitry Andric assert(Qualifier && "Expected a non-NULL qualifier");
358c3b054d2SDimitry Andric
359c3b054d2SDimitry Andric // Location of the trailing '::'.
360344a3780SDimitry Andric unsigned Length = sizeof(SourceLocation::UIntTy);
361c3b054d2SDimitry Andric
362c3b054d2SDimitry Andric switch (Qualifier->getKind()) {
363c3b054d2SDimitry Andric case NestedNameSpecifier::Global:
364c3b054d2SDimitry Andric // Nothing more to add.
365c3b054d2SDimitry Andric break;
366c3b054d2SDimitry Andric
367c3b054d2SDimitry Andric case NestedNameSpecifier::Identifier:
368c3b054d2SDimitry Andric case NestedNameSpecifier::Namespace:
369c3b054d2SDimitry Andric case NestedNameSpecifier::NamespaceAlias:
37006d4ba38SDimitry Andric case NestedNameSpecifier::Super:
371c3b054d2SDimitry Andric // The location of the identifier or namespace name.
372344a3780SDimitry Andric Length += sizeof(SourceLocation::UIntTy);
373c3b054d2SDimitry Andric break;
374c3b054d2SDimitry Andric
375c3b054d2SDimitry Andric case NestedNameSpecifier::TypeSpecWithTemplate:
376c3b054d2SDimitry Andric case NestedNameSpecifier::TypeSpec:
377c3b054d2SDimitry Andric // The "void*" that points at the TypeLoc data.
378c3b054d2SDimitry Andric // Note: the 'template' keyword is part of the TypeLoc.
379c3b054d2SDimitry Andric Length += sizeof(void *);
380c3b054d2SDimitry Andric break;
381c3b054d2SDimitry Andric }
382c3b054d2SDimitry Andric
383c3b054d2SDimitry Andric return Length;
384c3b054d2SDimitry Andric }
385c3b054d2SDimitry Andric
386c3b054d2SDimitry Andric unsigned
getDataLength(NestedNameSpecifier * Qualifier)387c3b054d2SDimitry Andric NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
388c3b054d2SDimitry Andric unsigned Length = 0;
389c3b054d2SDimitry Andric for (; Qualifier; Qualifier = Qualifier->getPrefix())
390c3b054d2SDimitry Andric Length += getLocalDataLength(Qualifier);
391c3b054d2SDimitry Andric return Length;
392c3b054d2SDimitry Andric }
393c3b054d2SDimitry Andric
39448675466SDimitry Andric /// Load a (possibly unaligned) source location from a given address
395c3b054d2SDimitry Andric /// and offset.
LoadSourceLocation(void * Data,unsigned Offset)396461a67faSDimitry Andric static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
397344a3780SDimitry Andric SourceLocation::UIntTy Raw;
398344a3780SDimitry Andric memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));
399c3b054d2SDimitry Andric return SourceLocation::getFromRawEncoding(Raw);
400c3b054d2SDimitry Andric }
401c3b054d2SDimitry Andric
40248675466SDimitry Andric /// Load a (possibly unaligned) pointer from a given address and
403c3b054d2SDimitry Andric /// offset.
LoadPointer(void * Data,unsigned Offset)404461a67faSDimitry Andric static void *LoadPointer(void *Data, unsigned Offset) {
405c3b054d2SDimitry Andric void *Result;
406c3b054d2SDimitry Andric memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
407c3b054d2SDimitry Andric return Result;
408c3b054d2SDimitry Andric }
409c3b054d2SDimitry Andric
getSourceRange() const410c3b054d2SDimitry Andric SourceRange NestedNameSpecifierLoc::getSourceRange() const {
411c3b054d2SDimitry Andric if (!Qualifier)
412c3b054d2SDimitry Andric return SourceRange();
413c3b054d2SDimitry Andric
414c3b054d2SDimitry Andric NestedNameSpecifierLoc First = *this;
415c3b054d2SDimitry Andric while (NestedNameSpecifierLoc Prefix = First.getPrefix())
416c3b054d2SDimitry Andric First = Prefix;
417c3b054d2SDimitry Andric
418c3b054d2SDimitry Andric return SourceRange(First.getLocalSourceRange().getBegin(),
419c3b054d2SDimitry Andric getLocalSourceRange().getEnd());
420c3b054d2SDimitry Andric }
421c3b054d2SDimitry Andric
getLocalSourceRange() const422c3b054d2SDimitry Andric SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
423c3b054d2SDimitry Andric if (!Qualifier)
424c3b054d2SDimitry Andric return SourceRange();
425c3b054d2SDimitry Andric
426c3b054d2SDimitry Andric unsigned Offset = getDataLength(Qualifier->getPrefix());
427c3b054d2SDimitry Andric switch (Qualifier->getKind()) {
428c3b054d2SDimitry Andric case NestedNameSpecifier::Global:
429c3b054d2SDimitry Andric return LoadSourceLocation(Data, Offset);
430c3b054d2SDimitry Andric
431c3b054d2SDimitry Andric case NestedNameSpecifier::Identifier:
432c3b054d2SDimitry Andric case NestedNameSpecifier::Namespace:
433c3b054d2SDimitry Andric case NestedNameSpecifier::NamespaceAlias:
43406d4ba38SDimitry Andric case NestedNameSpecifier::Super:
435344a3780SDimitry Andric return SourceRange(
436344a3780SDimitry Andric LoadSourceLocation(Data, Offset),
437344a3780SDimitry Andric LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy)));
438c3b054d2SDimitry Andric
439c3b054d2SDimitry Andric case NestedNameSpecifier::TypeSpecWithTemplate:
440c3b054d2SDimitry Andric case NestedNameSpecifier::TypeSpec: {
441c3b054d2SDimitry Andric // The "void*" that points at the TypeLoc data.
442c3b054d2SDimitry Andric // Note: the 'template' keyword is part of the TypeLoc.
443c3b054d2SDimitry Andric void *TypeData = LoadPointer(Data, Offset);
444c3b054d2SDimitry Andric TypeLoc TL(Qualifier->getAsType(), TypeData);
445c3b054d2SDimitry Andric return SourceRange(TL.getBeginLoc(),
446c3b054d2SDimitry Andric LoadSourceLocation(Data, Offset + sizeof(void*)));
447c3b054d2SDimitry Andric }
448c3b054d2SDimitry Andric }
449c3b054d2SDimitry Andric
450dbe13110SDimitry Andric llvm_unreachable("Invalid NNS Kind!");
451c3b054d2SDimitry Andric }
452c3b054d2SDimitry Andric
getTypeLoc() const453c3b054d2SDimitry Andric TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
454676fbe81SDimitry Andric if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
455676fbe81SDimitry Andric Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
456676fbe81SDimitry Andric return TypeLoc();
457c3b054d2SDimitry Andric
458c3b054d2SDimitry Andric // The "void*" that points at the TypeLoc data.
459c3b054d2SDimitry Andric unsigned Offset = getDataLength(Qualifier->getPrefix());
460c3b054d2SDimitry Andric void *TypeData = LoadPointer(Data, Offset);
461c3b054d2SDimitry Andric return TypeLoc(Qualifier->getAsType(), TypeData);
462c3b054d2SDimitry Andric }
46301af97d3SDimitry Andric
Append(char * Start,char * End,char * & Buffer,unsigned & BufferSize,unsigned & BufferCapacity)464461a67faSDimitry Andric static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
46501af97d3SDimitry Andric unsigned &BufferCapacity) {
46636c5ade2SDimitry Andric if (Start == End)
46736c5ade2SDimitry Andric return;
46836c5ade2SDimitry Andric
46901af97d3SDimitry Andric if (BufferSize + (End - Start) > BufferCapacity) {
47001af97d3SDimitry Andric // Reallocate the buffer.
47136c5ade2SDimitry Andric unsigned NewCapacity = std::max(
47236c5ade2SDimitry Andric (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
47301af97d3SDimitry Andric (unsigned)(BufferSize + (End - Start)));
474cfca06d7SDimitry Andric if (!BufferCapacity) {
47548675466SDimitry Andric char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
476cfca06d7SDimitry Andric if (Buffer)
47701af97d3SDimitry Andric memcpy(NewBuffer, Buffer, BufferSize);
47801af97d3SDimitry Andric Buffer = NewBuffer;
479cfca06d7SDimitry Andric } else {
480cfca06d7SDimitry Andric Buffer = static_cast<char *>(llvm::safe_realloc(Buffer, NewCapacity));
481cfca06d7SDimitry Andric }
48201af97d3SDimitry Andric BufferCapacity = NewCapacity;
48301af97d3SDimitry Andric }
484706b4fc4SDimitry Andric assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");
48501af97d3SDimitry Andric memcpy(Buffer + BufferSize, Start, End - Start);
48601af97d3SDimitry Andric BufferSize += End - Start;
48701af97d3SDimitry Andric }
48801af97d3SDimitry Andric
48948675466SDimitry Andric /// Save a source location to the given buffer.
SaveSourceLocation(SourceLocation Loc,char * & Buffer,unsigned & BufferSize,unsigned & BufferCapacity)490461a67faSDimitry Andric static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
49101af97d3SDimitry Andric unsigned &BufferSize, unsigned &BufferCapacity) {
492344a3780SDimitry Andric SourceLocation::UIntTy Raw = Loc.getRawEncoding();
49301af97d3SDimitry Andric Append(reinterpret_cast<char *>(&Raw),
494344a3780SDimitry Andric reinterpret_cast<char *>(&Raw) + sizeof(Raw), Buffer, BufferSize,
495344a3780SDimitry Andric BufferCapacity);
49601af97d3SDimitry Andric }
49701af97d3SDimitry Andric
49848675466SDimitry Andric /// Save a pointer to the given buffer.
SavePointer(void * Ptr,char * & Buffer,unsigned & BufferSize,unsigned & BufferCapacity)499461a67faSDimitry Andric static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
50001af97d3SDimitry Andric unsigned &BufferCapacity) {
50101af97d3SDimitry Andric Append(reinterpret_cast<char *>(&Ptr),
50201af97d3SDimitry Andric reinterpret_cast<char *>(&Ptr) + sizeof(void *),
50301af97d3SDimitry Andric Buffer, BufferSize, BufferCapacity);
50401af97d3SDimitry Andric }
50501af97d3SDimitry Andric
50601af97d3SDimitry Andric NestedNameSpecifierLocBuilder::
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder & Other)50701af97d3SDimitry Andric NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
508461a67faSDimitry Andric : Representation(Other.Representation) {
50901af97d3SDimitry Andric if (!Other.Buffer)
51001af97d3SDimitry Andric return;
51101af97d3SDimitry Andric
51201af97d3SDimitry Andric if (Other.BufferCapacity == 0) {
51301af97d3SDimitry Andric // Shallow copy is okay.
51401af97d3SDimitry Andric Buffer = Other.Buffer;
51501af97d3SDimitry Andric BufferSize = Other.BufferSize;
51601af97d3SDimitry Andric return;
51701af97d3SDimitry Andric }
51801af97d3SDimitry Andric
51901af97d3SDimitry Andric // Deep copy
5209f4dbff6SDimitry Andric Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
5219f4dbff6SDimitry Andric BufferCapacity);
52201af97d3SDimitry Andric }
52301af97d3SDimitry Andric
52401af97d3SDimitry Andric NestedNameSpecifierLocBuilder &
52501af97d3SDimitry Andric NestedNameSpecifierLocBuilder::
operator =(const NestedNameSpecifierLocBuilder & Other)52601af97d3SDimitry Andric operator=(const NestedNameSpecifierLocBuilder &Other) {
52701af97d3SDimitry Andric Representation = Other.Representation;
52801af97d3SDimitry Andric
52901af97d3SDimitry Andric if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
53001af97d3SDimitry Andric // Re-use our storage.
53101af97d3SDimitry Andric BufferSize = Other.BufferSize;
53201af97d3SDimitry Andric memcpy(Buffer, Other.Buffer, BufferSize);
53301af97d3SDimitry Andric return *this;
53401af97d3SDimitry Andric }
53501af97d3SDimitry Andric
53601af97d3SDimitry Andric // Free our storage, if we have any.
53701af97d3SDimitry Andric if (BufferCapacity) {
53801af97d3SDimitry Andric free(Buffer);
53901af97d3SDimitry Andric BufferCapacity = 0;
54001af97d3SDimitry Andric }
54101af97d3SDimitry Andric
54201af97d3SDimitry Andric if (!Other.Buffer) {
54301af97d3SDimitry Andric // Empty.
5449f4dbff6SDimitry Andric Buffer = nullptr;
54501af97d3SDimitry Andric BufferSize = 0;
54601af97d3SDimitry Andric return *this;
54701af97d3SDimitry Andric }
54801af97d3SDimitry Andric
54901af97d3SDimitry Andric if (Other.BufferCapacity == 0) {
55001af97d3SDimitry Andric // Shallow copy is okay.
55101af97d3SDimitry Andric Buffer = Other.Buffer;
55201af97d3SDimitry Andric BufferSize = Other.BufferSize;
55301af97d3SDimitry Andric return *this;
55401af97d3SDimitry Andric }
55501af97d3SDimitry Andric
55601af97d3SDimitry Andric // Deep copy.
557676fbe81SDimitry Andric BufferSize = 0;
5589f4dbff6SDimitry Andric Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
5599f4dbff6SDimitry Andric BufferCapacity);
56001af97d3SDimitry Andric return *this;
56101af97d3SDimitry Andric }
56201af97d3SDimitry Andric
Extend(ASTContext & Context,SourceLocation TemplateKWLoc,TypeLoc TL,SourceLocation ColonColonLoc)56301af97d3SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
56401af97d3SDimitry Andric SourceLocation TemplateKWLoc,
56501af97d3SDimitry Andric TypeLoc TL,
56601af97d3SDimitry Andric SourceLocation ColonColonLoc) {
56701af97d3SDimitry Andric Representation = NestedNameSpecifier::Create(Context, Representation,
56801af97d3SDimitry Andric TemplateKWLoc.isValid(),
56901af97d3SDimitry Andric TL.getTypePtr());
57001af97d3SDimitry Andric
57101af97d3SDimitry Andric // Push source-location info into the buffer.
57201af97d3SDimitry Andric SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
57301af97d3SDimitry Andric SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
57401af97d3SDimitry Andric }
57501af97d3SDimitry Andric
Extend(ASTContext & Context,IdentifierInfo * Identifier,SourceLocation IdentifierLoc,SourceLocation ColonColonLoc)57601af97d3SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
57701af97d3SDimitry Andric IdentifierInfo *Identifier,
57801af97d3SDimitry Andric SourceLocation IdentifierLoc,
57901af97d3SDimitry Andric SourceLocation ColonColonLoc) {
58001af97d3SDimitry Andric Representation = NestedNameSpecifier::Create(Context, Representation,
58101af97d3SDimitry Andric Identifier);
58201af97d3SDimitry Andric
58301af97d3SDimitry Andric // Push source-location info into the buffer.
58401af97d3SDimitry Andric SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
58501af97d3SDimitry Andric SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
58601af97d3SDimitry Andric }
58701af97d3SDimitry Andric
Extend(ASTContext & Context,NamespaceDecl * Namespace,SourceLocation NamespaceLoc,SourceLocation ColonColonLoc)58801af97d3SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
58901af97d3SDimitry Andric NamespaceDecl *Namespace,
59001af97d3SDimitry Andric SourceLocation NamespaceLoc,
59101af97d3SDimitry Andric SourceLocation ColonColonLoc) {
59201af97d3SDimitry Andric Representation = NestedNameSpecifier::Create(Context, Representation,
59301af97d3SDimitry Andric Namespace);
59401af97d3SDimitry Andric
59501af97d3SDimitry Andric // Push source-location info into the buffer.
59601af97d3SDimitry Andric SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
59701af97d3SDimitry Andric SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
59801af97d3SDimitry Andric }
59901af97d3SDimitry Andric
Extend(ASTContext & Context,NamespaceAliasDecl * Alias,SourceLocation AliasLoc,SourceLocation ColonColonLoc)60001af97d3SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
60101af97d3SDimitry Andric NamespaceAliasDecl *Alias,
60201af97d3SDimitry Andric SourceLocation AliasLoc,
60301af97d3SDimitry Andric SourceLocation ColonColonLoc) {
60401af97d3SDimitry Andric Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
60501af97d3SDimitry Andric
60601af97d3SDimitry Andric // Push source-location info into the buffer.
60701af97d3SDimitry Andric SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
60801af97d3SDimitry Andric SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
60901af97d3SDimitry Andric }
61001af97d3SDimitry Andric
MakeGlobal(ASTContext & Context,SourceLocation ColonColonLoc)61101af97d3SDimitry Andric void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
61201af97d3SDimitry Andric SourceLocation ColonColonLoc) {
61301af97d3SDimitry Andric assert(!Representation && "Already have a nested-name-specifier!?");
61401af97d3SDimitry Andric Representation = NestedNameSpecifier::GlobalSpecifier(Context);
61501af97d3SDimitry Andric
61601af97d3SDimitry Andric // Push source-location info into the buffer.
61701af97d3SDimitry Andric SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
61801af97d3SDimitry Andric }
61901af97d3SDimitry Andric
MakeSuper(ASTContext & Context,CXXRecordDecl * RD,SourceLocation SuperLoc,SourceLocation ColonColonLoc)62006d4ba38SDimitry Andric void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
62106d4ba38SDimitry Andric CXXRecordDecl *RD,
62206d4ba38SDimitry Andric SourceLocation SuperLoc,
62306d4ba38SDimitry Andric SourceLocation ColonColonLoc) {
62406d4ba38SDimitry Andric Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
62506d4ba38SDimitry Andric
62606d4ba38SDimitry Andric // Push source-location info into the buffer.
62706d4ba38SDimitry Andric SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
62806d4ba38SDimitry Andric SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
62906d4ba38SDimitry Andric }
63006d4ba38SDimitry Andric
MakeTrivial(ASTContext & Context,NestedNameSpecifier * Qualifier,SourceRange R)63101af97d3SDimitry Andric void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
63201af97d3SDimitry Andric NestedNameSpecifier *Qualifier,
63301af97d3SDimitry Andric SourceRange R) {
63401af97d3SDimitry Andric Representation = Qualifier;
63501af97d3SDimitry Andric
63601af97d3SDimitry Andric // Construct bogus (but well-formed) source information for the
63701af97d3SDimitry Andric // nested-name-specifier.
63801af97d3SDimitry Andric BufferSize = 0;
63936981b17SDimitry Andric SmallVector<NestedNameSpecifier *, 4> Stack;
64001af97d3SDimitry Andric for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
64101af97d3SDimitry Andric Stack.push_back(NNS);
64201af97d3SDimitry Andric while (!Stack.empty()) {
643bfef3995SDimitry Andric NestedNameSpecifier *NNS = Stack.pop_back_val();
64401af97d3SDimitry Andric switch (NNS->getKind()) {
64501af97d3SDimitry Andric case NestedNameSpecifier::Identifier:
64601af97d3SDimitry Andric case NestedNameSpecifier::Namespace:
64701af97d3SDimitry Andric case NestedNameSpecifier::NamespaceAlias:
64801af97d3SDimitry Andric SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
64901af97d3SDimitry Andric break;
65001af97d3SDimitry Andric
65101af97d3SDimitry Andric case NestedNameSpecifier::TypeSpec:
65201af97d3SDimitry Andric case NestedNameSpecifier::TypeSpecWithTemplate: {
65301af97d3SDimitry Andric TypeSourceInfo *TSInfo
65401af97d3SDimitry Andric = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
65501af97d3SDimitry Andric R.getBegin());
65601af97d3SDimitry Andric SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
65701af97d3SDimitry Andric BufferCapacity);
65801af97d3SDimitry Andric break;
65901af97d3SDimitry Andric }
66001af97d3SDimitry Andric
66101af97d3SDimitry Andric case NestedNameSpecifier::Global:
66206d4ba38SDimitry Andric case NestedNameSpecifier::Super:
66301af97d3SDimitry Andric break;
66401af97d3SDimitry Andric }
66501af97d3SDimitry Andric
66601af97d3SDimitry Andric // Save the location of the '::'.
66701af97d3SDimitry Andric SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
66801af97d3SDimitry Andric Buffer, BufferSize, BufferCapacity);
66901af97d3SDimitry Andric }
67001af97d3SDimitry Andric }
67101af97d3SDimitry Andric
Adopt(NestedNameSpecifierLoc Other)67201af97d3SDimitry Andric void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
67301af97d3SDimitry Andric if (BufferCapacity)
67401af97d3SDimitry Andric free(Buffer);
67501af97d3SDimitry Andric
67601af97d3SDimitry Andric if (!Other) {
6779f4dbff6SDimitry Andric Representation = nullptr;
67801af97d3SDimitry Andric BufferSize = 0;
67901af97d3SDimitry Andric return;
68001af97d3SDimitry Andric }
68101af97d3SDimitry Andric
68201af97d3SDimitry Andric // Rather than copying the data (which is wasteful), "adopt" the
68301af97d3SDimitry Andric // pointer (which points into the ASTContext) but set the capacity to zero to
68401af97d3SDimitry Andric // indicate that we don't own it.
68501af97d3SDimitry Andric Representation = Other.getNestedNameSpecifier();
68601af97d3SDimitry Andric Buffer = static_cast<char *>(Other.getOpaqueData());
68701af97d3SDimitry Andric BufferSize = Other.getDataLength();
68801af97d3SDimitry Andric BufferCapacity = 0;
68901af97d3SDimitry Andric }
69001af97d3SDimitry Andric
69101af97d3SDimitry Andric NestedNameSpecifierLoc
getWithLocInContext(ASTContext & Context) const69201af97d3SDimitry Andric NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
69301af97d3SDimitry Andric if (!Representation)
69401af97d3SDimitry Andric return NestedNameSpecifierLoc();
69501af97d3SDimitry Andric
69601af97d3SDimitry Andric // If we adopted our data pointer from elsewhere in the AST context, there's
69701af97d3SDimitry Andric // no need to copy the memory.
69801af97d3SDimitry Andric if (BufferCapacity == 0)
69901af97d3SDimitry Andric return NestedNameSpecifierLoc(Representation, Buffer);
70001af97d3SDimitry Andric
70101af97d3SDimitry Andric // FIXME: After copying the source-location information, should we free
70201af97d3SDimitry Andric // our (temporary) buffer and adopt the ASTContext-allocated memory?
70301af97d3SDimitry Andric // Doing so would optimize repeated calls to getWithLocInContext().
704bab175ecSDimitry Andric void *Mem = Context.Allocate(BufferSize, alignof(void *));
70501af97d3SDimitry Andric memcpy(Mem, Buffer, BufferSize);
70601af97d3SDimitry Andric return NestedNameSpecifierLoc(Representation, Mem);
70701af97d3SDimitry Andric }
708