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
25using namespace clang;
26
27NestedNameSpecifier *
28NestedNameSpecifier::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
45NestedNameSpecifier *
46NestedNameSpecifier::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
58NestedNameSpecifier *
59NestedNameSpecifier::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
74NestedNameSpecifier *
75NestedNameSpecifier::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
90NestedNameSpecifier *
91NestedNameSpecifier::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
102NestedNameSpecifier *
103NestedNameSpecifier::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
112NestedNameSpecifier *
113NestedNameSpecifier::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
121NestedNameSpecifier *
122NestedNameSpecifier::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
131NestedNameSpecifier::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.
157NamespaceDecl *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.
165NamespaceAliasDecl *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.
173CXXRecordDecl *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.
182bool 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.
212bool 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
232bool 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.
253void
254NestedNameSpecifier::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
321void NestedNameSpecifier::dump(const LangOptions &LO) const {
322  print(llvm::errs(), PrintingPolicy(LO));
323}
324
325void NestedNameSpecifier::dump() const {
326  LangOptions LO;
327  print(llvm::errs(), PrintingPolicy(LO));
328}
329
330unsigned
331NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
332  assert(Qualifier && "Expected a non-NULL qualifier");
333
334  // Location of the trailing '::'.
335  unsigned Length = sizeof(unsigned);
336
337  switch (Qualifier->getKind()) {
338  case NestedNameSpecifier::Global:
339    // Nothing more to add.
340    break;
341
342  case NestedNameSpecifier::Identifier:
343  case NestedNameSpecifier::Namespace:
344  case NestedNameSpecifier::NamespaceAlias:
345  case NestedNameSpecifier::Super:
346    // The location of the identifier or namespace name.
347    Length += sizeof(unsigned);
348    break;
349
350  case NestedNameSpecifier::TypeSpecWithTemplate:
351  case NestedNameSpecifier::TypeSpec:
352    // The "void*" that points at the TypeLoc data.
353    // Note: the 'template' keyword is part of the TypeLoc.
354    Length += sizeof(void *);
355    break;
356  }
357
358  return Length;
359}
360
361unsigned
362NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
363  unsigned Length = 0;
364  for (; Qualifier; Qualifier = Qualifier->getPrefix())
365    Length += getLocalDataLength(Qualifier);
366  return Length;
367}
368
369namespace {
370  /// \brief Load a (possibly unaligned) source location from a given address
371  /// and offset.
372  SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
373    unsigned Raw;
374    memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
375    return SourceLocation::getFromRawEncoding(Raw);
376  }
377
378  /// \brief Load a (possibly unaligned) pointer from a given address and
379  /// offset.
380  void *LoadPointer(void *Data, unsigned Offset) {
381    void *Result;
382    memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
383    return Result;
384  }
385}
386
387SourceRange NestedNameSpecifierLoc::getSourceRange() const {
388  if (!Qualifier)
389    return SourceRange();
390
391  NestedNameSpecifierLoc First = *this;
392  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
393    First = Prefix;
394
395  return SourceRange(First.getLocalSourceRange().getBegin(),
396                     getLocalSourceRange().getEnd());
397}
398
399SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
400  if (!Qualifier)
401    return SourceRange();
402
403  unsigned Offset = getDataLength(Qualifier->getPrefix());
404  switch (Qualifier->getKind()) {
405  case NestedNameSpecifier::Global:
406    return LoadSourceLocation(Data, Offset);
407
408  case NestedNameSpecifier::Identifier:
409  case NestedNameSpecifier::Namespace:
410  case NestedNameSpecifier::NamespaceAlias:
411  case NestedNameSpecifier::Super:
412    return SourceRange(LoadSourceLocation(Data, Offset),
413                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
414
415  case NestedNameSpecifier::TypeSpecWithTemplate:
416  case NestedNameSpecifier::TypeSpec: {
417    // The "void*" that points at the TypeLoc data.
418    // Note: the 'template' keyword is part of the TypeLoc.
419    void *TypeData = LoadPointer(Data, Offset);
420    TypeLoc TL(Qualifier->getAsType(), TypeData);
421    return SourceRange(TL.getBeginLoc(),
422                       LoadSourceLocation(Data, Offset + sizeof(void*)));
423  }
424  }
425
426  llvm_unreachable("Invalid NNS Kind!");
427}
428
429TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
430  assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec ||
431          Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) &&
432         "Nested-name-specifier location is not a type");
433
434  // The "void*" that points at the TypeLoc data.
435  unsigned Offset = getDataLength(Qualifier->getPrefix());
436  void *TypeData = LoadPointer(Data, Offset);
437  return TypeLoc(Qualifier->getAsType(), TypeData);
438}
439
440namespace {
441  void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
442              unsigned &BufferCapacity) {
443    if (Start == End)
444      return;
445
446    if (BufferSize + (End - Start) > BufferCapacity) {
447      // Reallocate the buffer.
448      unsigned NewCapacity = std::max(
449          (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
450          (unsigned)(BufferSize + (End - Start)));
451      char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
452      if (BufferCapacity) {
453        memcpy(NewBuffer, Buffer, BufferSize);
454        free(Buffer);
455      }
456      Buffer = NewBuffer;
457      BufferCapacity = NewCapacity;
458    }
459
460    memcpy(Buffer + BufferSize, Start, End - Start);
461    BufferSize += End-Start;
462  }
463
464  /// \brief Save a source location to the given buffer.
465  void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
466                          unsigned &BufferSize, unsigned &BufferCapacity) {
467    unsigned Raw = Loc.getRawEncoding();
468    Append(reinterpret_cast<char *>(&Raw),
469           reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
470           Buffer, BufferSize, BufferCapacity);
471  }
472
473  /// \brief Save a pointer to the given buffer.
474  void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
475                   unsigned &BufferCapacity) {
476    Append(reinterpret_cast<char *>(&Ptr),
477           reinterpret_cast<char *>(&Ptr) + sizeof(void *),
478           Buffer, BufferSize, BufferCapacity);
479  }
480}
481
482NestedNameSpecifierLocBuilder::
483NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
484  : Representation(Other.Representation), Buffer(nullptr),
485    BufferSize(0), BufferCapacity(0)
486{
487  if (!Other.Buffer)
488    return;
489
490  if (Other.BufferCapacity == 0) {
491    // Shallow copy is okay.
492    Buffer = Other.Buffer;
493    BufferSize = Other.BufferSize;
494    return;
495  }
496
497  // Deep copy
498  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
499         BufferCapacity);
500}
501
502NestedNameSpecifierLocBuilder &
503NestedNameSpecifierLocBuilder::
504operator=(const NestedNameSpecifierLocBuilder &Other) {
505  Representation = Other.Representation;
506
507  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
508    // Re-use our storage.
509    BufferSize = Other.BufferSize;
510    memcpy(Buffer, Other.Buffer, BufferSize);
511    return *this;
512  }
513
514  // Free our storage, if we have any.
515  if (BufferCapacity) {
516    free(Buffer);
517    BufferCapacity = 0;
518  }
519
520  if (!Other.Buffer) {
521    // Empty.
522    Buffer = nullptr;
523    BufferSize = 0;
524    return *this;
525  }
526
527  if (Other.BufferCapacity == 0) {
528    // Shallow copy is okay.
529    Buffer = Other.Buffer;
530    BufferSize = Other.BufferSize;
531    return *this;
532  }
533
534  // Deep copy.
535  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
536         BufferCapacity);
537  return *this;
538}
539
540void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
541                                           SourceLocation TemplateKWLoc,
542                                           TypeLoc TL,
543                                           SourceLocation ColonColonLoc) {
544  Representation = NestedNameSpecifier::Create(Context, Representation,
545                                               TemplateKWLoc.isValid(),
546                                               TL.getTypePtr());
547
548  // Push source-location info into the buffer.
549  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
550  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
551}
552
553void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
554                                           IdentifierInfo *Identifier,
555                                           SourceLocation IdentifierLoc,
556                                           SourceLocation ColonColonLoc) {
557  Representation = NestedNameSpecifier::Create(Context, Representation,
558                                               Identifier);
559
560  // Push source-location info into the buffer.
561  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
562  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
563}
564
565void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
566                                           NamespaceDecl *Namespace,
567                                           SourceLocation NamespaceLoc,
568                                           SourceLocation ColonColonLoc) {
569  Representation = NestedNameSpecifier::Create(Context, Representation,
570                                               Namespace);
571
572  // Push source-location info into the buffer.
573  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
574  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
575}
576
577void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
578                                           NamespaceAliasDecl *Alias,
579                                           SourceLocation AliasLoc,
580                                           SourceLocation ColonColonLoc) {
581  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
582
583  // Push source-location info into the buffer.
584  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
585  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
586}
587
588void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
589                                               SourceLocation ColonColonLoc) {
590  assert(!Representation && "Already have a nested-name-specifier!?");
591  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
592
593  // Push source-location info into the buffer.
594  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
595}
596
597void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
598                                              CXXRecordDecl *RD,
599                                              SourceLocation SuperLoc,
600                                              SourceLocation ColonColonLoc) {
601  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
602
603  // Push source-location info into the buffer.
604  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
605  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
606}
607
608void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
609                                                NestedNameSpecifier *Qualifier,
610                                                SourceRange R) {
611  Representation = Qualifier;
612
613  // Construct bogus (but well-formed) source information for the
614  // nested-name-specifier.
615  BufferSize = 0;
616  SmallVector<NestedNameSpecifier *, 4> Stack;
617  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
618    Stack.push_back(NNS);
619  while (!Stack.empty()) {
620    NestedNameSpecifier *NNS = Stack.pop_back_val();
621    switch (NNS->getKind()) {
622      case NestedNameSpecifier::Identifier:
623      case NestedNameSpecifier::Namespace:
624      case NestedNameSpecifier::NamespaceAlias:
625        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
626        break;
627
628      case NestedNameSpecifier::TypeSpec:
629      case NestedNameSpecifier::TypeSpecWithTemplate: {
630        TypeSourceInfo *TSInfo
631        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
632                                           R.getBegin());
633        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
634                    BufferCapacity);
635        break;
636      }
637
638      case NestedNameSpecifier::Global:
639      case NestedNameSpecifier::Super:
640        break;
641    }
642
643    // Save the location of the '::'.
644    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
645                       Buffer, BufferSize, BufferCapacity);
646  }
647}
648
649void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
650  if (BufferCapacity)
651    free(Buffer);
652
653  if (!Other) {
654    Representation = nullptr;
655    BufferSize = 0;
656    return;
657  }
658
659  // Rather than copying the data (which is wasteful), "adopt" the
660  // pointer (which points into the ASTContext) but set the capacity to zero to
661  // indicate that we don't own it.
662  Representation = Other.getNestedNameSpecifier();
663  Buffer = static_cast<char *>(Other.getOpaqueData());
664  BufferSize = Other.getDataLength();
665  BufferCapacity = 0;
666}
667
668NestedNameSpecifierLoc
669NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
670  if (!Representation)
671    return NestedNameSpecifierLoc();
672
673  // If we adopted our data pointer from elsewhere in the AST context, there's
674  // no need to copy the memory.
675  if (BufferCapacity == 0)
676    return NestedNameSpecifierLoc(Representation, Buffer);
677
678  // FIXME: After copying the source-location information, should we free
679  // our (temporary) buffer and adopt the ASTContext-allocated memory?
680  // Doing so would optimize repeated calls to getWithLocInContext().
681  void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
682  memcpy(Mem, Buffer, BufferSize);
683  return NestedNameSpecifierLoc(Representation, Mem);
684}
685