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