121fadadbSEugene Zelenko //===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
25253768aSDouglas Gregor //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65253768aSDouglas Gregor //
75253768aSDouglas Gregor //===----------------------------------------------------------------------===//
85253768aSDouglas Gregor //
95253768aSDouglas Gregor //  This file defines the NestedNameSpecifier class, which represents
105253768aSDouglas Gregor //  a C++ nested-name-specifier.
115253768aSDouglas Gregor //
125253768aSDouglas Gregor //===----------------------------------------------------------------------===//
1321fadadbSEugene Zelenko 
145253768aSDouglas Gregor #include "clang/AST/NestedNameSpecifier.h"
155253768aSDouglas Gregor #include "clang/AST/ASTContext.h"
165253768aSDouglas Gregor #include "clang/AST/Decl.h"
177b26ff91SDouglas Gregor #include "clang/AST/DeclCXX.h"
189d432e0dSClement Courbet #include "clang/AST/DeclTemplate.h"
1967d25914SHaojian Wu #include "clang/AST/DependenceFlags.h"
207de5966dSDouglas Gregor #include "clang/AST/PrettyPrinter.h"
2121fadadbSEugene Zelenko #include "clang/AST/TemplateName.h"
225253768aSDouglas Gregor #include "clang/AST/Type.h"
23869ad45fSDouglas Gregor #include "clang/AST/TypeLoc.h"
2421fadadbSEugene Zelenko #include "clang/Basic/LLVM.h"
2521fadadbSEugene Zelenko #include "clang/Basic/LangOptions.h"
2621fadadbSEugene Zelenko #include "clang/Basic/SourceLocation.h"
2721fadadbSEugene Zelenko #include "llvm/ADT/FoldingSet.h"
2821fadadbSEugene Zelenko #include "llvm/ADT/SmallVector.h"
2921fadadbSEugene Zelenko #include "llvm/Support/Casting.h"
3021fadadbSEugene Zelenko #include "llvm/Support/Compiler.h"
3121fadadbSEugene Zelenko #include "llvm/Support/ErrorHandling.h"
3218353910SDouglas Gregor #include "llvm/Support/raw_ostream.h"
3321fadadbSEugene Zelenko #include <algorithm>
34f21eb49aSDouglas Gregor #include <cassert>
3521fadadbSEugene Zelenko #include <cstdlib>
3621fadadbSEugene Zelenko #include <cstring>
3718353910SDouglas Gregor 
385253768aSDouglas Gregor using namespace clang;
395253768aSDouglas Gregor 
40f21eb49aSDouglas Gregor NestedNameSpecifier *
FindOrInsert(const ASTContext & Context,const NestedNameSpecifier & Mockup)4139c79807SJay Foad NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
42f21eb49aSDouglas Gregor                                   const NestedNameSpecifier &Mockup) {
43f21eb49aSDouglas Gregor   llvm::FoldingSetNodeID ID;
44f21eb49aSDouglas Gregor   Mockup.Profile(ID);
455253768aSDouglas Gregor 
4636250ad6SCraig Topper   void *InsertPos = nullptr;
47f21eb49aSDouglas Gregor   NestedNameSpecifier *NNS
48f21eb49aSDouglas Gregor     = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
49f21eb49aSDouglas Gregor   if (!NNS) {
50c3f89253SBenjamin Kramer     NNS =
51c3f89253SBenjamin Kramer         new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
52f21eb49aSDouglas Gregor     Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
535253768aSDouglas Gregor   }
5418353910SDouglas Gregor 
55f21eb49aSDouglas Gregor   return NNS;
56f21eb49aSDouglas Gregor }
57f21eb49aSDouglas Gregor 
58f21eb49aSDouglas Gregor NestedNameSpecifier *
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,IdentifierInfo * II)5939c79807SJay Foad NestedNameSpecifier::Create(const ASTContext &Context,
6039c79807SJay Foad                             NestedNameSpecifier *Prefix, IdentifierInfo *II) {
61f21eb49aSDouglas Gregor   assert(II && "Identifier cannot be NULL");
62308047d3SDouglas Gregor   assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
63f21eb49aSDouglas Gregor 
64f21eb49aSDouglas Gregor   NestedNameSpecifier Mockup;
65dce2b62bSDouglas Gregor   Mockup.Prefix.setPointer(Prefix);
667b26ff91SDouglas Gregor   Mockup.Prefix.setInt(StoredIdentifier);
67dce2b62bSDouglas Gregor   Mockup.Specifier = II;
68f21eb49aSDouglas Gregor   return FindOrInsert(Context, Mockup);
69f21eb49aSDouglas Gregor }
70f21eb49aSDouglas Gregor 
71f21eb49aSDouglas Gregor NestedNameSpecifier *
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,const NamespaceDecl * NS)7239c79807SJay Foad NestedNameSpecifier::Create(const ASTContext &Context,
73aeeca770SDmitri Gribenko                             NestedNameSpecifier *Prefix,
74aeeca770SDmitri Gribenko                             const NamespaceDecl *NS) {
75f21eb49aSDouglas Gregor   assert(NS && "Namespace cannot be NULL");
76f21eb49aSDouglas Gregor   assert((!Prefix ||
7736250ad6SCraig Topper           (Prefix->getAsType() == nullptr &&
7836250ad6SCraig Topper            Prefix->getAsIdentifier() == nullptr)) &&
79f21eb49aSDouglas Gregor          "Broken nested name specifier");
80f21eb49aSDouglas Gregor   NestedNameSpecifier Mockup;
81dce2b62bSDouglas Gregor   Mockup.Prefix.setPointer(Prefix);
8267860249SNikola Smiljanic   Mockup.Prefix.setInt(StoredDecl);
83aeeca770SDmitri Gribenko   Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
84f21eb49aSDouglas Gregor   return FindOrInsert(Context, Mockup);
85f21eb49aSDouglas Gregor }
86f21eb49aSDouglas Gregor 
87f21eb49aSDouglas Gregor NestedNameSpecifier *
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,NamespaceAliasDecl * Alias)8839c79807SJay Foad NestedNameSpecifier::Create(const ASTContext &Context,
8939c79807SJay Foad                             NestedNameSpecifier *Prefix,
907b26ff91SDouglas Gregor                             NamespaceAliasDecl *Alias) {
917b26ff91SDouglas Gregor   assert(Alias && "Namespace alias cannot be NULL");
927b26ff91SDouglas Gregor   assert((!Prefix ||
9336250ad6SCraig Topper           (Prefix->getAsType() == nullptr &&
9436250ad6SCraig Topper            Prefix->getAsIdentifier() == nullptr)) &&
957b26ff91SDouglas Gregor          "Broken nested name specifier");
967b26ff91SDouglas Gregor   NestedNameSpecifier Mockup;
977b26ff91SDouglas Gregor   Mockup.Prefix.setPointer(Prefix);
9867860249SNikola Smiljanic   Mockup.Prefix.setInt(StoredDecl);
997b26ff91SDouglas Gregor   Mockup.Specifier = Alias;
1007b26ff91SDouglas Gregor   return FindOrInsert(Context, Mockup);
1017b26ff91SDouglas Gregor }
1027b26ff91SDouglas Gregor 
1037b26ff91SDouglas Gregor NestedNameSpecifier *
Create(const ASTContext & Context,NestedNameSpecifier * Prefix,bool Template,const Type * T)1047b26ff91SDouglas Gregor NestedNameSpecifier::Create(const ASTContext &Context,
1057b26ff91SDouglas Gregor                             NestedNameSpecifier *Prefix,
106424cec97SJohn McCall                             bool Template, const Type *T) {
107f21eb49aSDouglas Gregor   assert(T && "Type cannot be NULL");
108f21eb49aSDouglas Gregor   NestedNameSpecifier Mockup;
109dce2b62bSDouglas Gregor   Mockup.Prefix.setPointer(Prefix);
1107b26ff91SDouglas Gregor   Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
111424cec97SJohn McCall   Mockup.Specifier = const_cast<Type*>(T);
112f21eb49aSDouglas Gregor   return FindOrInsert(Context, Mockup);
113f21eb49aSDouglas Gregor }
114f21eb49aSDouglas Gregor 
11564792e02SDouglas Gregor NestedNameSpecifier *
Create(const ASTContext & Context,IdentifierInfo * II)11639c79807SJay Foad NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
11764792e02SDouglas Gregor   assert(II && "Identifier cannot be NULL");
11864792e02SDouglas Gregor   NestedNameSpecifier Mockup;
11936250ad6SCraig Topper   Mockup.Prefix.setPointer(nullptr);
1207b26ff91SDouglas Gregor   Mockup.Prefix.setInt(StoredIdentifier);
12164792e02SDouglas Gregor   Mockup.Specifier = II;
12264792e02SDouglas Gregor   return FindOrInsert(Context, Mockup);
12364792e02SDouglas Gregor }
12464792e02SDouglas Gregor 
12539c79807SJay Foad NestedNameSpecifier *
GlobalSpecifier(const ASTContext & Context)12639c79807SJay Foad NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
127f21eb49aSDouglas Gregor   if (!Context.GlobalNestedNameSpecifier)
128beb386abSRichard Smith     Context.GlobalNestedNameSpecifier =
129c3f89253SBenjamin Kramer         new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
130f21eb49aSDouglas Gregor   return Context.GlobalNestedNameSpecifier;
131f21eb49aSDouglas Gregor }
132f21eb49aSDouglas Gregor 
13367860249SNikola Smiljanic NestedNameSpecifier *
SuperSpecifier(const ASTContext & Context,CXXRecordDecl * RD)13467860249SNikola Smiljanic NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
13567860249SNikola Smiljanic                                     CXXRecordDecl *RD) {
13667860249SNikola Smiljanic   NestedNameSpecifier Mockup;
13767860249SNikola Smiljanic   Mockup.Prefix.setPointer(nullptr);
13867860249SNikola Smiljanic   Mockup.Prefix.setInt(StoredDecl);
13967860249SNikola Smiljanic   Mockup.Specifier = RD;
14067860249SNikola Smiljanic   return FindOrInsert(Context, Mockup);
14167860249SNikola Smiljanic }
14267860249SNikola Smiljanic 
getKind() const1437b26ff91SDouglas Gregor NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
14436250ad6SCraig Topper   if (!Specifier)
1457b26ff91SDouglas Gregor     return Global;
1467b26ff91SDouglas Gregor 
1477b26ff91SDouglas Gregor   switch (Prefix.getInt()) {
1487b26ff91SDouglas Gregor   case StoredIdentifier:
1497b26ff91SDouglas Gregor     return Identifier;
1507b26ff91SDouglas Gregor 
15167860249SNikola Smiljanic   case StoredDecl: {
15267860249SNikola Smiljanic     NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
15367860249SNikola Smiljanic     if (isa<CXXRecordDecl>(ND))
15467860249SNikola Smiljanic       return Super;
15567860249SNikola Smiljanic     return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
15667860249SNikola Smiljanic   }
1577b26ff91SDouglas Gregor 
1587b26ff91SDouglas Gregor   case StoredTypeSpec:
1597b26ff91SDouglas Gregor     return TypeSpec;
1607b26ff91SDouglas Gregor 
1617b26ff91SDouglas Gregor   case StoredTypeSpecWithTemplate:
1627b26ff91SDouglas Gregor     return TypeSpecWithTemplate;
1637b26ff91SDouglas Gregor   }
1647b26ff91SDouglas Gregor 
165e4d798f0SDavid Blaikie   llvm_unreachable("Invalid NNS Kind!");
1667b26ff91SDouglas Gregor }
1677b26ff91SDouglas Gregor 
1689fc8faf9SAdrian Prantl /// Retrieve the namespace stored in this nested name specifier.
getAsNamespace() const1697b26ff91SDouglas Gregor NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
17067860249SNikola Smiljanic   if (Prefix.getInt() == StoredDecl)
1717b26ff91SDouglas Gregor     return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
1727b26ff91SDouglas Gregor 
17336250ad6SCraig Topper   return nullptr;
1747b26ff91SDouglas Gregor }
1757b26ff91SDouglas Gregor 
1769fc8faf9SAdrian Prantl /// Retrieve the namespace alias stored in this nested name specifier.
getAsNamespaceAlias() const1777b26ff91SDouglas Gregor NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
17867860249SNikola Smiljanic   if (Prefix.getInt() == StoredDecl)
1797b26ff91SDouglas Gregor     return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
1807b26ff91SDouglas Gregor 
18136250ad6SCraig Topper   return nullptr;
1827b26ff91SDouglas Gregor }
1837b26ff91SDouglas Gregor 
1849fc8faf9SAdrian Prantl /// Retrieve the record declaration stored in this nested name specifier.
getAsRecordDecl() const18567860249SNikola Smiljanic CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
1865179eb78SRichard Smith   switch (Prefix.getInt()) {
1875179eb78SRichard Smith   case StoredIdentifier:
1885179eb78SRichard Smith     return nullptr;
1895179eb78SRichard Smith 
1905179eb78SRichard Smith   case StoredDecl:
19167860249SNikola Smiljanic     return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
19267860249SNikola Smiljanic 
1935179eb78SRichard Smith   case StoredTypeSpec:
1945179eb78SRichard Smith   case StoredTypeSpecWithTemplate:
1955179eb78SRichard Smith     return getAsType()->getAsCXXRecordDecl();
1965179eb78SRichard Smith   }
1975179eb78SRichard Smith 
1985179eb78SRichard Smith   llvm_unreachable("Invalid NNS Kind!");
19967860249SNikola Smiljanic }
2007b26ff91SDouglas Gregor 
getDependence() const201ec3060c7SIlya Biryukov NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
202f21eb49aSDouglas Gregor   switch (getKind()) {
203ec3060c7SIlya Biryukov   case Identifier: {
204f21eb49aSDouglas Gregor     // Identifier specifiers always represent dependent types
205ec3060c7SIlya Biryukov     auto F = NestedNameSpecifierDependence::Dependent |
206ec3060c7SIlya Biryukov              NestedNameSpecifierDependence::Instantiation;
207ec3060c7SIlya Biryukov     // Prefix can contain unexpanded template parameters.
208ec3060c7SIlya Biryukov     if (getPrefix())
209ec3060c7SIlya Biryukov       return F | getPrefix()->getDependence();
210ec3060c7SIlya Biryukov     return F;
211ec3060c7SIlya Biryukov   }
212f21eb49aSDouglas Gregor 
213f21eb49aSDouglas Gregor   case Namespace:
2147b26ff91SDouglas Gregor   case NamespaceAlias:
215f21eb49aSDouglas Gregor   case Global:
216ec3060c7SIlya Biryukov     return NestedNameSpecifierDependence::None;
217f21eb49aSDouglas Gregor 
21867860249SNikola Smiljanic   case Super: {
21967860249SNikola Smiljanic     CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
22067860249SNikola Smiljanic     for (const auto &Base : RD->bases())
22167860249SNikola Smiljanic       if (Base.getType()->isDependentType())
222ec3060c7SIlya Biryukov         // FIXME: must also be instantiation-dependent.
223ec3060c7SIlya Biryukov         return NestedNameSpecifierDependence::Dependent;
224ec3060c7SIlya Biryukov     return NestedNameSpecifierDependence::None;
22567860249SNikola Smiljanic   }
22667860249SNikola Smiljanic 
227f21eb49aSDouglas Gregor   case TypeSpec:
228f21eb49aSDouglas Gregor   case TypeSpecWithTemplate:
229ec3060c7SIlya Biryukov     return toNestedNameSpecifierDependendence(getAsType()->getDependence());
230f21eb49aSDouglas Gregor   }
231e4d798f0SDavid Blaikie   llvm_unreachable("Invalid NNS Kind!");
232f21eb49aSDouglas Gregor }
233f21eb49aSDouglas Gregor 
isDependent() const234ec3060c7SIlya Biryukov bool NestedNameSpecifier::isDependent() const {
235ec3060c7SIlya Biryukov   return getDependence() & NestedNameSpecifierDependence::Dependent;
236ec3060c7SIlya Biryukov }
237ec3060c7SIlya Biryukov 
isInstantiationDependent() const238678d76c0SDouglas Gregor bool NestedNameSpecifier::isInstantiationDependent() const {
239ec3060c7SIlya Biryukov   return getDependence() & NestedNameSpecifierDependence::Instantiation;
240678d76c0SDouglas Gregor }
241678d76c0SDouglas Gregor 
containsUnexpandedParameterPack() const242506bd564SDouglas Gregor bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
243ec3060c7SIlya Biryukov   return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
244506bd564SDouglas Gregor }
245506bd564SDouglas Gregor 
containsErrors() const246d285f293SHaojian Wu bool NestedNameSpecifier::containsErrors() const {
247d285f293SHaojian Wu   return getDependence() & NestedNameSpecifierDependence::Error;
248d285f293SHaojian Wu }
249d285f293SHaojian Wu 
2509fc8faf9SAdrian Prantl /// Print this nested name specifier to the given output
251f21eb49aSDouglas Gregor /// stream.
print(raw_ostream & OS,const PrintingPolicy & Policy,bool ResolveTemplateArguments) const2529d432e0dSClement Courbet void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
2539d432e0dSClement Courbet                                 bool ResolveTemplateArguments) const {
254dce2b62bSDouglas Gregor   if (getPrefix())
2557de5966dSDouglas Gregor     getPrefix()->print(OS, Policy);
256f21eb49aSDouglas Gregor 
257f21eb49aSDouglas Gregor   switch (getKind()) {
258f21eb49aSDouglas Gregor   case Identifier:
259f21eb49aSDouglas Gregor     OS << getAsIdentifier()->getName();
260f21eb49aSDouglas Gregor     break;
261f21eb49aSDouglas Gregor 
262f21eb49aSDouglas Gregor   case Namespace:
2632e10cf96SDouglas Gregor     if (getAsNamespace()->isAnonymousNamespace())
2642e10cf96SDouglas Gregor       return;
2652e10cf96SDouglas Gregor 
2667b26ff91SDouglas Gregor     OS << getAsNamespace()->getName();
2677b26ff91SDouglas Gregor     break;
2687b26ff91SDouglas Gregor 
2697b26ff91SDouglas Gregor   case NamespaceAlias:
2707b26ff91SDouglas Gregor     OS << getAsNamespaceAlias()->getName();
271f21eb49aSDouglas Gregor     break;
272f21eb49aSDouglas Gregor 
273f21eb49aSDouglas Gregor   case Global:
274f21eb49aSDouglas Gregor     break;
275f21eb49aSDouglas Gregor 
27667860249SNikola Smiljanic   case Super:
27767860249SNikola Smiljanic     OS << "__super";
27867860249SNikola Smiljanic     break;
27967860249SNikola Smiljanic 
280f21eb49aSDouglas Gregor   case TypeSpecWithTemplate:
281f21eb49aSDouglas Gregor     OS << "template ";
282f21eb49aSDouglas Gregor     // Fall through to print the type.
283f87496d1SGalina Kistanova     LLVM_FALLTHROUGH;
284f21eb49aSDouglas Gregor 
285f21eb49aSDouglas Gregor   case TypeSpec: {
2869d432e0dSClement Courbet     const auto *Record =
2879d432e0dSClement Courbet             dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
2889d432e0dSClement Courbet     if (ResolveTemplateArguments && Record) {
2899d432e0dSClement Courbet         // Print the type trait with resolved template parameters.
2909d432e0dSClement Courbet         Record->printName(OS);
29199d63ccfSPratyush Das         printTemplateArgumentList(
29299d63ccfSPratyush Das             OS, Record->getTemplateArgs().asArray(), Policy,
29399d63ccfSPratyush Das             Record->getSpecializedTemplate()->getTemplateParameters());
2949d432e0dSClement Courbet         break;
2959d432e0dSClement Courbet     }
296424cec97SJohn McCall     const Type *T = getAsType();
29718353910SDouglas Gregor 
2987de5966dSDouglas Gregor     PrintingPolicy InnerPolicy(Policy);
299b2e195a5SJohn McCall     InnerPolicy.SuppressScope = true;
300053f691dSDouglas Gregor 
301053f691dSDouglas Gregor     // Nested-name-specifiers are intended to contain minimally-qualified
3026150c884SAbramo Bagnara     // types. An actual ElaboratedType will not occur, since we'll store
303053f691dSDouglas Gregor     // just the type that is referred to in the nested-name-specifier (e.g.,
304053f691dSDouglas Gregor     // a TypedefType, TagType, etc.). However, when we are dealing with
305053f691dSDouglas Gregor     // dependent template-id types (e.g., Outer<T>::template Inner<U>),
306053f691dSDouglas Gregor     // the type requires its own nested-name-specifier for uniqueness, so we
307053f691dSDouglas Gregor     // suppress that nested-name-specifier during printing.
3086150c884SAbramo Bagnara     assert(!isa<ElaboratedType>(T) &&
3096150c884SAbramo Bagnara            "Elaborated type in nested-name-specifier");
310053f691dSDouglas Gregor     if (const TemplateSpecializationType *SpecType
311053f691dSDouglas Gregor           = dyn_cast<TemplateSpecializationType>(T)) {
312053f691dSDouglas Gregor       // Print the template name without its corresponding
313053f691dSDouglas Gregor       // nested-name-specifier.
314*5fb3f437SDavid Blaikie       SpecType->getTemplateName().print(OS, InnerPolicy,
315*5fb3f437SDavid Blaikie                                         TemplateName::Qualified::None);
316053f691dSDouglas Gregor 
317053f691dSDouglas Gregor       // Print the template argument list.
31803e672ccSSerge Pavlov       printTemplateArgumentList(OS, SpecType->template_arguments(),
31903e672ccSSerge Pavlov                                 InnerPolicy);
3200642e5e7SMatthias Gehre     } else if (const auto *DepSpecType =
3210642e5e7SMatthias Gehre                    dyn_cast<DependentTemplateSpecializationType>(T)) {
3220642e5e7SMatthias Gehre       // Print the template name without its corresponding
3230642e5e7SMatthias Gehre       // nested-name-specifier.
3240642e5e7SMatthias Gehre       OS << DepSpecType->getIdentifier()->getName();
3250642e5e7SMatthias Gehre       // Print the template argument list.
3260642e5e7SMatthias Gehre       printTemplateArgumentList(OS, DepSpecType->template_arguments(),
3270642e5e7SMatthias Gehre                                 InnerPolicy);
328053f691dSDouglas Gregor     } else {
329053f691dSDouglas Gregor       // Print the type normally
3309170e914SBenjamin Kramer       QualType(T, 0).print(OS, InnerPolicy);
331053f691dSDouglas Gregor     }
332f21eb49aSDouglas Gregor     break;
333f21eb49aSDouglas Gregor   }
334f21eb49aSDouglas Gregor   }
33518353910SDouglas Gregor 
33618353910SDouglas Gregor   OS << "::";
33718353910SDouglas Gregor }
338f21eb49aSDouglas Gregor 
dump(const LangOptions & LO) const33907dd5af6SStephen Kelly LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
34007dd5af6SStephen Kelly   dump(llvm::errs(), LO);
341015e6c8aSYaron Keren }
342015e6c8aSYaron Keren 
dump() const34307dd5af6SStephen Kelly LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
34407dd5af6SStephen Kelly 
dump(llvm::raw_ostream & OS) const34507dd5af6SStephen Kelly LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
346015e6c8aSYaron Keren   LangOptions LO;
34707dd5af6SStephen Kelly   dump(OS, LO);
34807dd5af6SStephen Kelly }
34907dd5af6SStephen Kelly 
dump(llvm::raw_ostream & OS,const LangOptions & LO) const35007dd5af6SStephen Kelly LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
35107dd5af6SStephen Kelly                                                 const LangOptions &LO) const {
35207dd5af6SStephen Kelly   print(OS, PrintingPolicy(LO));
353333489bbSDouglas Gregor }
354869ad45fSDouglas Gregor 
355869ad45fSDouglas Gregor unsigned
getLocalDataLength(NestedNameSpecifier * Qualifier)356869ad45fSDouglas Gregor NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
357869ad45fSDouglas Gregor   assert(Qualifier && "Expected a non-NULL qualifier");
358869ad45fSDouglas Gregor 
359869ad45fSDouglas Gregor   // Location of the trailing '::'.
36021401a72SSimon Tatham   unsigned Length = sizeof(SourceLocation::UIntTy);
361869ad45fSDouglas Gregor 
362869ad45fSDouglas Gregor   switch (Qualifier->getKind()) {
363869ad45fSDouglas Gregor   case NestedNameSpecifier::Global:
364869ad45fSDouglas Gregor     // Nothing more to add.
365869ad45fSDouglas Gregor     break;
366869ad45fSDouglas Gregor 
367869ad45fSDouglas Gregor   case NestedNameSpecifier::Identifier:
368869ad45fSDouglas Gregor   case NestedNameSpecifier::Namespace:
369869ad45fSDouglas Gregor   case NestedNameSpecifier::NamespaceAlias:
37067860249SNikola Smiljanic   case NestedNameSpecifier::Super:
371869ad45fSDouglas Gregor     // The location of the identifier or namespace name.
37221401a72SSimon Tatham     Length += sizeof(SourceLocation::UIntTy);
373869ad45fSDouglas Gregor     break;
374869ad45fSDouglas Gregor 
375869ad45fSDouglas Gregor   case NestedNameSpecifier::TypeSpecWithTemplate:
376869ad45fSDouglas Gregor   case NestedNameSpecifier::TypeSpec:
377869ad45fSDouglas Gregor     // The "void*" that points at the TypeLoc data.
378869ad45fSDouglas Gregor     // Note: the 'template' keyword is part of the TypeLoc.
379869ad45fSDouglas Gregor     Length += sizeof(void *);
380869ad45fSDouglas Gregor     break;
381869ad45fSDouglas Gregor   }
382869ad45fSDouglas Gregor 
383869ad45fSDouglas Gregor   return Length;
384869ad45fSDouglas Gregor }
385869ad45fSDouglas Gregor 
386869ad45fSDouglas Gregor unsigned
getDataLength(NestedNameSpecifier * Qualifier)387869ad45fSDouglas Gregor NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
388869ad45fSDouglas Gregor   unsigned Length = 0;
389869ad45fSDouglas Gregor   for (; Qualifier; Qualifier = Qualifier->getPrefix())
390869ad45fSDouglas Gregor     Length += getLocalDataLength(Qualifier);
391869ad45fSDouglas Gregor   return Length;
392869ad45fSDouglas Gregor }
393869ad45fSDouglas Gregor 
3949fc8faf9SAdrian Prantl /// Load a (possibly unaligned) source location from a given address
395869ad45fSDouglas Gregor /// and offset.
LoadSourceLocation(void * Data,unsigned Offset)39621fadadbSEugene Zelenko static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
39721401a72SSimon Tatham   SourceLocation::UIntTy Raw;
39821401a72SSimon Tatham   memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));
399869ad45fSDouglas Gregor   return SourceLocation::getFromRawEncoding(Raw);
400869ad45fSDouglas Gregor }
401869ad45fSDouglas Gregor 
4029fc8faf9SAdrian Prantl /// Load a (possibly unaligned) pointer from a given address and
403869ad45fSDouglas Gregor /// offset.
LoadPointer(void * Data,unsigned Offset)40421fadadbSEugene Zelenko static void *LoadPointer(void *Data, unsigned Offset) {
405869ad45fSDouglas Gregor   void *Result;
406869ad45fSDouglas Gregor   memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
407869ad45fSDouglas Gregor   return Result;
408869ad45fSDouglas Gregor }
409869ad45fSDouglas Gregor 
getSourceRange() const410a9d87bc6SDouglas Gregor SourceRange NestedNameSpecifierLoc::getSourceRange() const {
41112441b3bSDouglas Gregor   if (!Qualifier)
41212441b3bSDouglas Gregor     return SourceRange();
41312441b3bSDouglas Gregor 
414869ad45fSDouglas Gregor   NestedNameSpecifierLoc First = *this;
415869ad45fSDouglas Gregor   while (NestedNameSpecifierLoc Prefix = First.getPrefix())
416869ad45fSDouglas Gregor     First = Prefix;
417869ad45fSDouglas Gregor 
418869ad45fSDouglas Gregor   return SourceRange(First.getLocalSourceRange().getBegin(),
419869ad45fSDouglas Gregor                      getLocalSourceRange().getEnd());
420869ad45fSDouglas Gregor }
421869ad45fSDouglas Gregor 
getLocalSourceRange() const422a9d87bc6SDouglas Gregor SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
42312441b3bSDouglas Gregor   if (!Qualifier)
42412441b3bSDouglas Gregor     return SourceRange();
42512441b3bSDouglas Gregor 
426869ad45fSDouglas Gregor   unsigned Offset = getDataLength(Qualifier->getPrefix());
427869ad45fSDouglas Gregor   switch (Qualifier->getKind()) {
428869ad45fSDouglas Gregor   case NestedNameSpecifier::Global:
429869ad45fSDouglas Gregor     return LoadSourceLocation(Data, Offset);
430869ad45fSDouglas Gregor 
431869ad45fSDouglas Gregor   case NestedNameSpecifier::Identifier:
432869ad45fSDouglas Gregor   case NestedNameSpecifier::Namespace:
433869ad45fSDouglas Gregor   case NestedNameSpecifier::NamespaceAlias:
43467860249SNikola Smiljanic   case NestedNameSpecifier::Super:
43521401a72SSimon Tatham     return SourceRange(
43621401a72SSimon Tatham         LoadSourceLocation(Data, Offset),
43721401a72SSimon Tatham         LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy)));
438869ad45fSDouglas Gregor 
439869ad45fSDouglas Gregor   case NestedNameSpecifier::TypeSpecWithTemplate:
440869ad45fSDouglas Gregor   case NestedNameSpecifier::TypeSpec: {
441869ad45fSDouglas Gregor     // The "void*" that points at the TypeLoc data.
442869ad45fSDouglas Gregor     // Note: the 'template' keyword is part of the TypeLoc.
443869ad45fSDouglas Gregor     void *TypeData = LoadPointer(Data, Offset);
444869ad45fSDouglas Gregor     TypeLoc TL(Qualifier->getAsType(), TypeData);
445869ad45fSDouglas Gregor     return SourceRange(TL.getBeginLoc(),
446869ad45fSDouglas Gregor                        LoadSourceLocation(Data, Offset + sizeof(void*)));
447869ad45fSDouglas Gregor   }
448869ad45fSDouglas Gregor   }
449869ad45fSDouglas Gregor 
450e4d798f0SDavid Blaikie   llvm_unreachable("Invalid NNS Kind!");
451869ad45fSDouglas Gregor }
452a9d87bc6SDouglas Gregor 
getTypeLoc() const453a9d87bc6SDouglas Gregor TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
45454272e5bSStephen Kelly   if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
45554272e5bSStephen Kelly       Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
45654272e5bSStephen Kelly     return TypeLoc();
457a9d87bc6SDouglas Gregor 
458a9d87bc6SDouglas Gregor   // The "void*" that points at the TypeLoc data.
459a9d87bc6SDouglas Gregor   unsigned Offset = getDataLength(Qualifier->getPrefix());
460a9d87bc6SDouglas Gregor   void *TypeData = LoadPointer(Data, Offset);
461a9d87bc6SDouglas Gregor   return TypeLoc(Qualifier->getAsType(), TypeData);
462a9d87bc6SDouglas Gregor }
4639b27251eSDouglas Gregor 
Append(char * Start,char * End,char * & Buffer,unsigned & BufferSize,unsigned & BufferCapacity)46421fadadbSEugene Zelenko static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
4659b27251eSDouglas Gregor                    unsigned &BufferCapacity) {
466b6708d8eSChandler Carruth   if (Start == End)
467b6708d8eSChandler Carruth     return;
468b6708d8eSChandler Carruth 
4699b27251eSDouglas Gregor   if (BufferSize + (End - Start) > BufferCapacity) {
4709b27251eSDouglas Gregor     // Reallocate the buffer.
471b6708d8eSChandler Carruth     unsigned NewCapacity = std::max(
472b6708d8eSChandler Carruth         (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
4739b27251eSDouglas Gregor         (unsigned)(BufferSize + (End - Start)));
474cc1c5165SBenjamin Kramer     if (!BufferCapacity) {
47552525730SSerge Pavlov       char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
476cc1c5165SBenjamin Kramer       if (Buffer)
4779b27251eSDouglas Gregor         memcpy(NewBuffer, Buffer, BufferSize);
4789b27251eSDouglas Gregor       Buffer = NewBuffer;
479cc1c5165SBenjamin Kramer     } else {
480cc1c5165SBenjamin Kramer       Buffer = static_cast<char *>(llvm::safe_realloc(Buffer, NewCapacity));
481cc1c5165SBenjamin Kramer     }
4829b27251eSDouglas Gregor     BufferCapacity = NewCapacity;
4839b27251eSDouglas Gregor   }
4847ec7a6e5SSimon Pilgrim   assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");
4859b27251eSDouglas Gregor   memcpy(Buffer + BufferSize, Start, End - Start);
4869b27251eSDouglas Gregor   BufferSize += End - Start;
4879b27251eSDouglas Gregor }
4889b27251eSDouglas Gregor 
4899fc8faf9SAdrian Prantl /// Save a source location to the given buffer.
SaveSourceLocation(SourceLocation Loc,char * & Buffer,unsigned & BufferSize,unsigned & BufferCapacity)49021fadadbSEugene Zelenko static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
4919b27251eSDouglas Gregor                                unsigned &BufferSize, unsigned &BufferCapacity) {
49221401a72SSimon Tatham   SourceLocation::UIntTy Raw = Loc.getRawEncoding();
4939b27251eSDouglas Gregor   Append(reinterpret_cast<char *>(&Raw),
49421401a72SSimon Tatham          reinterpret_cast<char *>(&Raw) + sizeof(Raw), Buffer, BufferSize,
49521401a72SSimon Tatham          BufferCapacity);
4969b27251eSDouglas Gregor }
4979b27251eSDouglas Gregor 
4989fc8faf9SAdrian Prantl /// Save a pointer to the given buffer.
SavePointer(void * Ptr,char * & Buffer,unsigned & BufferSize,unsigned & BufferCapacity)49921fadadbSEugene Zelenko static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
5009b27251eSDouglas Gregor                         unsigned &BufferCapacity) {
5019b27251eSDouglas Gregor   Append(reinterpret_cast<char *>(&Ptr),
5029b27251eSDouglas Gregor          reinterpret_cast<char *>(&Ptr) + sizeof(void *),
5039b27251eSDouglas Gregor          Buffer, BufferSize, BufferCapacity);
5049b27251eSDouglas Gregor }
5059b27251eSDouglas Gregor 
5069b27251eSDouglas Gregor NestedNameSpecifierLocBuilder::
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder & Other)5079b27251eSDouglas Gregor NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
50821fadadbSEugene Zelenko     : Representation(Other.Representation) {
5099b27251eSDouglas Gregor   if (!Other.Buffer)
5109b27251eSDouglas Gregor     return;
5119b27251eSDouglas Gregor 
5129b27251eSDouglas Gregor   if (Other.BufferCapacity == 0) {
5139b27251eSDouglas Gregor     // Shallow copy is okay.
5149b27251eSDouglas Gregor     Buffer = Other.Buffer;
5159b27251eSDouglas Gregor     BufferSize = Other.BufferSize;
5169b27251eSDouglas Gregor     return;
5179b27251eSDouglas Gregor   }
5189b27251eSDouglas Gregor 
5199b27251eSDouglas Gregor   // Deep copy
5209f81d6a4SSerge Pavlov   Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
5219f81d6a4SSerge Pavlov          BufferCapacity);
5229b27251eSDouglas Gregor }
5239b27251eSDouglas Gregor 
5249b27251eSDouglas Gregor NestedNameSpecifierLocBuilder &
5259b27251eSDouglas Gregor NestedNameSpecifierLocBuilder::
operator =(const NestedNameSpecifierLocBuilder & Other)5269b27251eSDouglas Gregor operator=(const NestedNameSpecifierLocBuilder &Other) {
5279b27251eSDouglas Gregor   Representation = Other.Representation;
5289b27251eSDouglas Gregor 
5299b27251eSDouglas Gregor   if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
5309b27251eSDouglas Gregor     // Re-use our storage.
5319b27251eSDouglas Gregor     BufferSize = Other.BufferSize;
5329b27251eSDouglas Gregor     memcpy(Buffer, Other.Buffer, BufferSize);
5339b27251eSDouglas Gregor     return *this;
5349b27251eSDouglas Gregor   }
5359b27251eSDouglas Gregor 
5369b27251eSDouglas Gregor   // Free our storage, if we have any.
5379b27251eSDouglas Gregor   if (BufferCapacity) {
5389b27251eSDouglas Gregor     free(Buffer);
5399b27251eSDouglas Gregor     BufferCapacity = 0;
5409b27251eSDouglas Gregor   }
5419b27251eSDouglas Gregor 
5429b27251eSDouglas Gregor   if (!Other.Buffer) {
5439b27251eSDouglas Gregor     // Empty.
54436250ad6SCraig Topper     Buffer = nullptr;
5459b27251eSDouglas Gregor     BufferSize = 0;
5469b27251eSDouglas Gregor     return *this;
5479b27251eSDouglas Gregor   }
5489b27251eSDouglas Gregor 
5499b27251eSDouglas Gregor   if (Other.BufferCapacity == 0) {
5509b27251eSDouglas Gregor     // Shallow copy is okay.
5519b27251eSDouglas Gregor     Buffer = Other.Buffer;
5529b27251eSDouglas Gregor     BufferSize = Other.BufferSize;
5539b27251eSDouglas Gregor     return *this;
5549b27251eSDouglas Gregor   }
5559b27251eSDouglas Gregor 
5569b27251eSDouglas Gregor   // Deep copy.
557c5871644SErik Pilkington   BufferSize = 0;
5589f81d6a4SSerge Pavlov   Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
5599f81d6a4SSerge Pavlov          BufferCapacity);
5609b27251eSDouglas Gregor   return *this;
5619b27251eSDouglas Gregor }
5629b27251eSDouglas Gregor 
Extend(ASTContext & Context,SourceLocation TemplateKWLoc,TypeLoc TL,SourceLocation ColonColonLoc)5639b27251eSDouglas Gregor void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
5649b27251eSDouglas Gregor                                            SourceLocation TemplateKWLoc,
5659b27251eSDouglas Gregor                                            TypeLoc TL,
5669b27251eSDouglas Gregor                                            SourceLocation ColonColonLoc) {
5679b27251eSDouglas Gregor   Representation = NestedNameSpecifier::Create(Context, Representation,
5689b27251eSDouglas Gregor                                                TemplateKWLoc.isValid(),
5699b27251eSDouglas Gregor                                                TL.getTypePtr());
5709b27251eSDouglas Gregor 
5719b27251eSDouglas Gregor   // Push source-location info into the buffer.
5729b27251eSDouglas Gregor   SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
5739b27251eSDouglas Gregor   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
5749b27251eSDouglas Gregor }
5759b27251eSDouglas Gregor 
Extend(ASTContext & Context,IdentifierInfo * Identifier,SourceLocation IdentifierLoc,SourceLocation ColonColonLoc)5769b27251eSDouglas Gregor void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
5779b27251eSDouglas Gregor                                            IdentifierInfo *Identifier,
5789b27251eSDouglas Gregor                                            SourceLocation IdentifierLoc,
5799b27251eSDouglas Gregor                                            SourceLocation ColonColonLoc) {
5809b27251eSDouglas Gregor   Representation = NestedNameSpecifier::Create(Context, Representation,
5819b27251eSDouglas Gregor                                                Identifier);
5829b27251eSDouglas Gregor 
5839b27251eSDouglas Gregor   // Push source-location info into the buffer.
5849b27251eSDouglas Gregor   SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
5859b27251eSDouglas Gregor   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
5869b27251eSDouglas Gregor }
5879b27251eSDouglas Gregor 
Extend(ASTContext & Context,NamespaceDecl * Namespace,SourceLocation NamespaceLoc,SourceLocation ColonColonLoc)5889b27251eSDouglas Gregor void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
5899b27251eSDouglas Gregor                                            NamespaceDecl *Namespace,
5909b27251eSDouglas Gregor                                            SourceLocation NamespaceLoc,
5919b27251eSDouglas Gregor                                            SourceLocation ColonColonLoc) {
5929b27251eSDouglas Gregor   Representation = NestedNameSpecifier::Create(Context, Representation,
5939b27251eSDouglas Gregor                                                Namespace);
5949b27251eSDouglas Gregor 
5959b27251eSDouglas Gregor   // Push source-location info into the buffer.
5969b27251eSDouglas Gregor   SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
5979b27251eSDouglas Gregor   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
5989b27251eSDouglas Gregor }
5999b27251eSDouglas Gregor 
Extend(ASTContext & Context,NamespaceAliasDecl * Alias,SourceLocation AliasLoc,SourceLocation ColonColonLoc)6009b27251eSDouglas Gregor void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
6019b27251eSDouglas Gregor                                            NamespaceAliasDecl *Alias,
6029b27251eSDouglas Gregor                                            SourceLocation AliasLoc,
6039b27251eSDouglas Gregor                                            SourceLocation ColonColonLoc) {
6049b27251eSDouglas Gregor   Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
6059b27251eSDouglas Gregor 
6069b27251eSDouglas Gregor   // Push source-location info into the buffer.
6079b27251eSDouglas Gregor   SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
6089b27251eSDouglas Gregor   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
6099b27251eSDouglas Gregor }
6109b27251eSDouglas Gregor 
MakeGlobal(ASTContext & Context,SourceLocation ColonColonLoc)6119b27251eSDouglas Gregor void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
6129b27251eSDouglas Gregor                                                SourceLocation ColonColonLoc) {
6139b27251eSDouglas Gregor   assert(!Representation && "Already have a nested-name-specifier!?");
6149b27251eSDouglas Gregor   Representation = NestedNameSpecifier::GlobalSpecifier(Context);
6159b27251eSDouglas Gregor 
6169b27251eSDouglas Gregor   // Push source-location info into the buffer.
6179b27251eSDouglas Gregor   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
6189b27251eSDouglas Gregor }
6199b27251eSDouglas Gregor 
MakeSuper(ASTContext & Context,CXXRecordDecl * RD,SourceLocation SuperLoc,SourceLocation ColonColonLoc)62067860249SNikola Smiljanic void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
62167860249SNikola Smiljanic                                               CXXRecordDecl *RD,
62267860249SNikola Smiljanic                                               SourceLocation SuperLoc,
62367860249SNikola Smiljanic                                               SourceLocation ColonColonLoc) {
62467860249SNikola Smiljanic   Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
62567860249SNikola Smiljanic 
62667860249SNikola Smiljanic   // Push source-location info into the buffer.
62767860249SNikola Smiljanic   SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
62867860249SNikola Smiljanic   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
62967860249SNikola Smiljanic }
63067860249SNikola Smiljanic 
MakeTrivial(ASTContext & Context,NestedNameSpecifier * Qualifier,SourceRange R)6319b27251eSDouglas Gregor void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
6329b27251eSDouglas Gregor                                                 NestedNameSpecifier *Qualifier,
6339b27251eSDouglas Gregor                                                 SourceRange R) {
6349b27251eSDouglas Gregor   Representation = Qualifier;
6359b27251eSDouglas Gregor 
6369b27251eSDouglas Gregor   // Construct bogus (but well-formed) source information for the
6379b27251eSDouglas Gregor   // nested-name-specifier.
6389b27251eSDouglas Gregor   BufferSize = 0;
6390e62c1ccSChris Lattner   SmallVector<NestedNameSpecifier *, 4> Stack;
6409b27251eSDouglas Gregor   for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
6419b27251eSDouglas Gregor     Stack.push_back(NNS);
6429b27251eSDouglas Gregor   while (!Stack.empty()) {
64325284cc9SRobert Wilhelm     NestedNameSpecifier *NNS = Stack.pop_back_val();
6449b27251eSDouglas Gregor     switch (NNS->getKind()) {
6459b27251eSDouglas Gregor       case NestedNameSpecifier::Identifier:
6469b27251eSDouglas Gregor       case NestedNameSpecifier::Namespace:
6479b27251eSDouglas Gregor       case NestedNameSpecifier::NamespaceAlias:
6489b27251eSDouglas Gregor         SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
6499b27251eSDouglas Gregor         break;
6509b27251eSDouglas Gregor 
6519b27251eSDouglas Gregor       case NestedNameSpecifier::TypeSpec:
6529b27251eSDouglas Gregor       case NestedNameSpecifier::TypeSpecWithTemplate: {
6539b27251eSDouglas Gregor         TypeSourceInfo *TSInfo
6549b27251eSDouglas Gregor         = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
6559b27251eSDouglas Gregor                                            R.getBegin());
6569b27251eSDouglas Gregor         SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
6579b27251eSDouglas Gregor                     BufferCapacity);
6589b27251eSDouglas Gregor         break;
6599b27251eSDouglas Gregor       }
6609b27251eSDouglas Gregor 
6619b27251eSDouglas Gregor       case NestedNameSpecifier::Global:
66267860249SNikola Smiljanic       case NestedNameSpecifier::Super:
6639b27251eSDouglas Gregor         break;
6649b27251eSDouglas Gregor     }
6659b27251eSDouglas Gregor 
6669b27251eSDouglas Gregor     // Save the location of the '::'.
6679b27251eSDouglas Gregor     SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
6689b27251eSDouglas Gregor                        Buffer, BufferSize, BufferCapacity);
6699b27251eSDouglas Gregor   }
6709b27251eSDouglas Gregor }
6719b27251eSDouglas Gregor 
Adopt(NestedNameSpecifierLoc Other)6729b27251eSDouglas Gregor void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
6739b27251eSDouglas Gregor   if (BufferCapacity)
6749b27251eSDouglas Gregor     free(Buffer);
6759b27251eSDouglas Gregor 
6769b27251eSDouglas Gregor   if (!Other) {
67736250ad6SCraig Topper     Representation = nullptr;
6789b27251eSDouglas Gregor     BufferSize = 0;
6799b27251eSDouglas Gregor     return;
6809b27251eSDouglas Gregor   }
6819b27251eSDouglas Gregor 
6829b27251eSDouglas Gregor   // Rather than copying the data (which is wasteful), "adopt" the
6839b27251eSDouglas Gregor   // pointer (which points into the ASTContext) but set the capacity to zero to
6849b27251eSDouglas Gregor   // indicate that we don't own it.
6859b27251eSDouglas Gregor   Representation = Other.getNestedNameSpecifier();
6869b27251eSDouglas Gregor   Buffer = static_cast<char *>(Other.getOpaqueData());
6879b27251eSDouglas Gregor   BufferSize = Other.getDataLength();
6889b27251eSDouglas Gregor   BufferCapacity = 0;
6899b27251eSDouglas Gregor }
6909b27251eSDouglas Gregor 
6919b27251eSDouglas Gregor NestedNameSpecifierLoc
getWithLocInContext(ASTContext & Context) const6929b27251eSDouglas Gregor NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
6939b27251eSDouglas Gregor   if (!Representation)
6949b27251eSDouglas Gregor     return NestedNameSpecifierLoc();
6959b27251eSDouglas Gregor 
6969b27251eSDouglas Gregor   // If we adopted our data pointer from elsewhere in the AST context, there's
6979b27251eSDouglas Gregor   // no need to copy the memory.
6989b27251eSDouglas Gregor   if (BufferCapacity == 0)
6999b27251eSDouglas Gregor     return NestedNameSpecifierLoc(Representation, Buffer);
7009b27251eSDouglas Gregor 
7019b27251eSDouglas Gregor   // FIXME: After copying the source-location information, should we free
7029b27251eSDouglas Gregor   // our (temporary) buffer and adopt the ASTContext-allocated memory?
7039b27251eSDouglas Gregor   // Doing so would optimize repeated calls to getWithLocInContext().
704c3f89253SBenjamin Kramer   void *Mem = Context.Allocate(BufferSize, alignof(void *));
7059b27251eSDouglas Gregor   memcpy(Mem, Buffer, BufferSize);
7069b27251eSDouglas Gregor   return NestedNameSpecifierLoc(Representation, Mem);
7079b27251eSDouglas Gregor }
708