NestedNameSpecifier.cpp revision 344779
1327952Sdim//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file defines the NestedNameSpecifier class, which represents
11193326Sed//  a C++ nested-name-specifier.
12193326Sed//
13193326Sed//===----------------------------------------------------------------------===//
14327952Sdim
15193326Sed#include "clang/AST/NestedNameSpecifier.h"
16193326Sed#include "clang/AST/ASTContext.h"
17193326Sed#include "clang/AST/Decl.h"
18219077Sdim#include "clang/AST/DeclCXX.h"
19344779Sdim#include "clang/AST/DeclTemplate.h"
20193326Sed#include "clang/AST/PrettyPrinter.h"
21327952Sdim#include "clang/AST/TemplateName.h"
22193326Sed#include "clang/AST/Type.h"
23219077Sdim#include "clang/AST/TypeLoc.h"
24327952Sdim#include "clang/Basic/LLVM.h"
25327952Sdim#include "clang/Basic/LangOptions.h"
26327952Sdim#include "clang/Basic/SourceLocation.h"
27327952Sdim#include "llvm/ADT/FoldingSet.h"
28327952Sdim#include "llvm/ADT/SmallVector.h"
29327952Sdim#include "llvm/Support/Casting.h"
30327952Sdim#include "llvm/Support/Compiler.h"
31327952Sdim#include "llvm/Support/ErrorHandling.h"
32193326Sed#include "llvm/Support/raw_ostream.h"
33327952Sdim#include <algorithm>
34193326Sed#include <cassert>
35327952Sdim#include <cstdlib>
36327952Sdim#include <cstring>
37193326Sed
38193326Sedusing namespace clang;
39193326Sed
40193326SedNestedNameSpecifier *
41218893SdimNestedNameSpecifier::FindOrInsert(const ASTContext &Context,
42193326Sed                                  const NestedNameSpecifier &Mockup) {
43193326Sed  llvm::FoldingSetNodeID ID;
44193326Sed  Mockup.Profile(ID);
45193326Sed
46276479Sdim  void *InsertPos = nullptr;
47198092Srdivacky  NestedNameSpecifier *NNS
48193326Sed    = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
49193326Sed  if (!NNS) {
50314564Sdim    NNS =
51314564Sdim        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
52193326Sed    Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
53193326Sed  }
54193326Sed
55193326Sed  return NNS;
56193326Sed}
57193326Sed
58193326SedNestedNameSpecifier *
59218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
60218893Sdim                            NestedNameSpecifier *Prefix, IdentifierInfo *II) {
61193326Sed  assert(II && "Identifier cannot be NULL");
62198092Srdivacky  assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
63193326Sed
64193326Sed  NestedNameSpecifier Mockup;
65193326Sed  Mockup.Prefix.setPointer(Prefix);
66219077Sdim  Mockup.Prefix.setInt(StoredIdentifier);
67193326Sed  Mockup.Specifier = II;
68193326Sed  return FindOrInsert(Context, Mockup);
69193326Sed}
70193326Sed
71193326SedNestedNameSpecifier *
72218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
73249423Sdim                            NestedNameSpecifier *Prefix,
74249423Sdim                            const NamespaceDecl *NS) {
75193326Sed  assert(NS && "Namespace cannot be NULL");
76198092Srdivacky  assert((!Prefix ||
77276479Sdim          (Prefix->getAsType() == nullptr &&
78276479Sdim           Prefix->getAsIdentifier() == nullptr)) &&
79193326Sed         "Broken nested name specifier");
80193326Sed  NestedNameSpecifier Mockup;
81193326Sed  Mockup.Prefix.setPointer(Prefix);
82280031Sdim  Mockup.Prefix.setInt(StoredDecl);
83249423Sdim  Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
84193326Sed  return FindOrInsert(Context, Mockup);
85193326Sed}
86193326Sed
87193326SedNestedNameSpecifier *
88218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
89341825Sdim                            NestedNameSpecifier *Prefix,
90219077Sdim                            NamespaceAliasDecl *Alias) {
91219077Sdim  assert(Alias && "Namespace alias cannot be NULL");
92219077Sdim  assert((!Prefix ||
93276479Sdim          (Prefix->getAsType() == nullptr &&
94276479Sdim           Prefix->getAsIdentifier() == nullptr)) &&
95219077Sdim         "Broken nested name specifier");
96219077Sdim  NestedNameSpecifier Mockup;
97219077Sdim  Mockup.Prefix.setPointer(Prefix);
98280031Sdim  Mockup.Prefix.setInt(StoredDecl);
99219077Sdim  Mockup.Specifier = Alias;
100219077Sdim  return FindOrInsert(Context, Mockup);
101219077Sdim}
102219077Sdim
103219077SdimNestedNameSpecifier *
104219077SdimNestedNameSpecifier::Create(const ASTContext &Context,
105218893Sdim                            NestedNameSpecifier *Prefix,
106218893Sdim                            bool Template, const Type *T) {
107193326Sed  assert(T && "Type cannot be NULL");
108193326Sed  NestedNameSpecifier Mockup;
109193326Sed  Mockup.Prefix.setPointer(Prefix);
110219077Sdim  Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
111218893Sdim  Mockup.Specifier = const_cast<Type*>(T);
112193326Sed  return FindOrInsert(Context, Mockup);
113193326Sed}
114198092Srdivacky
115198092SrdivackyNestedNameSpecifier *
116218893SdimNestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
117198092Srdivacky  assert(II && "Identifier cannot be NULL");
118198092Srdivacky  NestedNameSpecifier Mockup;
119276479Sdim  Mockup.Prefix.setPointer(nullptr);
120219077Sdim  Mockup.Prefix.setInt(StoredIdentifier);
121198092Srdivacky  Mockup.Specifier = II;
122198092Srdivacky  return FindOrInsert(Context, Mockup);
123198092Srdivacky}
124198092Srdivacky
125218893SdimNestedNameSpecifier *
126218893SdimNestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
127193326Sed  if (!Context.GlobalNestedNameSpecifier)
128239462Sdim    Context.GlobalNestedNameSpecifier =
129314564Sdim        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
130193326Sed  return Context.GlobalNestedNameSpecifier;
131193326Sed}
132193326Sed
133280031SdimNestedNameSpecifier *
134280031SdimNestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
135280031Sdim                                    CXXRecordDecl *RD) {
136280031Sdim  NestedNameSpecifier Mockup;
137280031Sdim  Mockup.Prefix.setPointer(nullptr);
138280031Sdim  Mockup.Prefix.setInt(StoredDecl);
139280031Sdim  Mockup.Specifier = RD;
140280031Sdim  return FindOrInsert(Context, Mockup);
141280031Sdim}
142280031Sdim
143219077SdimNestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
144276479Sdim  if (!Specifier)
145219077Sdim    return Global;
146219077Sdim
147219077Sdim  switch (Prefix.getInt()) {
148219077Sdim  case StoredIdentifier:
149219077Sdim    return Identifier;
150219077Sdim
151280031Sdim  case StoredDecl: {
152280031Sdim    NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
153280031Sdim    if (isa<CXXRecordDecl>(ND))
154280031Sdim      return Super;
155280031Sdim    return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
156280031Sdim  }
157219077Sdim
158219077Sdim  case StoredTypeSpec:
159219077Sdim    return TypeSpec;
160219077Sdim
161219077Sdim  case StoredTypeSpecWithTemplate:
162219077Sdim    return TypeSpecWithTemplate;
163219077Sdim  }
164219077Sdim
165234353Sdim  llvm_unreachable("Invalid NNS Kind!");
166219077Sdim}
167219077Sdim
168341825Sdim/// Retrieve the namespace stored in this nested name specifier.
169219077SdimNamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
170314564Sdim  if (Prefix.getInt() == StoredDecl)
171219077Sdim    return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
172219077Sdim
173276479Sdim  return nullptr;
174219077Sdim}
175219077Sdim
176341825Sdim/// Retrieve the namespace alias stored in this nested name specifier.
177219077SdimNamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
178314564Sdim  if (Prefix.getInt() == StoredDecl)
179219077Sdim    return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
180219077Sdim
181276479Sdim  return nullptr;
182219077Sdim}
183219077Sdim
184341825Sdim/// Retrieve the record declaration stored in this nested name specifier.
185280031SdimCXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
186309124Sdim  switch (Prefix.getInt()) {
187309124Sdim  case StoredIdentifier:
188309124Sdim    return nullptr;
189309124Sdim
190309124Sdim  case StoredDecl:
191280031Sdim    return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
192219077Sdim
193309124Sdim  case StoredTypeSpec:
194309124Sdim  case StoredTypeSpecWithTemplate:
195309124Sdim    return getAsType()->getAsCXXRecordDecl();
196309124Sdim  }
197309124Sdim
198309124Sdim  llvm_unreachable("Invalid NNS Kind!");
199280031Sdim}
200280031Sdim
201341825Sdim/// Whether this nested name specifier refers to a dependent
202193326Sed/// type or not.
203193326Sedbool NestedNameSpecifier::isDependent() const {
204193326Sed  switch (getKind()) {
205193326Sed  case Identifier:
206193326Sed    // Identifier specifiers always represent dependent types
207193326Sed    return true;
208193326Sed
209193326Sed  case Namespace:
210219077Sdim  case NamespaceAlias:
211193326Sed  case Global:
212193326Sed    return false;
213193326Sed
214280031Sdim  case Super: {
215280031Sdim    CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
216280031Sdim    for (const auto &Base : RD->bases())
217280031Sdim      if (Base.getType()->isDependentType())
218280031Sdim        return true;
219280031Sdim
220280031Sdim    return false;
221280031Sdim  }
222280031Sdim
223193326Sed  case TypeSpec:
224193326Sed  case TypeSpecWithTemplate:
225193326Sed    return getAsType()->isDependentType();
226193326Sed  }
227193326Sed
228234353Sdim  llvm_unreachable("Invalid NNS Kind!");
229193326Sed}
230193326Sed
231341825Sdim/// Whether this nested name specifier refers to a dependent
232224145Sdim/// type or not.
233224145Sdimbool NestedNameSpecifier::isInstantiationDependent() const {
234224145Sdim  switch (getKind()) {
235224145Sdim  case Identifier:
236224145Sdim    // Identifier specifiers always represent dependent types
237224145Sdim    return true;
238341825Sdim
239224145Sdim  case Namespace:
240224145Sdim  case NamespaceAlias:
241224145Sdim  case Global:
242280031Sdim  case Super:
243224145Sdim    return false;
244280031Sdim
245224145Sdim  case TypeSpec:
246224145Sdim  case TypeSpecWithTemplate:
247224145Sdim    return getAsType()->isInstantiationDependentType();
248224145Sdim  }
249234353Sdim
250234353Sdim  llvm_unreachable("Invalid NNS Kind!");
251224145Sdim}
252224145Sdim
253218893Sdimbool NestedNameSpecifier::containsUnexpandedParameterPack() const {
254218893Sdim  switch (getKind()) {
255218893Sdim  case Identifier:
256218893Sdim    return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
257218893Sdim
258218893Sdim  case Namespace:
259219077Sdim  case NamespaceAlias:
260218893Sdim  case Global:
261280031Sdim  case Super:
262218893Sdim    return false;
263218893Sdim
264218893Sdim  case TypeSpec:
265218893Sdim  case TypeSpecWithTemplate:
266218893Sdim    return getAsType()->containsUnexpandedParameterPack();
267218893Sdim  }
268218893Sdim
269234353Sdim  llvm_unreachable("Invalid NNS Kind!");
270218893Sdim}
271218893Sdim
272341825Sdim/// Print this nested name specifier to the given output
273193326Sed/// stream.
274344779Sdimvoid NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
275344779Sdim                                bool ResolveTemplateArguments) const {
276193326Sed  if (getPrefix())
277193326Sed    getPrefix()->print(OS, Policy);
278193326Sed
279193326Sed  switch (getKind()) {
280193326Sed  case Identifier:
281193326Sed    OS << getAsIdentifier()->getName();
282193326Sed    break;
283193326Sed
284193326Sed  case Namespace:
285234353Sdim    if (getAsNamespace()->isAnonymousNamespace())
286234353Sdim      return;
287341825Sdim
288219077Sdim    OS << getAsNamespace()->getName();
289193326Sed    break;
290193326Sed
291219077Sdim  case NamespaceAlias:
292219077Sdim    OS << getAsNamespaceAlias()->getName();
293219077Sdim    break;
294219077Sdim
295193326Sed  case Global:
296193326Sed    break;
297193326Sed
298280031Sdim  case Super:
299280031Sdim    OS << "__super";
300280031Sdim    break;
301280031Sdim
302193326Sed  case TypeSpecWithTemplate:
303193326Sed    OS << "template ";
304193326Sed    // Fall through to print the type.
305321369Sdim    LLVM_FALLTHROUGH;
306193326Sed
307193326Sed  case TypeSpec: {
308344779Sdim    const auto *Record =
309344779Sdim            dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
310344779Sdim    if (ResolveTemplateArguments && Record) {
311344779Sdim        // Print the type trait with resolved template parameters.
312344779Sdim        Record->printName(OS);
313344779Sdim        printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
314344779Sdim                                  Policy);
315344779Sdim        break;
316344779Sdim    }
317218893Sdim    const Type *T = getAsType();
318193326Sed
319193326Sed    PrintingPolicy InnerPolicy(Policy);
320198092Srdivacky    InnerPolicy.SuppressScope = true;
321198092Srdivacky
322198092Srdivacky    // Nested-name-specifiers are intended to contain minimally-qualified
323208600Srdivacky    // types. An actual ElaboratedType will not occur, since we'll store
324198092Srdivacky    // just the type that is referred to in the nested-name-specifier (e.g.,
325198092Srdivacky    // a TypedefType, TagType, etc.). However, when we are dealing with
326198092Srdivacky    // dependent template-id types (e.g., Outer<T>::template Inner<U>),
327198092Srdivacky    // the type requires its own nested-name-specifier for uniqueness, so we
328198092Srdivacky    // suppress that nested-name-specifier during printing.
329208600Srdivacky    assert(!isa<ElaboratedType>(T) &&
330208600Srdivacky           "Elaborated type in nested-name-specifier");
331198092Srdivacky    if (const TemplateSpecializationType *SpecType
332198092Srdivacky          = dyn_cast<TemplateSpecializationType>(T)) {
333198092Srdivacky      // Print the template name without its corresponding
334198092Srdivacky      // nested-name-specifier.
335198092Srdivacky      SpecType->getTemplateName().print(OS, InnerPolicy, true);
336198092Srdivacky
337198092Srdivacky      // Print the template argument list.
338327952Sdim      printTemplateArgumentList(OS, SpecType->template_arguments(),
339327952Sdim                                InnerPolicy);
340198092Srdivacky    } else {
341198092Srdivacky      // Print the type normally
342249423Sdim      QualType(T, 0).print(OS, InnerPolicy);
343198092Srdivacky    }
344193326Sed    break;
345193326Sed  }
346193326Sed  }
347193326Sed
348193326Sed  OS << "::";
349193326Sed}
350193326Sed
351344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
352344779Sdim  dump(llvm::errs(), LO);
353193326Sed}
354219077Sdim
355344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
356344779Sdim
357344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
358296417Sdim  LangOptions LO;
359344779Sdim  dump(OS, LO);
360296417Sdim}
361296417Sdim
362344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
363344779Sdim                                                const LangOptions &LO) const {
364344779Sdim  print(OS, PrintingPolicy(LO));
365344779Sdim}
366344779Sdim
367341825Sdimunsigned
368219077SdimNestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
369219077Sdim  assert(Qualifier && "Expected a non-NULL qualifier");
370219077Sdim
371219077Sdim  // Location of the trailing '::'.
372219077Sdim  unsigned Length = sizeof(unsigned);
373219077Sdim
374219077Sdim  switch (Qualifier->getKind()) {
375219077Sdim  case NestedNameSpecifier::Global:
376219077Sdim    // Nothing more to add.
377219077Sdim    break;
378219077Sdim
379219077Sdim  case NestedNameSpecifier::Identifier:
380219077Sdim  case NestedNameSpecifier::Namespace:
381219077Sdim  case NestedNameSpecifier::NamespaceAlias:
382280031Sdim  case NestedNameSpecifier::Super:
383219077Sdim    // The location of the identifier or namespace name.
384219077Sdim    Length += sizeof(unsigned);
385219077Sdim    break;
386219077Sdim
387219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
388219077Sdim  case NestedNameSpecifier::TypeSpec:
389219077Sdim    // The "void*" that points at the TypeLoc data.
390219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
391219077Sdim    Length += sizeof(void *);
392219077Sdim    break;
393219077Sdim  }
394219077Sdim
395219077Sdim  return Length;
396219077Sdim}
397219077Sdim
398341825Sdimunsigned
399219077SdimNestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
400219077Sdim  unsigned Length = 0;
401219077Sdim  for (; Qualifier; Qualifier = Qualifier->getPrefix())
402219077Sdim    Length += getLocalDataLength(Qualifier);
403219077Sdim  return Length;
404219077Sdim}
405219077Sdim
406341825Sdim/// Load a (possibly unaligned) source location from a given address
407327952Sdim/// and offset.
408327952Sdimstatic SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
409327952Sdim  unsigned Raw;
410327952Sdim  memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
411327952Sdim  return SourceLocation::getFromRawEncoding(Raw);
412327952Sdim}
413341825Sdim
414341825Sdim/// Load a (possibly unaligned) pointer from a given address and
415327952Sdim/// offset.
416327952Sdimstatic void *LoadPointer(void *Data, unsigned Offset) {
417327952Sdim  void *Result;
418327952Sdim  memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
419327952Sdim  return Result;
420219077Sdim}
421219077Sdim
422219077SdimSourceRange NestedNameSpecifierLoc::getSourceRange() const {
423219077Sdim  if (!Qualifier)
424219077Sdim    return SourceRange();
425341825Sdim
426219077Sdim  NestedNameSpecifierLoc First = *this;
427219077Sdim  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
428219077Sdim    First = Prefix;
429341825Sdim
430341825Sdim  return SourceRange(First.getLocalSourceRange().getBegin(),
431219077Sdim                     getLocalSourceRange().getEnd());
432219077Sdim}
433219077Sdim
434219077SdimSourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
435219077Sdim  if (!Qualifier)
436219077Sdim    return SourceRange();
437341825Sdim
438219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
439219077Sdim  switch (Qualifier->getKind()) {
440219077Sdim  case NestedNameSpecifier::Global:
441219077Sdim    return LoadSourceLocation(Data, Offset);
442219077Sdim
443219077Sdim  case NestedNameSpecifier::Identifier:
444219077Sdim  case NestedNameSpecifier::Namespace:
445219077Sdim  case NestedNameSpecifier::NamespaceAlias:
446280031Sdim  case NestedNameSpecifier::Super:
447219077Sdim    return SourceRange(LoadSourceLocation(Data, Offset),
448219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
449219077Sdim
450219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
451219077Sdim  case NestedNameSpecifier::TypeSpec: {
452219077Sdim    // The "void*" that points at the TypeLoc data.
453219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
454219077Sdim    void *TypeData = LoadPointer(Data, Offset);
455219077Sdim    TypeLoc TL(Qualifier->getAsType(), TypeData);
456219077Sdim    return SourceRange(TL.getBeginLoc(),
457219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(void*)));
458219077Sdim  }
459219077Sdim  }
460234353Sdim
461234353Sdim  llvm_unreachable("Invalid NNS Kind!");
462219077Sdim}
463219077Sdim
464219077SdimTypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
465344779Sdim  if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
466344779Sdim      Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
467344779Sdim    return TypeLoc();
468219077Sdim
469219077Sdim  // The "void*" that points at the TypeLoc data.
470219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
471219077Sdim  void *TypeData = LoadPointer(Data, Offset);
472219077Sdim  return TypeLoc(Qualifier->getAsType(), TypeData);
473219077Sdim}
474221345Sdim
475327952Sdimstatic void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
476221345Sdim              unsigned &BufferCapacity) {
477327952Sdim  if (Start == End)
478327952Sdim    return;
479288943Sdim
480327952Sdim  if (BufferSize + (End - Start) > BufferCapacity) {
481327952Sdim    // Reallocate the buffer.
482327952Sdim    unsigned NewCapacity = std::max(
483327952Sdim        (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
484327952Sdim        (unsigned)(BufferSize + (End - Start)));
485341825Sdim    char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
486327952Sdim    if (BufferCapacity) {
487327952Sdim      memcpy(NewBuffer, Buffer, BufferSize);
488327952Sdim      free(Buffer);
489221345Sdim    }
490327952Sdim    Buffer = NewBuffer;
491327952Sdim    BufferCapacity = NewCapacity;
492221345Sdim  }
493327952Sdim
494327952Sdim  memcpy(Buffer + BufferSize, Start, End - Start);
495327952Sdim  BufferSize += End-Start;
496327952Sdim}
497341825Sdim
498341825Sdim/// Save a source location to the given buffer.
499327952Sdimstatic void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
500327952Sdim                               unsigned &BufferSize, unsigned &BufferCapacity) {
501327952Sdim  unsigned Raw = Loc.getRawEncoding();
502327952Sdim  Append(reinterpret_cast<char *>(&Raw),
503327952Sdim         reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
504327952Sdim         Buffer, BufferSize, BufferCapacity);
505327952Sdim}
506341825Sdim
507341825Sdim/// Save a pointer to the given buffer.
508327952Sdimstatic void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
509327952Sdim                        unsigned &BufferCapacity) {
510327952Sdim  Append(reinterpret_cast<char *>(&Ptr),
511327952Sdim         reinterpret_cast<char *>(&Ptr) + sizeof(void *),
512327952Sdim         Buffer, BufferSize, BufferCapacity);
513221345Sdim}
514221345Sdim
515221345SdimNestedNameSpecifierLocBuilder::
516341825SdimNestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
517327952Sdim    : Representation(Other.Representation) {
518221345Sdim  if (!Other.Buffer)
519221345Sdim    return;
520341825Sdim
521221345Sdim  if (Other.BufferCapacity == 0) {
522221345Sdim    // Shallow copy is okay.
523221345Sdim    Buffer = Other.Buffer;
524221345Sdim    BufferSize = Other.BufferSize;
525221345Sdim    return;
526221345Sdim  }
527341825Sdim
528221345Sdim  // Deep copy
529276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
530276479Sdim         BufferCapacity);
531221345Sdim}
532221345Sdim
533221345SdimNestedNameSpecifierLocBuilder &
534221345SdimNestedNameSpecifierLocBuilder::
535221345Sdimoperator=(const NestedNameSpecifierLocBuilder &Other) {
536221345Sdim  Representation = Other.Representation;
537341825Sdim
538221345Sdim  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
539221345Sdim    // Re-use our storage.
540221345Sdim    BufferSize = Other.BufferSize;
541221345Sdim    memcpy(Buffer, Other.Buffer, BufferSize);
542221345Sdim    return *this;
543221345Sdim  }
544341825Sdim
545221345Sdim  // Free our storage, if we have any.
546221345Sdim  if (BufferCapacity) {
547221345Sdim    free(Buffer);
548221345Sdim    BufferCapacity = 0;
549221345Sdim  }
550341825Sdim
551221345Sdim  if (!Other.Buffer) {
552221345Sdim    // Empty.
553276479Sdim    Buffer = nullptr;
554221345Sdim    BufferSize = 0;
555221345Sdim    return *this;
556221345Sdim  }
557341825Sdim
558221345Sdim  if (Other.BufferCapacity == 0) {
559221345Sdim    // Shallow copy is okay.
560221345Sdim    Buffer = Other.Buffer;
561221345Sdim    BufferSize = Other.BufferSize;
562221345Sdim    return *this;
563221345Sdim  }
564341825Sdim
565221345Sdim  // Deep copy.
566344779Sdim  BufferSize = 0;
567276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
568276479Sdim         BufferCapacity);
569221345Sdim  return *this;
570221345Sdim}
571221345Sdim
572341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
573341825Sdim                                           SourceLocation TemplateKWLoc,
574341825Sdim                                           TypeLoc TL,
575221345Sdim                                           SourceLocation ColonColonLoc) {
576341825Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
577341825Sdim                                               TemplateKWLoc.isValid(),
578221345Sdim                                               TL.getTypePtr());
579341825Sdim
580221345Sdim  // Push source-location info into the buffer.
581221345Sdim  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
582221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
583221345Sdim}
584221345Sdim
585341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
586221345Sdim                                           IdentifierInfo *Identifier,
587341825Sdim                                           SourceLocation IdentifierLoc,
588221345Sdim                                           SourceLocation ColonColonLoc) {
589341825Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
590221345Sdim                                               Identifier);
591341825Sdim
592221345Sdim  // Push source-location info into the buffer.
593221345Sdim  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
594221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
595221345Sdim}
596221345Sdim
597341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
598221345Sdim                                           NamespaceDecl *Namespace,
599341825Sdim                                           SourceLocation NamespaceLoc,
600221345Sdim                                           SourceLocation ColonColonLoc) {
601341825Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
602221345Sdim                                               Namespace);
603341825Sdim
604221345Sdim  // Push source-location info into the buffer.
605221345Sdim  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
606221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
607221345Sdim}
608221345Sdim
609221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
610221345Sdim                                           NamespaceAliasDecl *Alias,
611341825Sdim                                           SourceLocation AliasLoc,
612221345Sdim                                           SourceLocation ColonColonLoc) {
613221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
614341825Sdim
615221345Sdim  // Push source-location info into the buffer.
616221345Sdim  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
617221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
618221345Sdim}
619221345Sdim
620341825Sdimvoid NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
621221345Sdim                                               SourceLocation ColonColonLoc) {
622221345Sdim  assert(!Representation && "Already have a nested-name-specifier!?");
623221345Sdim  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
624341825Sdim
625221345Sdim  // Push source-location info into the buffer.
626221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
627221345Sdim}
628221345Sdim
629280031Sdimvoid NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
630280031Sdim                                              CXXRecordDecl *RD,
631280031Sdim                                              SourceLocation SuperLoc,
632280031Sdim                                              SourceLocation ColonColonLoc) {
633280031Sdim  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
634280031Sdim
635280031Sdim  // Push source-location info into the buffer.
636280031Sdim  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
637280031Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
638280031Sdim}
639280031Sdim
640341825Sdimvoid NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
641341825Sdim                                                NestedNameSpecifier *Qualifier,
642221345Sdim                                                SourceRange R) {
643221345Sdim  Representation = Qualifier;
644341825Sdim
645341825Sdim  // Construct bogus (but well-formed) source information for the
646221345Sdim  // nested-name-specifier.
647221345Sdim  BufferSize = 0;
648226633Sdim  SmallVector<NestedNameSpecifier *, 4> Stack;
649221345Sdim  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
650221345Sdim    Stack.push_back(NNS);
651221345Sdim  while (!Stack.empty()) {
652261991Sdim    NestedNameSpecifier *NNS = Stack.pop_back_val();
653221345Sdim    switch (NNS->getKind()) {
654221345Sdim      case NestedNameSpecifier::Identifier:
655221345Sdim      case NestedNameSpecifier::Namespace:
656221345Sdim      case NestedNameSpecifier::NamespaceAlias:
657221345Sdim        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
658221345Sdim        break;
659341825Sdim
660221345Sdim      case NestedNameSpecifier::TypeSpec:
661221345Sdim      case NestedNameSpecifier::TypeSpecWithTemplate: {
662221345Sdim        TypeSourceInfo *TSInfo
663221345Sdim        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
664221345Sdim                                           R.getBegin());
665341825Sdim        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
666221345Sdim                    BufferCapacity);
667221345Sdim        break;
668221345Sdim      }
669341825Sdim
670221345Sdim      case NestedNameSpecifier::Global:
671280031Sdim      case NestedNameSpecifier::Super:
672221345Sdim        break;
673221345Sdim    }
674341825Sdim
675221345Sdim    // Save the location of the '::'.
676341825Sdim    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
677221345Sdim                       Buffer, BufferSize, BufferCapacity);
678221345Sdim  }
679221345Sdim}
680221345Sdim
681221345Sdimvoid NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
682221345Sdim  if (BufferCapacity)
683221345Sdim    free(Buffer);
684221345Sdim
685221345Sdim  if (!Other) {
686276479Sdim    Representation = nullptr;
687221345Sdim    BufferSize = 0;
688221345Sdim    return;
689221345Sdim  }
690341825Sdim
691341825Sdim  // Rather than copying the data (which is wasteful), "adopt" the
692221345Sdim  // pointer (which points into the ASTContext) but set the capacity to zero to
693221345Sdim  // indicate that we don't own it.
694221345Sdim  Representation = Other.getNestedNameSpecifier();
695221345Sdim  Buffer = static_cast<char *>(Other.getOpaqueData());
696221345Sdim  BufferSize = Other.getDataLength();
697221345Sdim  BufferCapacity = 0;
698221345Sdim}
699221345Sdim
700341825SdimNestedNameSpecifierLoc
701221345SdimNestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
702221345Sdim  if (!Representation)
703221345Sdim    return NestedNameSpecifierLoc();
704341825Sdim
705221345Sdim  // If we adopted our data pointer from elsewhere in the AST context, there's
706221345Sdim  // no need to copy the memory.
707221345Sdim  if (BufferCapacity == 0)
708221345Sdim    return NestedNameSpecifierLoc(Representation, Buffer);
709341825Sdim
710221345Sdim  // FIXME: After copying the source-location information, should we free
711221345Sdim  // our (temporary) buffer and adopt the ASTContext-allocated memory?
712221345Sdim  // Doing so would optimize repeated calls to getWithLocInContext().
713314564Sdim  void *Mem = Context.Allocate(BufferSize, alignof(void *));
714221345Sdim  memcpy(Mem, Buffer, BufferSize);
715221345Sdim  return NestedNameSpecifierLoc(Representation, Mem);
716221345Sdim}
717