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