xref: /src/contrib/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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