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) {
322  print(llvm::errs(), PrintingPolicy(LO));
323}
324
325unsigned
326NestedNameSpecifierLoc::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
356unsigned
357NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
358  unsigned Length = 0;
359  for (; Qualifier; Qualifier = Qualifier->getPrefix())
360    Length += getLocalDataLength(Qualifier);
361  return Length;
362}
363
364namespace {
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
382SourceRange 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
394SourceRange 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
424TypeLoc 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
435namespace {
436  void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
437              unsigned &BufferCapacity) {
438    if (Start == End)
439      return;
440
441    if (BufferSize + (End - Start) > BufferCapacity) {
442      // Reallocate the buffer.
443      unsigned NewCapacity = std::max(
444          (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
445          (unsigned)(BufferSize + (End - Start)));
446      char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
447      if (BufferCapacity) {
448        memcpy(NewBuffer, Buffer, BufferSize);
449        free(Buffer);
450      }
451      Buffer = NewBuffer;
452      BufferCapacity = NewCapacity;
453    }
454
455    memcpy(Buffer + BufferSize, Start, End - Start);
456    BufferSize += End-Start;
457  }
458
459  /// \brief Save a source location to the given buffer.
460  void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
461                          unsigned &BufferSize, unsigned &BufferCapacity) {
462    unsigned Raw = Loc.getRawEncoding();
463    Append(reinterpret_cast<char *>(&Raw),
464           reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
465           Buffer, BufferSize, BufferCapacity);
466  }
467
468  /// \brief Save a pointer to the given buffer.
469  void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
470                   unsigned &BufferCapacity) {
471    Append(reinterpret_cast<char *>(&Ptr),
472           reinterpret_cast<char *>(&Ptr) + sizeof(void *),
473           Buffer, BufferSize, BufferCapacity);
474  }
475}
476
477NestedNameSpecifierLocBuilder::
478NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
479  : Representation(Other.Representation), Buffer(nullptr),
480    BufferSize(0), BufferCapacity(0)
481{
482  if (!Other.Buffer)
483    return;
484
485  if (Other.BufferCapacity == 0) {
486    // Shallow copy is okay.
487    Buffer = Other.Buffer;
488    BufferSize = Other.BufferSize;
489    return;
490  }
491
492  // Deep copy
493  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
494         BufferCapacity);
495}
496
497NestedNameSpecifierLocBuilder &
498NestedNameSpecifierLocBuilder::
499operator=(const NestedNameSpecifierLocBuilder &Other) {
500  Representation = Other.Representation;
501
502  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
503    // Re-use our storage.
504    BufferSize = Other.BufferSize;
505    memcpy(Buffer, Other.Buffer, BufferSize);
506    return *this;
507  }
508
509  // Free our storage, if we have any.
510  if (BufferCapacity) {
511    free(Buffer);
512    BufferCapacity = 0;
513  }
514
515  if (!Other.Buffer) {
516    // Empty.
517    Buffer = nullptr;
518    BufferSize = 0;
519    return *this;
520  }
521
522  if (Other.BufferCapacity == 0) {
523    // Shallow copy is okay.
524    Buffer = Other.Buffer;
525    BufferSize = Other.BufferSize;
526    return *this;
527  }
528
529  // Deep copy.
530  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
531         BufferCapacity);
532  return *this;
533}
534
535void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
536                                           SourceLocation TemplateKWLoc,
537                                           TypeLoc TL,
538                                           SourceLocation ColonColonLoc) {
539  Representation = NestedNameSpecifier::Create(Context, Representation,
540                                               TemplateKWLoc.isValid(),
541                                               TL.getTypePtr());
542
543  // Push source-location info into the buffer.
544  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
545  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
546}
547
548void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
549                                           IdentifierInfo *Identifier,
550                                           SourceLocation IdentifierLoc,
551                                           SourceLocation ColonColonLoc) {
552  Representation = NestedNameSpecifier::Create(Context, Representation,
553                                               Identifier);
554
555  // Push source-location info into the buffer.
556  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
557  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
558}
559
560void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
561                                           NamespaceDecl *Namespace,
562                                           SourceLocation NamespaceLoc,
563                                           SourceLocation ColonColonLoc) {
564  Representation = NestedNameSpecifier::Create(Context, Representation,
565                                               Namespace);
566
567  // Push source-location info into the buffer.
568  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
569  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
570}
571
572void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
573                                           NamespaceAliasDecl *Alias,
574                                           SourceLocation AliasLoc,
575                                           SourceLocation ColonColonLoc) {
576  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
577
578  // Push source-location info into the buffer.
579  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
580  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
581}
582
583void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
584                                               SourceLocation ColonColonLoc) {
585  assert(!Representation && "Already have a nested-name-specifier!?");
586  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
587
588  // Push source-location info into the buffer.
589  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
590}
591
592void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
593                                              CXXRecordDecl *RD,
594                                              SourceLocation SuperLoc,
595                                              SourceLocation ColonColonLoc) {
596  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
597
598  // Push source-location info into the buffer.
599  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
600  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
601}
602
603void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
604                                                NestedNameSpecifier *Qualifier,
605                                                SourceRange R) {
606  Representation = Qualifier;
607
608  // Construct bogus (but well-formed) source information for the
609  // nested-name-specifier.
610  BufferSize = 0;
611  SmallVector<NestedNameSpecifier *, 4> Stack;
612  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
613    Stack.push_back(NNS);
614  while (!Stack.empty()) {
615    NestedNameSpecifier *NNS = Stack.pop_back_val();
616    switch (NNS->getKind()) {
617      case NestedNameSpecifier::Identifier:
618      case NestedNameSpecifier::Namespace:
619      case NestedNameSpecifier::NamespaceAlias:
620        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
621        break;
622
623      case NestedNameSpecifier::TypeSpec:
624      case NestedNameSpecifier::TypeSpecWithTemplate: {
625        TypeSourceInfo *TSInfo
626        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
627                                           R.getBegin());
628        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
629                    BufferCapacity);
630        break;
631      }
632
633      case NestedNameSpecifier::Global:
634      case NestedNameSpecifier::Super:
635        break;
636    }
637
638    // Save the location of the '::'.
639    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
640                       Buffer, BufferSize, BufferCapacity);
641  }
642}
643
644void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
645  if (BufferCapacity)
646    free(Buffer);
647
648  if (!Other) {
649    Representation = nullptr;
650    BufferSize = 0;
651    return;
652  }
653
654  // Rather than copying the data (which is wasteful), "adopt" the
655  // pointer (which points into the ASTContext) but set the capacity to zero to
656  // indicate that we don't own it.
657  Representation = Other.getNestedNameSpecifier();
658  Buffer = static_cast<char *>(Other.getOpaqueData());
659  BufferSize = Other.getDataLength();
660  BufferCapacity = 0;
661}
662
663NestedNameSpecifierLoc
664NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
665  if (!Representation)
666    return NestedNameSpecifierLoc();
667
668  // If we adopted our data pointer from elsewhere in the AST context, there's
669  // no need to copy the memory.
670  if (BufferCapacity == 0)
671    return NestedNameSpecifierLoc(Representation, Buffer);
672
673  // FIXME: After copying the source-location information, should we free
674  // our (temporary) buffer and adopt the ASTContext-allocated memory?
675  // Doing so would optimize repeated calls to getWithLocInContext().
676  void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
677  memcpy(Mem, Buffer, BufferSize);
678  return NestedNameSpecifierLoc(Representation, Mem);
679}
680