xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file defines the NestedNameSpecifier class, which represents
100b57cec5SDimitry Andric //  a C++ nested-name-specifier.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/AST/NestedNameSpecifier.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
160b57cec5SDimitry Andric #include "clang/AST/Decl.h"
170b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
195ffd83dbSDimitry Andric #include "clang/AST/DependenceFlags.h"
200b57cec5SDimitry Andric #include "clang/AST/PrettyPrinter.h"
210b57cec5SDimitry Andric #include "clang/AST/TemplateName.h"
220b57cec5SDimitry Andric #include "clang/AST/Type.h"
230b57cec5SDimitry Andric #include "clang/AST/TypeLoc.h"
240b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
250b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
260b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
270b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h"
280b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
290b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
300b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
310b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
330b57cec5SDimitry Andric #include <algorithm>
340b57cec5SDimitry Andric #include <cassert>
350b57cec5SDimitry Andric #include <cstdlib>
360b57cec5SDimitry Andric #include <cstring>
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric using namespace clang;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric NestedNameSpecifier *
410b57cec5SDimitry Andric NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
420b57cec5SDimitry Andric                                   const NestedNameSpecifier &Mockup) {
430b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
440b57cec5SDimitry Andric   Mockup.Profile(ID);
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   void *InsertPos = nullptr;
470b57cec5SDimitry Andric   NestedNameSpecifier *NNS
480b57cec5SDimitry Andric     = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
490b57cec5SDimitry Andric   if (!NNS) {
500b57cec5SDimitry Andric     NNS =
510b57cec5SDimitry Andric         new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
520b57cec5SDimitry Andric     Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
530b57cec5SDimitry Andric   }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   return NNS;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
58*0fca6ea1SDimitry Andric NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
59*0fca6ea1SDimitry Andric                                                  NestedNameSpecifier *Prefix,
60*0fca6ea1SDimitry Andric                                                  const IdentifierInfo *II) {
610b57cec5SDimitry Andric   assert(II && "Identifier cannot be NULL");
620b57cec5SDimitry Andric   assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   NestedNameSpecifier Mockup;
650b57cec5SDimitry Andric   Mockup.Prefix.setPointer(Prefix);
660b57cec5SDimitry Andric   Mockup.Prefix.setInt(StoredIdentifier);
67*0fca6ea1SDimitry Andric   Mockup.Specifier = const_cast<IdentifierInfo *>(II);
680b57cec5SDimitry Andric   return FindOrInsert(Context, Mockup);
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric NestedNameSpecifier *
720b57cec5SDimitry Andric NestedNameSpecifier::Create(const ASTContext &Context,
730b57cec5SDimitry Andric                             NestedNameSpecifier *Prefix,
740b57cec5SDimitry Andric                             const NamespaceDecl *NS) {
750b57cec5SDimitry Andric   assert(NS && "Namespace cannot be NULL");
760b57cec5SDimitry Andric   assert((!Prefix ||
770b57cec5SDimitry Andric           (Prefix->getAsType() == nullptr &&
780b57cec5SDimitry Andric            Prefix->getAsIdentifier() == nullptr)) &&
790b57cec5SDimitry Andric          "Broken nested name specifier");
800b57cec5SDimitry Andric   NestedNameSpecifier Mockup;
810b57cec5SDimitry Andric   Mockup.Prefix.setPointer(Prefix);
820b57cec5SDimitry Andric   Mockup.Prefix.setInt(StoredDecl);
830b57cec5SDimitry Andric   Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
840b57cec5SDimitry Andric   return FindOrInsert(Context, Mockup);
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric NestedNameSpecifier *
880b57cec5SDimitry Andric NestedNameSpecifier::Create(const ASTContext &Context,
890b57cec5SDimitry Andric                             NestedNameSpecifier *Prefix,
90*0fca6ea1SDimitry Andric                             const NamespaceAliasDecl *Alias) {
910b57cec5SDimitry Andric   assert(Alias && "Namespace alias cannot be NULL");
920b57cec5SDimitry Andric   assert((!Prefix ||
930b57cec5SDimitry Andric           (Prefix->getAsType() == nullptr &&
940b57cec5SDimitry Andric            Prefix->getAsIdentifier() == nullptr)) &&
950b57cec5SDimitry Andric          "Broken nested name specifier");
960b57cec5SDimitry Andric   NestedNameSpecifier Mockup;
970b57cec5SDimitry Andric   Mockup.Prefix.setPointer(Prefix);
980b57cec5SDimitry Andric   Mockup.Prefix.setInt(StoredDecl);
99*0fca6ea1SDimitry Andric   Mockup.Specifier = const_cast<NamespaceAliasDecl *>(Alias);
1000b57cec5SDimitry Andric   return FindOrInsert(Context, Mockup);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric NestedNameSpecifier *
1040b57cec5SDimitry Andric NestedNameSpecifier::Create(const ASTContext &Context,
1050b57cec5SDimitry Andric                             NestedNameSpecifier *Prefix,
1060b57cec5SDimitry Andric                             bool Template, const Type *T) {
1070b57cec5SDimitry Andric   assert(T && "Type cannot be NULL");
1080b57cec5SDimitry Andric   NestedNameSpecifier Mockup;
1090b57cec5SDimitry Andric   Mockup.Prefix.setPointer(Prefix);
1100b57cec5SDimitry Andric   Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
1110b57cec5SDimitry Andric   Mockup.Specifier = const_cast<Type*>(T);
1120b57cec5SDimitry Andric   return FindOrInsert(Context, Mockup);
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
115*0fca6ea1SDimitry Andric NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
116*0fca6ea1SDimitry Andric                                                  const IdentifierInfo *II) {
1170b57cec5SDimitry Andric   assert(II && "Identifier cannot be NULL");
1180b57cec5SDimitry Andric   NestedNameSpecifier Mockup;
1190b57cec5SDimitry Andric   Mockup.Prefix.setPointer(nullptr);
1200b57cec5SDimitry Andric   Mockup.Prefix.setInt(StoredIdentifier);
121*0fca6ea1SDimitry Andric   Mockup.Specifier = const_cast<IdentifierInfo *>(II);
1220b57cec5SDimitry Andric   return FindOrInsert(Context, Mockup);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric NestedNameSpecifier *
1260b57cec5SDimitry Andric NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
1270b57cec5SDimitry Andric   if (!Context.GlobalNestedNameSpecifier)
1280b57cec5SDimitry Andric     Context.GlobalNestedNameSpecifier =
1290b57cec5SDimitry Andric         new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
1300b57cec5SDimitry Andric   return Context.GlobalNestedNameSpecifier;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric NestedNameSpecifier *
1340b57cec5SDimitry Andric NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
1350b57cec5SDimitry Andric                                     CXXRecordDecl *RD) {
1360b57cec5SDimitry Andric   NestedNameSpecifier Mockup;
1370b57cec5SDimitry Andric   Mockup.Prefix.setPointer(nullptr);
1380b57cec5SDimitry Andric   Mockup.Prefix.setInt(StoredDecl);
1390b57cec5SDimitry Andric   Mockup.Specifier = RD;
1400b57cec5SDimitry Andric   return FindOrInsert(Context, Mockup);
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
1440b57cec5SDimitry Andric   if (!Specifier)
1450b57cec5SDimitry Andric     return Global;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   switch (Prefix.getInt()) {
1480b57cec5SDimitry Andric   case StoredIdentifier:
1490b57cec5SDimitry Andric     return Identifier;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   case StoredDecl: {
1520b57cec5SDimitry Andric     NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
1530b57cec5SDimitry Andric     if (isa<CXXRecordDecl>(ND))
1540b57cec5SDimitry Andric       return Super;
1550b57cec5SDimitry Andric     return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   case StoredTypeSpec:
1590b57cec5SDimitry Andric     return TypeSpec;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   case StoredTypeSpecWithTemplate:
1620b57cec5SDimitry Andric     return TypeSpecWithTemplate;
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   llvm_unreachable("Invalid NNS Kind!");
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric /// Retrieve the namespace stored in this nested name specifier.
1690b57cec5SDimitry Andric NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
1700b57cec5SDimitry Andric   if (Prefix.getInt() == StoredDecl)
1710b57cec5SDimitry Andric     return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   return nullptr;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric /// Retrieve the namespace alias stored in this nested name specifier.
1770b57cec5SDimitry Andric NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
1780b57cec5SDimitry Andric   if (Prefix.getInt() == StoredDecl)
1790b57cec5SDimitry Andric     return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   return nullptr;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric /// Retrieve the record declaration stored in this nested name specifier.
1850b57cec5SDimitry Andric CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
1860b57cec5SDimitry Andric   switch (Prefix.getInt()) {
1870b57cec5SDimitry Andric   case StoredIdentifier:
1880b57cec5SDimitry Andric     return nullptr;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   case StoredDecl:
1910b57cec5SDimitry Andric     return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   case StoredTypeSpec:
1940b57cec5SDimitry Andric   case StoredTypeSpecWithTemplate:
1950b57cec5SDimitry Andric     return getAsType()->getAsCXXRecordDecl();
1960b57cec5SDimitry Andric   }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   llvm_unreachable("Invalid NNS Kind!");
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2015ffd83dbSDimitry Andric NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
2020b57cec5SDimitry Andric   switch (getKind()) {
2035ffd83dbSDimitry Andric   case Identifier: {
2040b57cec5SDimitry Andric     // Identifier specifiers always represent dependent types
2055ffd83dbSDimitry Andric     auto F = NestedNameSpecifierDependence::Dependent |
2065ffd83dbSDimitry Andric              NestedNameSpecifierDependence::Instantiation;
2075ffd83dbSDimitry Andric     // Prefix can contain unexpanded template parameters.
2085ffd83dbSDimitry Andric     if (getPrefix())
2095ffd83dbSDimitry Andric       return F | getPrefix()->getDependence();
2105ffd83dbSDimitry Andric     return F;
2115ffd83dbSDimitry Andric   }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   case Namespace:
2140b57cec5SDimitry Andric   case NamespaceAlias:
2150b57cec5SDimitry Andric   case Global:
2165ffd83dbSDimitry Andric     return NestedNameSpecifierDependence::None;
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   case Super: {
2190b57cec5SDimitry Andric     CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
2200b57cec5SDimitry Andric     for (const auto &Base : RD->bases())
2210b57cec5SDimitry Andric       if (Base.getType()->isDependentType())
2225ffd83dbSDimitry Andric         // FIXME: must also be instantiation-dependent.
2235ffd83dbSDimitry Andric         return NestedNameSpecifierDependence::Dependent;
2245ffd83dbSDimitry Andric     return NestedNameSpecifierDependence::None;
2250b57cec5SDimitry Andric   }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   case TypeSpec:
2280b57cec5SDimitry Andric   case TypeSpecWithTemplate:
2295ffd83dbSDimitry Andric     return toNestedNameSpecifierDependendence(getAsType()->getDependence());
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric   llvm_unreachable("Invalid NNS Kind!");
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric 
2345ffd83dbSDimitry Andric bool NestedNameSpecifier::isDependent() const {
2355ffd83dbSDimitry Andric   return getDependence() & NestedNameSpecifierDependence::Dependent;
2365ffd83dbSDimitry Andric }
2375ffd83dbSDimitry Andric 
2380b57cec5SDimitry Andric bool NestedNameSpecifier::isInstantiationDependent() const {
2395ffd83dbSDimitry Andric   return getDependence() & NestedNameSpecifierDependence::Instantiation;
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
2435ffd83dbSDimitry Andric   return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2465ffd83dbSDimitry Andric bool NestedNameSpecifier::containsErrors() const {
2475ffd83dbSDimitry Andric   return getDependence() & NestedNameSpecifierDependence::Error;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric /// Print this nested name specifier to the given output
2510b57cec5SDimitry Andric /// stream.
2520b57cec5SDimitry Andric void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
2530b57cec5SDimitry Andric                                 bool ResolveTemplateArguments) const {
2540b57cec5SDimitry Andric   if (getPrefix())
2550b57cec5SDimitry Andric     getPrefix()->print(OS, Policy);
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   switch (getKind()) {
2580b57cec5SDimitry Andric   case Identifier:
2590b57cec5SDimitry Andric     OS << getAsIdentifier()->getName();
2600b57cec5SDimitry Andric     break;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   case Namespace:
2630b57cec5SDimitry Andric     if (getAsNamespace()->isAnonymousNamespace())
2640b57cec5SDimitry Andric       return;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric     OS << getAsNamespace()->getName();
2670b57cec5SDimitry Andric     break;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   case NamespaceAlias:
2700b57cec5SDimitry Andric     OS << getAsNamespaceAlias()->getName();
2710b57cec5SDimitry Andric     break;
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   case Global:
2740b57cec5SDimitry Andric     break;
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   case Super:
2770b57cec5SDimitry Andric     OS << "__super";
2780b57cec5SDimitry Andric     break;
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   case TypeSpecWithTemplate:
2810b57cec5SDimitry Andric     OS << "template ";
2820b57cec5SDimitry Andric     // Fall through to print the type.
283bdd1243dSDimitry Andric     [[fallthrough]];
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   case TypeSpec: {
2860b57cec5SDimitry Andric     const auto *Record =
2870b57cec5SDimitry Andric             dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
2880b57cec5SDimitry Andric     if (ResolveTemplateArguments && Record) {
2890b57cec5SDimitry Andric         // Print the type trait with resolved template parameters.
290bdd1243dSDimitry Andric         Record->printName(OS, Policy);
291fe6060f1SDimitry Andric         printTemplateArgumentList(
292fe6060f1SDimitry Andric             OS, Record->getTemplateArgs().asArray(), Policy,
293fe6060f1SDimitry Andric             Record->getSpecializedTemplate()->getTemplateParameters());
2940b57cec5SDimitry Andric         break;
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric     const Type *T = getAsType();
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric     PrintingPolicy InnerPolicy(Policy);
2990b57cec5SDimitry Andric     InnerPolicy.SuppressScope = true;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric     // Nested-name-specifiers are intended to contain minimally-qualified
3020b57cec5SDimitry Andric     // types. An actual ElaboratedType will not occur, since we'll store
3030b57cec5SDimitry Andric     // just the type that is referred to in the nested-name-specifier (e.g.,
3040b57cec5SDimitry Andric     // a TypedefType, TagType, etc.). However, when we are dealing with
3050b57cec5SDimitry Andric     // dependent template-id types (e.g., Outer<T>::template Inner<U>),
3060b57cec5SDimitry Andric     // the type requires its own nested-name-specifier for uniqueness, so we
3070b57cec5SDimitry Andric     // suppress that nested-name-specifier during printing.
3080b57cec5SDimitry Andric     assert(!isa<ElaboratedType>(T) &&
3090b57cec5SDimitry Andric            "Elaborated type in nested-name-specifier");
3100b57cec5SDimitry Andric     if (const TemplateSpecializationType *SpecType
3110b57cec5SDimitry Andric           = dyn_cast<TemplateSpecializationType>(T)) {
3120b57cec5SDimitry Andric       // Print the template name without its corresponding
3130b57cec5SDimitry Andric       // nested-name-specifier.
314349cc55cSDimitry Andric       SpecType->getTemplateName().print(OS, InnerPolicy,
315349cc55cSDimitry Andric                                         TemplateName::Qualified::None);
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric       // Print the template argument list.
3180b57cec5SDimitry Andric       printTemplateArgumentList(OS, SpecType->template_arguments(),
3190b57cec5SDimitry Andric                                 InnerPolicy);
3205ffd83dbSDimitry Andric     } else if (const auto *DepSpecType =
3215ffd83dbSDimitry Andric                    dyn_cast<DependentTemplateSpecializationType>(T)) {
3225ffd83dbSDimitry Andric       // Print the template name without its corresponding
3235ffd83dbSDimitry Andric       // nested-name-specifier.
3245ffd83dbSDimitry Andric       OS << DepSpecType->getIdentifier()->getName();
3255ffd83dbSDimitry Andric       // Print the template argument list.
3265ffd83dbSDimitry Andric       printTemplateArgumentList(OS, DepSpecType->template_arguments(),
3275ffd83dbSDimitry Andric                                 InnerPolicy);
3280b57cec5SDimitry Andric     } else {
3290b57cec5SDimitry Andric       // Print the type normally
3300b57cec5SDimitry Andric       QualType(T, 0).print(OS, InnerPolicy);
3310b57cec5SDimitry Andric     }
3320b57cec5SDimitry Andric     break;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric   }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   OS << "::";
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
3400b57cec5SDimitry Andric   dump(llvm::errs(), LO);
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
3460b57cec5SDimitry Andric   LangOptions LO;
3470b57cec5SDimitry Andric   dump(OS, LO);
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
3510b57cec5SDimitry Andric                                                 const LangOptions &LO) const {
3520b57cec5SDimitry Andric   print(OS, PrintingPolicy(LO));
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric unsigned
3560b57cec5SDimitry Andric NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
3570b57cec5SDimitry Andric   assert(Qualifier && "Expected a non-NULL qualifier");
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   // Location of the trailing '::'.
360fe6060f1SDimitry Andric   unsigned Length = sizeof(SourceLocation::UIntTy);
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   switch (Qualifier->getKind()) {
3630b57cec5SDimitry Andric   case NestedNameSpecifier::Global:
3640b57cec5SDimitry Andric     // Nothing more to add.
3650b57cec5SDimitry Andric     break;
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   case NestedNameSpecifier::Identifier:
3680b57cec5SDimitry Andric   case NestedNameSpecifier::Namespace:
3690b57cec5SDimitry Andric   case NestedNameSpecifier::NamespaceAlias:
3700b57cec5SDimitry Andric   case NestedNameSpecifier::Super:
3710b57cec5SDimitry Andric     // The location of the identifier or namespace name.
372fe6060f1SDimitry Andric     Length += sizeof(SourceLocation::UIntTy);
3730b57cec5SDimitry Andric     break;
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   case NestedNameSpecifier::TypeSpecWithTemplate:
3760b57cec5SDimitry Andric   case NestedNameSpecifier::TypeSpec:
3770b57cec5SDimitry Andric     // The "void*" that points at the TypeLoc data.
3780b57cec5SDimitry Andric     // Note: the 'template' keyword is part of the TypeLoc.
3790b57cec5SDimitry Andric     Length += sizeof(void *);
3800b57cec5SDimitry Andric     break;
3810b57cec5SDimitry Andric   }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric   return Length;
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric unsigned
3870b57cec5SDimitry Andric NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
3880b57cec5SDimitry Andric   unsigned Length = 0;
3890b57cec5SDimitry Andric   for (; Qualifier; Qualifier = Qualifier->getPrefix())
3900b57cec5SDimitry Andric     Length += getLocalDataLength(Qualifier);
3910b57cec5SDimitry Andric   return Length;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric /// Load a (possibly unaligned) source location from a given address
3950b57cec5SDimitry Andric /// and offset.
3960b57cec5SDimitry Andric static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
397fe6060f1SDimitry Andric   SourceLocation::UIntTy Raw;
398fe6060f1SDimitry Andric   memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));
3990b57cec5SDimitry Andric   return SourceLocation::getFromRawEncoding(Raw);
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric /// Load a (possibly unaligned) pointer from a given address and
4030b57cec5SDimitry Andric /// offset.
4040b57cec5SDimitry Andric static void *LoadPointer(void *Data, unsigned Offset) {
4050b57cec5SDimitry Andric   void *Result;
4060b57cec5SDimitry Andric   memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
4070b57cec5SDimitry Andric   return Result;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric SourceRange NestedNameSpecifierLoc::getSourceRange() const {
4110b57cec5SDimitry Andric   if (!Qualifier)
4120b57cec5SDimitry Andric     return SourceRange();
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   NestedNameSpecifierLoc First = *this;
4150b57cec5SDimitry Andric   while (NestedNameSpecifierLoc Prefix = First.getPrefix())
4160b57cec5SDimitry Andric     First = Prefix;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   return SourceRange(First.getLocalSourceRange().getBegin(),
4190b57cec5SDimitry Andric                      getLocalSourceRange().getEnd());
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
4230b57cec5SDimitry Andric   if (!Qualifier)
4240b57cec5SDimitry Andric     return SourceRange();
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   unsigned Offset = getDataLength(Qualifier->getPrefix());
4270b57cec5SDimitry Andric   switch (Qualifier->getKind()) {
4280b57cec5SDimitry Andric   case NestedNameSpecifier::Global:
4290b57cec5SDimitry Andric     return LoadSourceLocation(Data, Offset);
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   case NestedNameSpecifier::Identifier:
4320b57cec5SDimitry Andric   case NestedNameSpecifier::Namespace:
4330b57cec5SDimitry Andric   case NestedNameSpecifier::NamespaceAlias:
4340b57cec5SDimitry Andric   case NestedNameSpecifier::Super:
435fe6060f1SDimitry Andric     return SourceRange(
436fe6060f1SDimitry Andric         LoadSourceLocation(Data, Offset),
437fe6060f1SDimitry Andric         LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy)));
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   case NestedNameSpecifier::TypeSpecWithTemplate:
4400b57cec5SDimitry Andric   case NestedNameSpecifier::TypeSpec: {
4410b57cec5SDimitry Andric     // The "void*" that points at the TypeLoc data.
4420b57cec5SDimitry Andric     // Note: the 'template' keyword is part of the TypeLoc.
4430b57cec5SDimitry Andric     void *TypeData = LoadPointer(Data, Offset);
4440b57cec5SDimitry Andric     TypeLoc TL(Qualifier->getAsType(), TypeData);
4450b57cec5SDimitry Andric     return SourceRange(TL.getBeginLoc(),
4460b57cec5SDimitry Andric                        LoadSourceLocation(Data, Offset + sizeof(void*)));
4470b57cec5SDimitry Andric   }
4480b57cec5SDimitry Andric   }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   llvm_unreachable("Invalid NNS Kind!");
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
4540b57cec5SDimitry Andric   if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
4550b57cec5SDimitry Andric       Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
4560b57cec5SDimitry Andric     return TypeLoc();
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   // The "void*" that points at the TypeLoc data.
4590b57cec5SDimitry Andric   unsigned Offset = getDataLength(Qualifier->getPrefix());
4600b57cec5SDimitry Andric   void *TypeData = LoadPointer(Data, Offset);
4610b57cec5SDimitry Andric   return TypeLoc(Qualifier->getAsType(), TypeData);
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
4650b57cec5SDimitry Andric                    unsigned &BufferCapacity) {
4660b57cec5SDimitry Andric   if (Start == End)
4670b57cec5SDimitry Andric     return;
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   if (BufferSize + (End - Start) > BufferCapacity) {
4700b57cec5SDimitry Andric     // Reallocate the buffer.
4710b57cec5SDimitry Andric     unsigned NewCapacity = std::max(
4720b57cec5SDimitry Andric         (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
4730b57cec5SDimitry Andric         (unsigned)(BufferSize + (End - Start)));
4745ffd83dbSDimitry Andric     if (!BufferCapacity) {
4750b57cec5SDimitry Andric       char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
4765ffd83dbSDimitry Andric       if (Buffer)
4770b57cec5SDimitry Andric         memcpy(NewBuffer, Buffer, BufferSize);
4780b57cec5SDimitry Andric       Buffer = NewBuffer;
4795ffd83dbSDimitry Andric     } else {
4805ffd83dbSDimitry Andric       Buffer = static_cast<char *>(llvm::safe_realloc(Buffer, NewCapacity));
4815ffd83dbSDimitry Andric     }
4820b57cec5SDimitry Andric     BufferCapacity = NewCapacity;
4830b57cec5SDimitry Andric   }
484480093f4SDimitry Andric   assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");
4850b57cec5SDimitry Andric   memcpy(Buffer + BufferSize, Start, End - Start);
4860b57cec5SDimitry Andric   BufferSize += End - Start;
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric /// Save a source location to the given buffer.
4900b57cec5SDimitry Andric static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
4910b57cec5SDimitry Andric                                unsigned &BufferSize, unsigned &BufferCapacity) {
492fe6060f1SDimitry Andric   SourceLocation::UIntTy Raw = Loc.getRawEncoding();
4930b57cec5SDimitry Andric   Append(reinterpret_cast<char *>(&Raw),
494fe6060f1SDimitry Andric          reinterpret_cast<char *>(&Raw) + sizeof(Raw), Buffer, BufferSize,
495fe6060f1SDimitry Andric          BufferCapacity);
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric /// Save a pointer to the given buffer.
4990b57cec5SDimitry Andric static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
5000b57cec5SDimitry Andric                         unsigned &BufferCapacity) {
5010b57cec5SDimitry Andric   Append(reinterpret_cast<char *>(&Ptr),
5020b57cec5SDimitry Andric          reinterpret_cast<char *>(&Ptr) + sizeof(void *),
5030b57cec5SDimitry Andric          Buffer, BufferSize, BufferCapacity);
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric NestedNameSpecifierLocBuilder::
5070b57cec5SDimitry Andric NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
5080b57cec5SDimitry Andric     : Representation(Other.Representation) {
5090b57cec5SDimitry Andric   if (!Other.Buffer)
5100b57cec5SDimitry Andric     return;
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   if (Other.BufferCapacity == 0) {
5130b57cec5SDimitry Andric     // Shallow copy is okay.
5140b57cec5SDimitry Andric     Buffer = Other.Buffer;
5150b57cec5SDimitry Andric     BufferSize = Other.BufferSize;
5160b57cec5SDimitry Andric     return;
5170b57cec5SDimitry Andric   }
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   // Deep copy
5200b57cec5SDimitry Andric   Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
5210b57cec5SDimitry Andric          BufferCapacity);
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric NestedNameSpecifierLocBuilder &
5250b57cec5SDimitry Andric NestedNameSpecifierLocBuilder::
5260b57cec5SDimitry Andric operator=(const NestedNameSpecifierLocBuilder &Other) {
5270b57cec5SDimitry Andric   Representation = Other.Representation;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric   if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
5300b57cec5SDimitry Andric     // Re-use our storage.
5310b57cec5SDimitry Andric     BufferSize = Other.BufferSize;
5320b57cec5SDimitry Andric     memcpy(Buffer, Other.Buffer, BufferSize);
5330b57cec5SDimitry Andric     return *this;
5340b57cec5SDimitry Andric   }
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   // Free our storage, if we have any.
5370b57cec5SDimitry Andric   if (BufferCapacity) {
5380b57cec5SDimitry Andric     free(Buffer);
5390b57cec5SDimitry Andric     BufferCapacity = 0;
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   if (!Other.Buffer) {
5430b57cec5SDimitry Andric     // Empty.
5440b57cec5SDimitry Andric     Buffer = nullptr;
5450b57cec5SDimitry Andric     BufferSize = 0;
5460b57cec5SDimitry Andric     return *this;
5470b57cec5SDimitry Andric   }
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   if (Other.BufferCapacity == 0) {
5500b57cec5SDimitry Andric     // Shallow copy is okay.
5510b57cec5SDimitry Andric     Buffer = Other.Buffer;
5520b57cec5SDimitry Andric     BufferSize = Other.BufferSize;
5530b57cec5SDimitry Andric     return *this;
5540b57cec5SDimitry Andric   }
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   // Deep copy.
5570b57cec5SDimitry Andric   BufferSize = 0;
5580b57cec5SDimitry Andric   Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
5590b57cec5SDimitry Andric          BufferCapacity);
5600b57cec5SDimitry Andric   return *this;
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
5640b57cec5SDimitry Andric                                            SourceLocation TemplateKWLoc,
5650b57cec5SDimitry Andric                                            TypeLoc TL,
5660b57cec5SDimitry Andric                                            SourceLocation ColonColonLoc) {
5670b57cec5SDimitry Andric   Representation = NestedNameSpecifier::Create(Context, Representation,
5680b57cec5SDimitry Andric                                                TemplateKWLoc.isValid(),
5690b57cec5SDimitry Andric                                                TL.getTypePtr());
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   // Push source-location info into the buffer.
5720b57cec5SDimitry Andric   SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
5730b57cec5SDimitry Andric   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
5770b57cec5SDimitry Andric                                            IdentifierInfo *Identifier,
5780b57cec5SDimitry Andric                                            SourceLocation IdentifierLoc,
5790b57cec5SDimitry Andric                                            SourceLocation ColonColonLoc) {
5800b57cec5SDimitry Andric   Representation = NestedNameSpecifier::Create(Context, Representation,
5810b57cec5SDimitry Andric                                                Identifier);
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric   // Push source-location info into the buffer.
5840b57cec5SDimitry Andric   SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
5850b57cec5SDimitry Andric   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
5890b57cec5SDimitry Andric                                            NamespaceDecl *Namespace,
5900b57cec5SDimitry Andric                                            SourceLocation NamespaceLoc,
5910b57cec5SDimitry Andric                                            SourceLocation ColonColonLoc) {
5920b57cec5SDimitry Andric   Representation = NestedNameSpecifier::Create(Context, Representation,
5930b57cec5SDimitry Andric                                                Namespace);
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   // Push source-location info into the buffer.
5960b57cec5SDimitry Andric   SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
5970b57cec5SDimitry Andric   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
6010b57cec5SDimitry Andric                                            NamespaceAliasDecl *Alias,
6020b57cec5SDimitry Andric                                            SourceLocation AliasLoc,
6030b57cec5SDimitry Andric                                            SourceLocation ColonColonLoc) {
6040b57cec5SDimitry Andric   Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   // Push source-location info into the buffer.
6070b57cec5SDimitry Andric   SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
6080b57cec5SDimitry Andric   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
6120b57cec5SDimitry Andric                                                SourceLocation ColonColonLoc) {
6130b57cec5SDimitry Andric   assert(!Representation && "Already have a nested-name-specifier!?");
6140b57cec5SDimitry Andric   Representation = NestedNameSpecifier::GlobalSpecifier(Context);
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   // Push source-location info into the buffer.
6170b57cec5SDimitry Andric   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
6210b57cec5SDimitry Andric                                               CXXRecordDecl *RD,
6220b57cec5SDimitry Andric                                               SourceLocation SuperLoc,
6230b57cec5SDimitry Andric                                               SourceLocation ColonColonLoc) {
6240b57cec5SDimitry Andric   Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   // Push source-location info into the buffer.
6270b57cec5SDimitry Andric   SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
6280b57cec5SDimitry Andric   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
6290b57cec5SDimitry Andric }
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
6320b57cec5SDimitry Andric                                                 NestedNameSpecifier *Qualifier,
6330b57cec5SDimitry Andric                                                 SourceRange R) {
6340b57cec5SDimitry Andric   Representation = Qualifier;
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   // Construct bogus (but well-formed) source information for the
6370b57cec5SDimitry Andric   // nested-name-specifier.
6380b57cec5SDimitry Andric   BufferSize = 0;
6390b57cec5SDimitry Andric   SmallVector<NestedNameSpecifier *, 4> Stack;
6400b57cec5SDimitry Andric   for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
6410b57cec5SDimitry Andric     Stack.push_back(NNS);
6420b57cec5SDimitry Andric   while (!Stack.empty()) {
6430b57cec5SDimitry Andric     NestedNameSpecifier *NNS = Stack.pop_back_val();
6440b57cec5SDimitry Andric     switch (NNS->getKind()) {
6450b57cec5SDimitry Andric       case NestedNameSpecifier::Identifier:
6460b57cec5SDimitry Andric       case NestedNameSpecifier::Namespace:
6470b57cec5SDimitry Andric       case NestedNameSpecifier::NamespaceAlias:
6480b57cec5SDimitry Andric         SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
6490b57cec5SDimitry Andric         break;
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric       case NestedNameSpecifier::TypeSpec:
6520b57cec5SDimitry Andric       case NestedNameSpecifier::TypeSpecWithTemplate: {
6530b57cec5SDimitry Andric         TypeSourceInfo *TSInfo
6540b57cec5SDimitry Andric         = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
6550b57cec5SDimitry Andric                                            R.getBegin());
6560b57cec5SDimitry Andric         SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
6570b57cec5SDimitry Andric                     BufferCapacity);
6580b57cec5SDimitry Andric         break;
6590b57cec5SDimitry Andric       }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric       case NestedNameSpecifier::Global:
6620b57cec5SDimitry Andric       case NestedNameSpecifier::Super:
6630b57cec5SDimitry Andric         break;
6640b57cec5SDimitry Andric     }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric     // Save the location of the '::'.
6670b57cec5SDimitry Andric     SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
6680b57cec5SDimitry Andric                        Buffer, BufferSize, BufferCapacity);
6690b57cec5SDimitry Andric   }
6700b57cec5SDimitry Andric }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
6730b57cec5SDimitry Andric   if (BufferCapacity)
6740b57cec5SDimitry Andric     free(Buffer);
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   if (!Other) {
6770b57cec5SDimitry Andric     Representation = nullptr;
6780b57cec5SDimitry Andric     BufferSize = 0;
6790b57cec5SDimitry Andric     return;
6800b57cec5SDimitry Andric   }
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   // Rather than copying the data (which is wasteful), "adopt" the
6830b57cec5SDimitry Andric   // pointer (which points into the ASTContext) but set the capacity to zero to
6840b57cec5SDimitry Andric   // indicate that we don't own it.
6850b57cec5SDimitry Andric   Representation = Other.getNestedNameSpecifier();
6860b57cec5SDimitry Andric   Buffer = static_cast<char *>(Other.getOpaqueData());
6870b57cec5SDimitry Andric   BufferSize = Other.getDataLength();
6880b57cec5SDimitry Andric   BufferCapacity = 0;
6890b57cec5SDimitry Andric }
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric NestedNameSpecifierLoc
6920b57cec5SDimitry Andric NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
6930b57cec5SDimitry Andric   if (!Representation)
6940b57cec5SDimitry Andric     return NestedNameSpecifierLoc();
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   // If we adopted our data pointer from elsewhere in the AST context, there's
6970b57cec5SDimitry Andric   // no need to copy the memory.
6980b57cec5SDimitry Andric   if (BufferCapacity == 0)
6990b57cec5SDimitry Andric     return NestedNameSpecifierLoc(Representation, Buffer);
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric   // FIXME: After copying the source-location information, should we free
7020b57cec5SDimitry Andric   // our (temporary) buffer and adopt the ASTContext-allocated memory?
7030b57cec5SDimitry Andric   // Doing so would optimize repeated calls to getWithLocInContext().
7040b57cec5SDimitry Andric   void *Mem = Context.Allocate(BufferSize, alignof(void *));
7050b57cec5SDimitry Andric   memcpy(Mem, Buffer, BufferSize);
7060b57cec5SDimitry Andric   return NestedNameSpecifierLoc(Representation, Mem);
7070b57cec5SDimitry Andric }
708