1327952Sdim//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
2193326Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193326Sed//
7193326Sed//===----------------------------------------------------------------------===//
8193326Sed//
9193326Sed//  This file defines the NestedNameSpecifier class, which represents
10193326Sed//  a C++ nested-name-specifier.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13327952Sdim
14193326Sed#include "clang/AST/NestedNameSpecifier.h"
15193326Sed#include "clang/AST/ASTContext.h"
16193326Sed#include "clang/AST/Decl.h"
17219077Sdim#include "clang/AST/DeclCXX.h"
18344779Sdim#include "clang/AST/DeclTemplate.h"
19193326Sed#include "clang/AST/PrettyPrinter.h"
20327952Sdim#include "clang/AST/TemplateName.h"
21193326Sed#include "clang/AST/Type.h"
22219077Sdim#include "clang/AST/TypeLoc.h"
23327952Sdim#include "clang/Basic/LLVM.h"
24327952Sdim#include "clang/Basic/LangOptions.h"
25327952Sdim#include "clang/Basic/SourceLocation.h"
26327952Sdim#include "llvm/ADT/FoldingSet.h"
27327952Sdim#include "llvm/ADT/SmallVector.h"
28327952Sdim#include "llvm/Support/Casting.h"
29327952Sdim#include "llvm/Support/Compiler.h"
30327952Sdim#include "llvm/Support/ErrorHandling.h"
31193326Sed#include "llvm/Support/raw_ostream.h"
32327952Sdim#include <algorithm>
33193326Sed#include <cassert>
34327952Sdim#include <cstdlib>
35327952Sdim#include <cstring>
36193326Sed
37193326Sedusing namespace clang;
38193326Sed
39193326SedNestedNameSpecifier *
40218893SdimNestedNameSpecifier::FindOrInsert(const ASTContext &Context,
41193326Sed                                  const NestedNameSpecifier &Mockup) {
42193326Sed  llvm::FoldingSetNodeID ID;
43193326Sed  Mockup.Profile(ID);
44193326Sed
45276479Sdim  void *InsertPos = nullptr;
46198092Srdivacky  NestedNameSpecifier *NNS
47193326Sed    = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
48193326Sed  if (!NNS) {
49314564Sdim    NNS =
50314564Sdim        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
51193326Sed    Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
52193326Sed  }
53193326Sed
54193326Sed  return NNS;
55193326Sed}
56193326Sed
57193326SedNestedNameSpecifier *
58218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
59218893Sdim                            NestedNameSpecifier *Prefix, IdentifierInfo *II) {
60193326Sed  assert(II && "Identifier cannot be NULL");
61198092Srdivacky  assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
62193326Sed
63193326Sed  NestedNameSpecifier Mockup;
64193326Sed  Mockup.Prefix.setPointer(Prefix);
65219077Sdim  Mockup.Prefix.setInt(StoredIdentifier);
66193326Sed  Mockup.Specifier = II;
67193326Sed  return FindOrInsert(Context, Mockup);
68193326Sed}
69193326Sed
70193326SedNestedNameSpecifier *
71218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
72249423Sdim                            NestedNameSpecifier *Prefix,
73249423Sdim                            const NamespaceDecl *NS) {
74193326Sed  assert(NS && "Namespace cannot be NULL");
75198092Srdivacky  assert((!Prefix ||
76276479Sdim          (Prefix->getAsType() == nullptr &&
77276479Sdim           Prefix->getAsIdentifier() == nullptr)) &&
78193326Sed         "Broken nested name specifier");
79193326Sed  NestedNameSpecifier Mockup;
80193326Sed  Mockup.Prefix.setPointer(Prefix);
81280031Sdim  Mockup.Prefix.setInt(StoredDecl);
82249423Sdim  Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
83193326Sed  return FindOrInsert(Context, Mockup);
84193326Sed}
85193326Sed
86193326SedNestedNameSpecifier *
87218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
88341825Sdim                            NestedNameSpecifier *Prefix,
89219077Sdim                            NamespaceAliasDecl *Alias) {
90219077Sdim  assert(Alias && "Namespace alias cannot be NULL");
91219077Sdim  assert((!Prefix ||
92276479Sdim          (Prefix->getAsType() == nullptr &&
93276479Sdim           Prefix->getAsIdentifier() == nullptr)) &&
94219077Sdim         "Broken nested name specifier");
95219077Sdim  NestedNameSpecifier Mockup;
96219077Sdim  Mockup.Prefix.setPointer(Prefix);
97280031Sdim  Mockup.Prefix.setInt(StoredDecl);
98219077Sdim  Mockup.Specifier = Alias;
99219077Sdim  return FindOrInsert(Context, Mockup);
100219077Sdim}
101219077Sdim
102219077SdimNestedNameSpecifier *
103219077SdimNestedNameSpecifier::Create(const ASTContext &Context,
104218893Sdim                            NestedNameSpecifier *Prefix,
105218893Sdim                            bool Template, const Type *T) {
106193326Sed  assert(T && "Type cannot be NULL");
107193326Sed  NestedNameSpecifier Mockup;
108193326Sed  Mockup.Prefix.setPointer(Prefix);
109219077Sdim  Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
110218893Sdim  Mockup.Specifier = const_cast<Type*>(T);
111193326Sed  return FindOrInsert(Context, Mockup);
112193326Sed}
113198092Srdivacky
114198092SrdivackyNestedNameSpecifier *
115218893SdimNestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
116198092Srdivacky  assert(II && "Identifier cannot be NULL");
117198092Srdivacky  NestedNameSpecifier Mockup;
118276479Sdim  Mockup.Prefix.setPointer(nullptr);
119219077Sdim  Mockup.Prefix.setInt(StoredIdentifier);
120198092Srdivacky  Mockup.Specifier = II;
121198092Srdivacky  return FindOrInsert(Context, Mockup);
122198092Srdivacky}
123198092Srdivacky
124218893SdimNestedNameSpecifier *
125218893SdimNestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
126193326Sed  if (!Context.GlobalNestedNameSpecifier)
127239462Sdim    Context.GlobalNestedNameSpecifier =
128314564Sdim        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
129193326Sed  return Context.GlobalNestedNameSpecifier;
130193326Sed}
131193326Sed
132280031SdimNestedNameSpecifier *
133280031SdimNestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
134280031Sdim                                    CXXRecordDecl *RD) {
135280031Sdim  NestedNameSpecifier Mockup;
136280031Sdim  Mockup.Prefix.setPointer(nullptr);
137280031Sdim  Mockup.Prefix.setInt(StoredDecl);
138280031Sdim  Mockup.Specifier = RD;
139280031Sdim  return FindOrInsert(Context, Mockup);
140280031Sdim}
141280031Sdim
142219077SdimNestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
143276479Sdim  if (!Specifier)
144219077Sdim    return Global;
145219077Sdim
146219077Sdim  switch (Prefix.getInt()) {
147219077Sdim  case StoredIdentifier:
148219077Sdim    return Identifier;
149219077Sdim
150280031Sdim  case StoredDecl: {
151280031Sdim    NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
152280031Sdim    if (isa<CXXRecordDecl>(ND))
153280031Sdim      return Super;
154280031Sdim    return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
155280031Sdim  }
156219077Sdim
157219077Sdim  case StoredTypeSpec:
158219077Sdim    return TypeSpec;
159219077Sdim
160219077Sdim  case StoredTypeSpecWithTemplate:
161219077Sdim    return TypeSpecWithTemplate;
162219077Sdim  }
163219077Sdim
164234353Sdim  llvm_unreachable("Invalid NNS Kind!");
165219077Sdim}
166219077Sdim
167341825Sdim/// Retrieve the namespace stored in this nested name specifier.
168219077SdimNamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
169314564Sdim  if (Prefix.getInt() == StoredDecl)
170219077Sdim    return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
171219077Sdim
172276479Sdim  return nullptr;
173219077Sdim}
174219077Sdim
175341825Sdim/// Retrieve the namespace alias stored in this nested name specifier.
176219077SdimNamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
177314564Sdim  if (Prefix.getInt() == StoredDecl)
178219077Sdim    return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
179219077Sdim
180276479Sdim  return nullptr;
181219077Sdim}
182219077Sdim
183341825Sdim/// Retrieve the record declaration stored in this nested name specifier.
184280031SdimCXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
185309124Sdim  switch (Prefix.getInt()) {
186309124Sdim  case StoredIdentifier:
187309124Sdim    return nullptr;
188309124Sdim
189309124Sdim  case StoredDecl:
190280031Sdim    return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
191219077Sdim
192309124Sdim  case StoredTypeSpec:
193309124Sdim  case StoredTypeSpecWithTemplate:
194309124Sdim    return getAsType()->getAsCXXRecordDecl();
195309124Sdim  }
196309124Sdim
197309124Sdim  llvm_unreachable("Invalid NNS Kind!");
198280031Sdim}
199280031Sdim
200341825Sdim/// Whether this nested name specifier refers to a dependent
201193326Sed/// type or not.
202193326Sedbool NestedNameSpecifier::isDependent() const {
203193326Sed  switch (getKind()) {
204193326Sed  case Identifier:
205193326Sed    // Identifier specifiers always represent dependent types
206193326Sed    return true;
207193326Sed
208193326Sed  case Namespace:
209219077Sdim  case NamespaceAlias:
210193326Sed  case Global:
211193326Sed    return false;
212193326Sed
213280031Sdim  case Super: {
214280031Sdim    CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
215280031Sdim    for (const auto &Base : RD->bases())
216280031Sdim      if (Base.getType()->isDependentType())
217280031Sdim        return true;
218280031Sdim
219280031Sdim    return false;
220280031Sdim  }
221280031Sdim
222193326Sed  case TypeSpec:
223193326Sed  case TypeSpecWithTemplate:
224193326Sed    return getAsType()->isDependentType();
225193326Sed  }
226193326Sed
227234353Sdim  llvm_unreachable("Invalid NNS Kind!");
228193326Sed}
229193326Sed
230341825Sdim/// Whether this nested name specifier refers to a dependent
231224145Sdim/// type or not.
232224145Sdimbool NestedNameSpecifier::isInstantiationDependent() const {
233224145Sdim  switch (getKind()) {
234224145Sdim  case Identifier:
235224145Sdim    // Identifier specifiers always represent dependent types
236224145Sdim    return true;
237341825Sdim
238224145Sdim  case Namespace:
239224145Sdim  case NamespaceAlias:
240224145Sdim  case Global:
241280031Sdim  case Super:
242224145Sdim    return false;
243280031Sdim
244224145Sdim  case TypeSpec:
245224145Sdim  case TypeSpecWithTemplate:
246224145Sdim    return getAsType()->isInstantiationDependentType();
247224145Sdim  }
248234353Sdim
249234353Sdim  llvm_unreachable("Invalid NNS Kind!");
250224145Sdim}
251224145Sdim
252218893Sdimbool NestedNameSpecifier::containsUnexpandedParameterPack() const {
253218893Sdim  switch (getKind()) {
254218893Sdim  case Identifier:
255218893Sdim    return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
256218893Sdim
257218893Sdim  case Namespace:
258219077Sdim  case NamespaceAlias:
259218893Sdim  case Global:
260280031Sdim  case Super:
261218893Sdim    return false;
262218893Sdim
263218893Sdim  case TypeSpec:
264218893Sdim  case TypeSpecWithTemplate:
265218893Sdim    return getAsType()->containsUnexpandedParameterPack();
266218893Sdim  }
267218893Sdim
268234353Sdim  llvm_unreachable("Invalid NNS Kind!");
269218893Sdim}
270218893Sdim
271341825Sdim/// Print this nested name specifier to the given output
272193326Sed/// stream.
273344779Sdimvoid NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
274344779Sdim                                bool ResolveTemplateArguments) const {
275193326Sed  if (getPrefix())
276193326Sed    getPrefix()->print(OS, Policy);
277193326Sed
278193326Sed  switch (getKind()) {
279193326Sed  case Identifier:
280193326Sed    OS << getAsIdentifier()->getName();
281193326Sed    break;
282193326Sed
283193326Sed  case Namespace:
284234353Sdim    if (getAsNamespace()->isAnonymousNamespace())
285234353Sdim      return;
286341825Sdim
287219077Sdim    OS << getAsNamespace()->getName();
288193326Sed    break;
289193326Sed
290219077Sdim  case NamespaceAlias:
291219077Sdim    OS << getAsNamespaceAlias()->getName();
292219077Sdim    break;
293219077Sdim
294193326Sed  case Global:
295193326Sed    break;
296193326Sed
297280031Sdim  case Super:
298280031Sdim    OS << "__super";
299280031Sdim    break;
300280031Sdim
301193326Sed  case TypeSpecWithTemplate:
302193326Sed    OS << "template ";
303193326Sed    // Fall through to print the type.
304321369Sdim    LLVM_FALLTHROUGH;
305193326Sed
306193326Sed  case TypeSpec: {
307344779Sdim    const auto *Record =
308344779Sdim            dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
309344779Sdim    if (ResolveTemplateArguments && Record) {
310344779Sdim        // Print the type trait with resolved template parameters.
311344779Sdim        Record->printName(OS);
312344779Sdim        printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
313344779Sdim                                  Policy);
314344779Sdim        break;
315344779Sdim    }
316218893Sdim    const Type *T = getAsType();
317193326Sed
318193326Sed    PrintingPolicy InnerPolicy(Policy);
319198092Srdivacky    InnerPolicy.SuppressScope = true;
320198092Srdivacky
321198092Srdivacky    // Nested-name-specifiers are intended to contain minimally-qualified
322208600Srdivacky    // types. An actual ElaboratedType will not occur, since we'll store
323198092Srdivacky    // just the type that is referred to in the nested-name-specifier (e.g.,
324198092Srdivacky    // a TypedefType, TagType, etc.). However, when we are dealing with
325198092Srdivacky    // dependent template-id types (e.g., Outer<T>::template Inner<U>),
326198092Srdivacky    // the type requires its own nested-name-specifier for uniqueness, so we
327198092Srdivacky    // suppress that nested-name-specifier during printing.
328208600Srdivacky    assert(!isa<ElaboratedType>(T) &&
329208600Srdivacky           "Elaborated type in nested-name-specifier");
330198092Srdivacky    if (const TemplateSpecializationType *SpecType
331198092Srdivacky          = dyn_cast<TemplateSpecializationType>(T)) {
332198092Srdivacky      // Print the template name without its corresponding
333198092Srdivacky      // nested-name-specifier.
334198092Srdivacky      SpecType->getTemplateName().print(OS, InnerPolicy, true);
335198092Srdivacky
336198092Srdivacky      // Print the template argument list.
337327952Sdim      printTemplateArgumentList(OS, SpecType->template_arguments(),
338327952Sdim                                InnerPolicy);
339198092Srdivacky    } else {
340198092Srdivacky      // Print the type normally
341249423Sdim      QualType(T, 0).print(OS, InnerPolicy);
342198092Srdivacky    }
343193326Sed    break;
344193326Sed  }
345193326Sed  }
346193326Sed
347193326Sed  OS << "::";
348193326Sed}
349193326Sed
350344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
351344779Sdim  dump(llvm::errs(), LO);
352193326Sed}
353219077Sdim
354344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
355344779Sdim
356344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
357296417Sdim  LangOptions LO;
358344779Sdim  dump(OS, LO);
359296417Sdim}
360296417Sdim
361344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
362344779Sdim                                                const LangOptions &LO) const {
363344779Sdim  print(OS, PrintingPolicy(LO));
364344779Sdim}
365344779Sdim
366341825Sdimunsigned
367219077SdimNestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
368219077Sdim  assert(Qualifier && "Expected a non-NULL qualifier");
369219077Sdim
370219077Sdim  // Location of the trailing '::'.
371219077Sdim  unsigned Length = sizeof(unsigned);
372219077Sdim
373219077Sdim  switch (Qualifier->getKind()) {
374219077Sdim  case NestedNameSpecifier::Global:
375219077Sdim    // Nothing more to add.
376219077Sdim    break;
377219077Sdim
378219077Sdim  case NestedNameSpecifier::Identifier:
379219077Sdim  case NestedNameSpecifier::Namespace:
380219077Sdim  case NestedNameSpecifier::NamespaceAlias:
381280031Sdim  case NestedNameSpecifier::Super:
382219077Sdim    // The location of the identifier or namespace name.
383219077Sdim    Length += sizeof(unsigned);
384219077Sdim    break;
385219077Sdim
386219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
387219077Sdim  case NestedNameSpecifier::TypeSpec:
388219077Sdim    // The "void*" that points at the TypeLoc data.
389219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
390219077Sdim    Length += sizeof(void *);
391219077Sdim    break;
392219077Sdim  }
393219077Sdim
394219077Sdim  return Length;
395219077Sdim}
396219077Sdim
397341825Sdimunsigned
398219077SdimNestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
399219077Sdim  unsigned Length = 0;
400219077Sdim  for (; Qualifier; Qualifier = Qualifier->getPrefix())
401219077Sdim    Length += getLocalDataLength(Qualifier);
402219077Sdim  return Length;
403219077Sdim}
404219077Sdim
405341825Sdim/// Load a (possibly unaligned) source location from a given address
406327952Sdim/// and offset.
407327952Sdimstatic SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
408327952Sdim  unsigned Raw;
409327952Sdim  memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
410327952Sdim  return SourceLocation::getFromRawEncoding(Raw);
411327952Sdim}
412341825Sdim
413341825Sdim/// Load a (possibly unaligned) pointer from a given address and
414327952Sdim/// offset.
415327952Sdimstatic void *LoadPointer(void *Data, unsigned Offset) {
416327952Sdim  void *Result;
417327952Sdim  memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
418327952Sdim  return Result;
419219077Sdim}
420219077Sdim
421219077SdimSourceRange NestedNameSpecifierLoc::getSourceRange() const {
422219077Sdim  if (!Qualifier)
423219077Sdim    return SourceRange();
424341825Sdim
425219077Sdim  NestedNameSpecifierLoc First = *this;
426219077Sdim  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
427219077Sdim    First = Prefix;
428341825Sdim
429341825Sdim  return SourceRange(First.getLocalSourceRange().getBegin(),
430219077Sdim                     getLocalSourceRange().getEnd());
431219077Sdim}
432219077Sdim
433219077SdimSourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
434219077Sdim  if (!Qualifier)
435219077Sdim    return SourceRange();
436341825Sdim
437219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
438219077Sdim  switch (Qualifier->getKind()) {
439219077Sdim  case NestedNameSpecifier::Global:
440219077Sdim    return LoadSourceLocation(Data, Offset);
441219077Sdim
442219077Sdim  case NestedNameSpecifier::Identifier:
443219077Sdim  case NestedNameSpecifier::Namespace:
444219077Sdim  case NestedNameSpecifier::NamespaceAlias:
445280031Sdim  case NestedNameSpecifier::Super:
446219077Sdim    return SourceRange(LoadSourceLocation(Data, Offset),
447219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
448219077Sdim
449219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
450219077Sdim  case NestedNameSpecifier::TypeSpec: {
451219077Sdim    // The "void*" that points at the TypeLoc data.
452219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
453219077Sdim    void *TypeData = LoadPointer(Data, Offset);
454219077Sdim    TypeLoc TL(Qualifier->getAsType(), TypeData);
455219077Sdim    return SourceRange(TL.getBeginLoc(),
456219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(void*)));
457219077Sdim  }
458219077Sdim  }
459234353Sdim
460234353Sdim  llvm_unreachable("Invalid NNS Kind!");
461219077Sdim}
462219077Sdim
463219077SdimTypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
464344779Sdim  if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
465344779Sdim      Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
466344779Sdim    return TypeLoc();
467219077Sdim
468219077Sdim  // The "void*" that points at the TypeLoc data.
469219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
470219077Sdim  void *TypeData = LoadPointer(Data, Offset);
471219077Sdim  return TypeLoc(Qualifier->getAsType(), TypeData);
472219077Sdim}
473221345Sdim
474327952Sdimstatic void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
475360784Sdim                   unsigned &BufferCapacity) {
476327952Sdim  if (Start == End)
477327952Sdim    return;
478288943Sdim
479327952Sdim  if (BufferSize + (End - Start) > BufferCapacity) {
480327952Sdim    // Reallocate the buffer.
481327952Sdim    unsigned NewCapacity = std::max(
482327952Sdim        (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
483327952Sdim        (unsigned)(BufferSize + (End - Start)));
484341825Sdim    char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
485327952Sdim    if (BufferCapacity) {
486327952Sdim      memcpy(NewBuffer, Buffer, BufferSize);
487327952Sdim      free(Buffer);
488221345Sdim    }
489327952Sdim    Buffer = NewBuffer;
490327952Sdim    BufferCapacity = NewCapacity;
491221345Sdim  }
492360784Sdim  assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");
493327952Sdim  memcpy(Buffer + BufferSize, Start, End - Start);
494360784Sdim  BufferSize += End - Start;
495327952Sdim}
496341825Sdim
497341825Sdim/// Save a source location to the given buffer.
498327952Sdimstatic void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
499327952Sdim                               unsigned &BufferSize, unsigned &BufferCapacity) {
500327952Sdim  unsigned Raw = Loc.getRawEncoding();
501327952Sdim  Append(reinterpret_cast<char *>(&Raw),
502327952Sdim         reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
503327952Sdim         Buffer, BufferSize, BufferCapacity);
504327952Sdim}
505341825Sdim
506341825Sdim/// Save a pointer to the given buffer.
507327952Sdimstatic void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
508327952Sdim                        unsigned &BufferCapacity) {
509327952Sdim  Append(reinterpret_cast<char *>(&Ptr),
510327952Sdim         reinterpret_cast<char *>(&Ptr) + sizeof(void *),
511327952Sdim         Buffer, BufferSize, BufferCapacity);
512221345Sdim}
513221345Sdim
514221345SdimNestedNameSpecifierLocBuilder::
515341825SdimNestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
516327952Sdim    : Representation(Other.Representation) {
517221345Sdim  if (!Other.Buffer)
518221345Sdim    return;
519341825Sdim
520221345Sdim  if (Other.BufferCapacity == 0) {
521221345Sdim    // Shallow copy is okay.
522221345Sdim    Buffer = Other.Buffer;
523221345Sdim    BufferSize = Other.BufferSize;
524221345Sdim    return;
525221345Sdim  }
526341825Sdim
527221345Sdim  // Deep copy
528276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
529276479Sdim         BufferCapacity);
530221345Sdim}
531221345Sdim
532221345SdimNestedNameSpecifierLocBuilder &
533221345SdimNestedNameSpecifierLocBuilder::
534221345Sdimoperator=(const NestedNameSpecifierLocBuilder &Other) {
535221345Sdim  Representation = Other.Representation;
536341825Sdim
537221345Sdim  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
538221345Sdim    // Re-use our storage.
539221345Sdim    BufferSize = Other.BufferSize;
540221345Sdim    memcpy(Buffer, Other.Buffer, BufferSize);
541221345Sdim    return *this;
542221345Sdim  }
543341825Sdim
544221345Sdim  // Free our storage, if we have any.
545221345Sdim  if (BufferCapacity) {
546221345Sdim    free(Buffer);
547221345Sdim    BufferCapacity = 0;
548221345Sdim  }
549341825Sdim
550221345Sdim  if (!Other.Buffer) {
551221345Sdim    // Empty.
552276479Sdim    Buffer = nullptr;
553221345Sdim    BufferSize = 0;
554221345Sdim    return *this;
555221345Sdim  }
556341825Sdim
557221345Sdim  if (Other.BufferCapacity == 0) {
558221345Sdim    // Shallow copy is okay.
559221345Sdim    Buffer = Other.Buffer;
560221345Sdim    BufferSize = Other.BufferSize;
561221345Sdim    return *this;
562221345Sdim  }
563341825Sdim
564221345Sdim  // Deep copy.
565344779Sdim  BufferSize = 0;
566276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
567276479Sdim         BufferCapacity);
568221345Sdim  return *this;
569221345Sdim}
570221345Sdim
571341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
572341825Sdim                                           SourceLocation TemplateKWLoc,
573341825Sdim                                           TypeLoc TL,
574221345Sdim                                           SourceLocation ColonColonLoc) {
575341825Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
576341825Sdim                                               TemplateKWLoc.isValid(),
577221345Sdim                                               TL.getTypePtr());
578341825Sdim
579221345Sdim  // Push source-location info into the buffer.
580221345Sdim  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
581221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
582221345Sdim}
583221345Sdim
584341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
585221345Sdim                                           IdentifierInfo *Identifier,
586341825Sdim                                           SourceLocation IdentifierLoc,
587221345Sdim                                           SourceLocation ColonColonLoc) {
588341825Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
589221345Sdim                                               Identifier);
590341825Sdim
591221345Sdim  // Push source-location info into the buffer.
592221345Sdim  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
593221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
594221345Sdim}
595221345Sdim
596341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
597221345Sdim                                           NamespaceDecl *Namespace,
598341825Sdim                                           SourceLocation NamespaceLoc,
599221345Sdim                                           SourceLocation ColonColonLoc) {
600341825Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
601221345Sdim                                               Namespace);
602341825Sdim
603221345Sdim  // Push source-location info into the buffer.
604221345Sdim  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
605221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
606221345Sdim}
607221345Sdim
608221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
609221345Sdim                                           NamespaceAliasDecl *Alias,
610341825Sdim                                           SourceLocation AliasLoc,
611221345Sdim                                           SourceLocation ColonColonLoc) {
612221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
613341825Sdim
614221345Sdim  // Push source-location info into the buffer.
615221345Sdim  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
616221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
617221345Sdim}
618221345Sdim
619341825Sdimvoid NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
620221345Sdim                                               SourceLocation ColonColonLoc) {
621221345Sdim  assert(!Representation && "Already have a nested-name-specifier!?");
622221345Sdim  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
623341825Sdim
624221345Sdim  // Push source-location info into the buffer.
625221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
626221345Sdim}
627221345Sdim
628280031Sdimvoid NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
629280031Sdim                                              CXXRecordDecl *RD,
630280031Sdim                                              SourceLocation SuperLoc,
631280031Sdim                                              SourceLocation ColonColonLoc) {
632280031Sdim  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
633280031Sdim
634280031Sdim  // Push source-location info into the buffer.
635280031Sdim  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
636280031Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
637280031Sdim}
638280031Sdim
639341825Sdimvoid NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
640341825Sdim                                                NestedNameSpecifier *Qualifier,
641221345Sdim                                                SourceRange R) {
642221345Sdim  Representation = Qualifier;
643341825Sdim
644341825Sdim  // Construct bogus (but well-formed) source information for the
645221345Sdim  // nested-name-specifier.
646221345Sdim  BufferSize = 0;
647226633Sdim  SmallVector<NestedNameSpecifier *, 4> Stack;
648221345Sdim  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
649221345Sdim    Stack.push_back(NNS);
650221345Sdim  while (!Stack.empty()) {
651261991Sdim    NestedNameSpecifier *NNS = Stack.pop_back_val();
652221345Sdim    switch (NNS->getKind()) {
653221345Sdim      case NestedNameSpecifier::Identifier:
654221345Sdim      case NestedNameSpecifier::Namespace:
655221345Sdim      case NestedNameSpecifier::NamespaceAlias:
656221345Sdim        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
657221345Sdim        break;
658341825Sdim
659221345Sdim      case NestedNameSpecifier::TypeSpec:
660221345Sdim      case NestedNameSpecifier::TypeSpecWithTemplate: {
661221345Sdim        TypeSourceInfo *TSInfo
662221345Sdim        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
663221345Sdim                                           R.getBegin());
664341825Sdim        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
665221345Sdim                    BufferCapacity);
666221345Sdim        break;
667221345Sdim      }
668341825Sdim
669221345Sdim      case NestedNameSpecifier::Global:
670280031Sdim      case NestedNameSpecifier::Super:
671221345Sdim        break;
672221345Sdim    }
673341825Sdim
674221345Sdim    // Save the location of the '::'.
675341825Sdim    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
676221345Sdim                       Buffer, BufferSize, BufferCapacity);
677221345Sdim  }
678221345Sdim}
679221345Sdim
680221345Sdimvoid NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
681221345Sdim  if (BufferCapacity)
682221345Sdim    free(Buffer);
683221345Sdim
684221345Sdim  if (!Other) {
685276479Sdim    Representation = nullptr;
686221345Sdim    BufferSize = 0;
687221345Sdim    return;
688221345Sdim  }
689341825Sdim
690341825Sdim  // Rather than copying the data (which is wasteful), "adopt" the
691221345Sdim  // pointer (which points into the ASTContext) but set the capacity to zero to
692221345Sdim  // indicate that we don't own it.
693221345Sdim  Representation = Other.getNestedNameSpecifier();
694221345Sdim  Buffer = static_cast<char *>(Other.getOpaqueData());
695221345Sdim  BufferSize = Other.getDataLength();
696221345Sdim  BufferCapacity = 0;
697221345Sdim}
698221345Sdim
699341825SdimNestedNameSpecifierLoc
700221345SdimNestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
701221345Sdim  if (!Representation)
702221345Sdim    return NestedNameSpecifierLoc();
703341825Sdim
704221345Sdim  // If we adopted our data pointer from elsewhere in the AST context, there's
705221345Sdim  // no need to copy the memory.
706221345Sdim  if (BufferCapacity == 0)
707221345Sdim    return NestedNameSpecifierLoc(Representation, Buffer);
708341825Sdim
709221345Sdim  // FIXME: After copying the source-location information, should we free
710221345Sdim  // our (temporary) buffer and adopt the ASTContext-allocated memory?
711221345Sdim  // Doing so would optimize repeated calls to getWithLocInContext().
712314564Sdim  void *Mem = Context.Allocate(BufferSize, alignof(void *));
713221345Sdim  memcpy(Mem, Buffer, BufferSize);
714221345Sdim  return NestedNameSpecifierLoc(Representation, Mem);
715221345Sdim}
716