NestedNameSpecifier.cpp revision 314564
1193326Sed//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=//
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//===----------------------------------------------------------------------===//
14193326Sed#include "clang/AST/NestedNameSpecifier.h"
15193326Sed#include "clang/AST/ASTContext.h"
16193326Sed#include "clang/AST/Decl.h"
17219077Sdim#include "clang/AST/DeclCXX.h"
18193326Sed#include "clang/AST/PrettyPrinter.h"
19193326Sed#include "clang/AST/Type.h"
20219077Sdim#include "clang/AST/TypeLoc.h"
21239462Sdim#include "llvm/Support/AlignOf.h"
22193326Sed#include "llvm/Support/raw_ostream.h"
23193326Sed#include <cassert>
24193326Sed
25193326Sedusing namespace clang;
26193326Sed
27193326SedNestedNameSpecifier *
28218893SdimNestedNameSpecifier::FindOrInsert(const ASTContext &Context,
29193326Sed                                  const NestedNameSpecifier &Mockup) {
30193326Sed  llvm::FoldingSetNodeID ID;
31193326Sed  Mockup.Profile(ID);
32193326Sed
33276479Sdim  void *InsertPos = nullptr;
34198092Srdivacky  NestedNameSpecifier *NNS
35193326Sed    = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
36193326Sed  if (!NNS) {
37314564Sdim    NNS =
38314564Sdim        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
39193326Sed    Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
40193326Sed  }
41193326Sed
42193326Sed  return NNS;
43193326Sed}
44193326Sed
45193326SedNestedNameSpecifier *
46218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
47218893Sdim                            NestedNameSpecifier *Prefix, IdentifierInfo *II) {
48193326Sed  assert(II && "Identifier cannot be NULL");
49198092Srdivacky  assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
50193326Sed
51193326Sed  NestedNameSpecifier Mockup;
52193326Sed  Mockup.Prefix.setPointer(Prefix);
53219077Sdim  Mockup.Prefix.setInt(StoredIdentifier);
54193326Sed  Mockup.Specifier = II;
55193326Sed  return FindOrInsert(Context, Mockup);
56193326Sed}
57193326Sed
58193326SedNestedNameSpecifier *
59218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
60249423Sdim                            NestedNameSpecifier *Prefix,
61249423Sdim                            const NamespaceDecl *NS) {
62193326Sed  assert(NS && "Namespace cannot be NULL");
63198092Srdivacky  assert((!Prefix ||
64276479Sdim          (Prefix->getAsType() == nullptr &&
65276479Sdim           Prefix->getAsIdentifier() == nullptr)) &&
66193326Sed         "Broken nested name specifier");
67193326Sed  NestedNameSpecifier Mockup;
68193326Sed  Mockup.Prefix.setPointer(Prefix);
69280031Sdim  Mockup.Prefix.setInt(StoredDecl);
70249423Sdim  Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
71193326Sed  return FindOrInsert(Context, Mockup);
72193326Sed}
73193326Sed
74193326SedNestedNameSpecifier *
75218893SdimNestedNameSpecifier::Create(const ASTContext &Context,
76219077Sdim                            NestedNameSpecifier *Prefix,
77219077Sdim                            NamespaceAliasDecl *Alias) {
78219077Sdim  assert(Alias && "Namespace alias cannot be NULL");
79219077Sdim  assert((!Prefix ||
80276479Sdim          (Prefix->getAsType() == nullptr &&
81276479Sdim           Prefix->getAsIdentifier() == nullptr)) &&
82219077Sdim         "Broken nested name specifier");
83219077Sdim  NestedNameSpecifier Mockup;
84219077Sdim  Mockup.Prefix.setPointer(Prefix);
85280031Sdim  Mockup.Prefix.setInt(StoredDecl);
86219077Sdim  Mockup.Specifier = Alias;
87219077Sdim  return FindOrInsert(Context, Mockup);
88219077Sdim}
89219077Sdim
90219077SdimNestedNameSpecifier *
91219077SdimNestedNameSpecifier::Create(const ASTContext &Context,
92218893Sdim                            NestedNameSpecifier *Prefix,
93218893Sdim                            bool Template, const Type *T) {
94193326Sed  assert(T && "Type cannot be NULL");
95193326Sed  NestedNameSpecifier Mockup;
96193326Sed  Mockup.Prefix.setPointer(Prefix);
97219077Sdim  Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
98218893Sdim  Mockup.Specifier = const_cast<Type*>(T);
99193326Sed  return FindOrInsert(Context, Mockup);
100193326Sed}
101198092Srdivacky
102198092SrdivackyNestedNameSpecifier *
103218893SdimNestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
104198092Srdivacky  assert(II && "Identifier cannot be NULL");
105198092Srdivacky  NestedNameSpecifier Mockup;
106276479Sdim  Mockup.Prefix.setPointer(nullptr);
107219077Sdim  Mockup.Prefix.setInt(StoredIdentifier);
108198092Srdivacky  Mockup.Specifier = II;
109198092Srdivacky  return FindOrInsert(Context, Mockup);
110198092Srdivacky}
111198092Srdivacky
112218893SdimNestedNameSpecifier *
113218893SdimNestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
114193326Sed  if (!Context.GlobalNestedNameSpecifier)
115239462Sdim    Context.GlobalNestedNameSpecifier =
116314564Sdim        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
117193326Sed  return Context.GlobalNestedNameSpecifier;
118193326Sed}
119193326Sed
120280031SdimNestedNameSpecifier *
121280031SdimNestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
122280031Sdim                                    CXXRecordDecl *RD) {
123280031Sdim  NestedNameSpecifier Mockup;
124280031Sdim  Mockup.Prefix.setPointer(nullptr);
125280031Sdim  Mockup.Prefix.setInt(StoredDecl);
126280031Sdim  Mockup.Specifier = RD;
127280031Sdim  return FindOrInsert(Context, Mockup);
128280031Sdim}
129280031Sdim
130219077SdimNestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
131276479Sdim  if (!Specifier)
132219077Sdim    return Global;
133219077Sdim
134219077Sdim  switch (Prefix.getInt()) {
135219077Sdim  case StoredIdentifier:
136219077Sdim    return Identifier;
137219077Sdim
138280031Sdim  case StoredDecl: {
139280031Sdim    NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
140280031Sdim    if (isa<CXXRecordDecl>(ND))
141280031Sdim      return Super;
142280031Sdim    return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
143280031Sdim  }
144219077Sdim
145219077Sdim  case StoredTypeSpec:
146219077Sdim    return TypeSpec;
147219077Sdim
148219077Sdim  case StoredTypeSpecWithTemplate:
149219077Sdim    return TypeSpecWithTemplate;
150219077Sdim  }
151219077Sdim
152234353Sdim  llvm_unreachable("Invalid NNS Kind!");
153219077Sdim}
154219077Sdim
155280031Sdim/// \brief Retrieve the namespace stored in this nested name specifier.
156219077SdimNamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
157314564Sdim  if (Prefix.getInt() == StoredDecl)
158219077Sdim    return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
159219077Sdim
160276479Sdim  return nullptr;
161219077Sdim}
162219077Sdim
163280031Sdim/// \brief Retrieve the namespace alias stored in this nested name specifier.
164219077SdimNamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
165314564Sdim  if (Prefix.getInt() == StoredDecl)
166219077Sdim    return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
167219077Sdim
168276479Sdim  return nullptr;
169219077Sdim}
170219077Sdim
171280031Sdim/// \brief Retrieve the record declaration stored in this nested name specifier.
172280031SdimCXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
173309124Sdim  switch (Prefix.getInt()) {
174309124Sdim  case StoredIdentifier:
175309124Sdim    return nullptr;
176309124Sdim
177309124Sdim  case StoredDecl:
178280031Sdim    return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
179219077Sdim
180309124Sdim  case StoredTypeSpec:
181309124Sdim  case StoredTypeSpecWithTemplate:
182309124Sdim    return getAsType()->getAsCXXRecordDecl();
183309124Sdim  }
184309124Sdim
185309124Sdim  llvm_unreachable("Invalid NNS Kind!");
186280031Sdim}
187280031Sdim
188193326Sed/// \brief Whether this nested name specifier refers to a dependent
189193326Sed/// type or not.
190193326Sedbool NestedNameSpecifier::isDependent() const {
191193326Sed  switch (getKind()) {
192193326Sed  case Identifier:
193193326Sed    // Identifier specifiers always represent dependent types
194193326Sed    return true;
195193326Sed
196193326Sed  case Namespace:
197219077Sdim  case NamespaceAlias:
198193326Sed  case Global:
199193326Sed    return false;
200193326Sed
201280031Sdim  case Super: {
202280031Sdim    CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
203280031Sdim    for (const auto &Base : RD->bases())
204280031Sdim      if (Base.getType()->isDependentType())
205280031Sdim        return true;
206280031Sdim
207280031Sdim    return false;
208280031Sdim  }
209280031Sdim
210193326Sed  case TypeSpec:
211193326Sed  case TypeSpecWithTemplate:
212193326Sed    return getAsType()->isDependentType();
213193326Sed  }
214193326Sed
215234353Sdim  llvm_unreachable("Invalid NNS Kind!");
216193326Sed}
217193326Sed
218224145Sdim/// \brief Whether this nested name specifier refers to a dependent
219224145Sdim/// type or not.
220224145Sdimbool NestedNameSpecifier::isInstantiationDependent() const {
221224145Sdim  switch (getKind()) {
222224145Sdim  case Identifier:
223224145Sdim    // Identifier specifiers always represent dependent types
224224145Sdim    return true;
225224145Sdim
226224145Sdim  case Namespace:
227224145Sdim  case NamespaceAlias:
228224145Sdim  case Global:
229280031Sdim  case Super:
230224145Sdim    return false;
231280031Sdim
232224145Sdim  case TypeSpec:
233224145Sdim  case TypeSpecWithTemplate:
234224145Sdim    return getAsType()->isInstantiationDependentType();
235224145Sdim  }
236234353Sdim
237234353Sdim  llvm_unreachable("Invalid NNS Kind!");
238224145Sdim}
239224145Sdim
240218893Sdimbool NestedNameSpecifier::containsUnexpandedParameterPack() const {
241218893Sdim  switch (getKind()) {
242218893Sdim  case Identifier:
243218893Sdim    return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
244218893Sdim
245218893Sdim  case Namespace:
246219077Sdim  case NamespaceAlias:
247218893Sdim  case Global:
248280031Sdim  case Super:
249218893Sdim    return false;
250218893Sdim
251218893Sdim  case TypeSpec:
252218893Sdim  case TypeSpecWithTemplate:
253218893Sdim    return getAsType()->containsUnexpandedParameterPack();
254218893Sdim  }
255218893Sdim
256234353Sdim  llvm_unreachable("Invalid NNS Kind!");
257218893Sdim}
258218893Sdim
259193326Sed/// \brief Print this nested name specifier to the given output
260193326Sed/// stream.
261198092Srdivackyvoid
262226633SdimNestedNameSpecifier::print(raw_ostream &OS,
263193326Sed                           const PrintingPolicy &Policy) const {
264193326Sed  if (getPrefix())
265193326Sed    getPrefix()->print(OS, Policy);
266193326Sed
267193326Sed  switch (getKind()) {
268193326Sed  case Identifier:
269193326Sed    OS << getAsIdentifier()->getName();
270193326Sed    break;
271193326Sed
272193326Sed  case Namespace:
273234353Sdim    if (getAsNamespace()->isAnonymousNamespace())
274234353Sdim      return;
275234353Sdim
276219077Sdim    OS << getAsNamespace()->getName();
277193326Sed    break;
278193326Sed
279219077Sdim  case NamespaceAlias:
280219077Sdim    OS << getAsNamespaceAlias()->getName();
281219077Sdim    break;
282219077Sdim
283193326Sed  case Global:
284193326Sed    break;
285193326Sed
286280031Sdim  case Super:
287280031Sdim    OS << "__super";
288280031Sdim    break;
289280031Sdim
290193326Sed  case TypeSpecWithTemplate:
291193326Sed    OS << "template ";
292193326Sed    // Fall through to print the type.
293193326Sed
294193326Sed  case TypeSpec: {
295218893Sdim    const Type *T = getAsType();
296193326Sed
297193326Sed    PrintingPolicy InnerPolicy(Policy);
298198092Srdivacky    InnerPolicy.SuppressScope = true;
299198092Srdivacky
300198092Srdivacky    // Nested-name-specifiers are intended to contain minimally-qualified
301208600Srdivacky    // types. An actual ElaboratedType will not occur, since we'll store
302198092Srdivacky    // just the type that is referred to in the nested-name-specifier (e.g.,
303198092Srdivacky    // a TypedefType, TagType, etc.). However, when we are dealing with
304198092Srdivacky    // dependent template-id types (e.g., Outer<T>::template Inner<U>),
305198092Srdivacky    // the type requires its own nested-name-specifier for uniqueness, so we
306198092Srdivacky    // suppress that nested-name-specifier during printing.
307208600Srdivacky    assert(!isa<ElaboratedType>(T) &&
308208600Srdivacky           "Elaborated type in nested-name-specifier");
309198092Srdivacky    if (const TemplateSpecializationType *SpecType
310198092Srdivacky          = dyn_cast<TemplateSpecializationType>(T)) {
311198092Srdivacky      // Print the template name without its corresponding
312198092Srdivacky      // nested-name-specifier.
313198092Srdivacky      SpecType->getTemplateName().print(OS, InnerPolicy, true);
314198092Srdivacky
315198092Srdivacky      // Print the template argument list.
316249423Sdim      TemplateSpecializationType::PrintTemplateArgumentList(
317309124Sdim          OS, SpecType->template_arguments(), InnerPolicy);
318198092Srdivacky    } else {
319198092Srdivacky      // Print the type normally
320249423Sdim      QualType(T, 0).print(OS, InnerPolicy);
321198092Srdivacky    }
322193326Sed    break;
323193326Sed  }
324193326Sed  }
325193326Sed
326193326Sed  OS << "::";
327193326Sed}
328193326Sed
329296417Sdimvoid NestedNameSpecifier::dump(const LangOptions &LO) const {
330195341Sed  print(llvm::errs(), PrintingPolicy(LO));
331193326Sed}
332219077Sdim
333309124SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump() const {
334296417Sdim  LangOptions LO;
335296417Sdim  print(llvm::errs(), PrintingPolicy(LO));
336296417Sdim}
337296417Sdim
338219077Sdimunsigned
339219077SdimNestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
340219077Sdim  assert(Qualifier && "Expected a non-NULL qualifier");
341219077Sdim
342219077Sdim  // Location of the trailing '::'.
343219077Sdim  unsigned Length = sizeof(unsigned);
344219077Sdim
345219077Sdim  switch (Qualifier->getKind()) {
346219077Sdim  case NestedNameSpecifier::Global:
347219077Sdim    // Nothing more to add.
348219077Sdim    break;
349219077Sdim
350219077Sdim  case NestedNameSpecifier::Identifier:
351219077Sdim  case NestedNameSpecifier::Namespace:
352219077Sdim  case NestedNameSpecifier::NamespaceAlias:
353280031Sdim  case NestedNameSpecifier::Super:
354219077Sdim    // The location of the identifier or namespace name.
355219077Sdim    Length += sizeof(unsigned);
356219077Sdim    break;
357219077Sdim
358219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
359219077Sdim  case NestedNameSpecifier::TypeSpec:
360219077Sdim    // The "void*" that points at the TypeLoc data.
361219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
362219077Sdim    Length += sizeof(void *);
363219077Sdim    break;
364219077Sdim  }
365219077Sdim
366219077Sdim  return Length;
367219077Sdim}
368219077Sdim
369219077Sdimunsigned
370219077SdimNestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
371219077Sdim  unsigned Length = 0;
372219077Sdim  for (; Qualifier; Qualifier = Qualifier->getPrefix())
373219077Sdim    Length += getLocalDataLength(Qualifier);
374219077Sdim  return Length;
375219077Sdim}
376219077Sdim
377219077Sdimnamespace {
378219077Sdim  /// \brief Load a (possibly unaligned) source location from a given address
379219077Sdim  /// and offset.
380219077Sdim  SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
381219077Sdim    unsigned Raw;
382219077Sdim    memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
383219077Sdim    return SourceLocation::getFromRawEncoding(Raw);
384219077Sdim  }
385219077Sdim
386219077Sdim  /// \brief Load a (possibly unaligned) pointer from a given address and
387219077Sdim  /// offset.
388219077Sdim  void *LoadPointer(void *Data, unsigned Offset) {
389219077Sdim    void *Result;
390219077Sdim    memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
391219077Sdim    return Result;
392219077Sdim  }
393219077Sdim}
394219077Sdim
395219077SdimSourceRange NestedNameSpecifierLoc::getSourceRange() const {
396219077Sdim  if (!Qualifier)
397219077Sdim    return SourceRange();
398219077Sdim
399219077Sdim  NestedNameSpecifierLoc First = *this;
400219077Sdim  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
401219077Sdim    First = Prefix;
402219077Sdim
403219077Sdim  return SourceRange(First.getLocalSourceRange().getBegin(),
404219077Sdim                     getLocalSourceRange().getEnd());
405219077Sdim}
406219077Sdim
407219077SdimSourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
408219077Sdim  if (!Qualifier)
409219077Sdim    return SourceRange();
410219077Sdim
411219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
412219077Sdim  switch (Qualifier->getKind()) {
413219077Sdim  case NestedNameSpecifier::Global:
414219077Sdim    return LoadSourceLocation(Data, Offset);
415219077Sdim
416219077Sdim  case NestedNameSpecifier::Identifier:
417219077Sdim  case NestedNameSpecifier::Namespace:
418219077Sdim  case NestedNameSpecifier::NamespaceAlias:
419280031Sdim  case NestedNameSpecifier::Super:
420219077Sdim    return SourceRange(LoadSourceLocation(Data, Offset),
421219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
422219077Sdim
423219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
424219077Sdim  case NestedNameSpecifier::TypeSpec: {
425219077Sdim    // The "void*" that points at the TypeLoc data.
426219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
427219077Sdim    void *TypeData = LoadPointer(Data, Offset);
428219077Sdim    TypeLoc TL(Qualifier->getAsType(), TypeData);
429219077Sdim    return SourceRange(TL.getBeginLoc(),
430219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(void*)));
431219077Sdim  }
432219077Sdim  }
433234353Sdim
434234353Sdim  llvm_unreachable("Invalid NNS Kind!");
435219077Sdim}
436219077Sdim
437219077SdimTypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
438219077Sdim  assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec ||
439219077Sdim          Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) &&
440219077Sdim         "Nested-name-specifier location is not a type");
441219077Sdim
442219077Sdim  // The "void*" that points at the TypeLoc data.
443219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
444219077Sdim  void *TypeData = LoadPointer(Data, Offset);
445219077Sdim  return TypeLoc(Qualifier->getAsType(), TypeData);
446219077Sdim}
447221345Sdim
448221345Sdimnamespace {
449221345Sdim  void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
450221345Sdim              unsigned &BufferCapacity) {
451288943Sdim    if (Start == End)
452288943Sdim      return;
453288943Sdim
454221345Sdim    if (BufferSize + (End - Start) > BufferCapacity) {
455221345Sdim      // Reallocate the buffer.
456288943Sdim      unsigned NewCapacity = std::max(
457288943Sdim          (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
458288943Sdim          (unsigned)(BufferSize + (End - Start)));
459221345Sdim      char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
460288943Sdim      if (BufferCapacity) {
461288943Sdim        memcpy(NewBuffer, Buffer, BufferSize);
462221345Sdim        free(Buffer);
463288943Sdim      }
464221345Sdim      Buffer = NewBuffer;
465221345Sdim      BufferCapacity = NewCapacity;
466221345Sdim    }
467221345Sdim
468221345Sdim    memcpy(Buffer + BufferSize, Start, End - Start);
469221345Sdim    BufferSize += End-Start;
470221345Sdim  }
471221345Sdim
472221345Sdim  /// \brief Save a source location to the given buffer.
473221345Sdim  void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
474221345Sdim                          unsigned &BufferSize, unsigned &BufferCapacity) {
475221345Sdim    unsigned Raw = Loc.getRawEncoding();
476221345Sdim    Append(reinterpret_cast<char *>(&Raw),
477221345Sdim           reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
478221345Sdim           Buffer, BufferSize, BufferCapacity);
479221345Sdim  }
480221345Sdim
481221345Sdim  /// \brief Save a pointer to the given buffer.
482221345Sdim  void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
483221345Sdim                   unsigned &BufferCapacity) {
484221345Sdim    Append(reinterpret_cast<char *>(&Ptr),
485221345Sdim           reinterpret_cast<char *>(&Ptr) + sizeof(void *),
486221345Sdim           Buffer, BufferSize, BufferCapacity);
487221345Sdim  }
488221345Sdim}
489221345Sdim
490221345SdimNestedNameSpecifierLocBuilder::
491221345SdimNestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
492276479Sdim  : Representation(Other.Representation), Buffer(nullptr),
493221345Sdim    BufferSize(0), BufferCapacity(0)
494221345Sdim{
495221345Sdim  if (!Other.Buffer)
496221345Sdim    return;
497221345Sdim
498221345Sdim  if (Other.BufferCapacity == 0) {
499221345Sdim    // Shallow copy is okay.
500221345Sdim    Buffer = Other.Buffer;
501221345Sdim    BufferSize = Other.BufferSize;
502221345Sdim    return;
503221345Sdim  }
504221345Sdim
505221345Sdim  // Deep copy
506276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
507276479Sdim         BufferCapacity);
508221345Sdim}
509221345Sdim
510221345SdimNestedNameSpecifierLocBuilder &
511221345SdimNestedNameSpecifierLocBuilder::
512221345Sdimoperator=(const NestedNameSpecifierLocBuilder &Other) {
513221345Sdim  Representation = Other.Representation;
514221345Sdim
515221345Sdim  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
516221345Sdim    // Re-use our storage.
517221345Sdim    BufferSize = Other.BufferSize;
518221345Sdim    memcpy(Buffer, Other.Buffer, BufferSize);
519221345Sdim    return *this;
520221345Sdim  }
521221345Sdim
522221345Sdim  // Free our storage, if we have any.
523221345Sdim  if (BufferCapacity) {
524221345Sdim    free(Buffer);
525221345Sdim    BufferCapacity = 0;
526221345Sdim  }
527221345Sdim
528221345Sdim  if (!Other.Buffer) {
529221345Sdim    // Empty.
530276479Sdim    Buffer = nullptr;
531221345Sdim    BufferSize = 0;
532221345Sdim    return *this;
533221345Sdim  }
534221345Sdim
535221345Sdim  if (Other.BufferCapacity == 0) {
536221345Sdim    // Shallow copy is okay.
537221345Sdim    Buffer = Other.Buffer;
538221345Sdim    BufferSize = Other.BufferSize;
539221345Sdim    return *this;
540221345Sdim  }
541221345Sdim
542221345Sdim  // Deep copy.
543276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
544276479Sdim         BufferCapacity);
545221345Sdim  return *this;
546221345Sdim}
547221345Sdim
548221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
549221345Sdim                                           SourceLocation TemplateKWLoc,
550221345Sdim                                           TypeLoc TL,
551221345Sdim                                           SourceLocation ColonColonLoc) {
552221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
553221345Sdim                                               TemplateKWLoc.isValid(),
554221345Sdim                                               TL.getTypePtr());
555221345Sdim
556221345Sdim  // Push source-location info into the buffer.
557221345Sdim  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
558221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
559221345Sdim}
560221345Sdim
561221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
562221345Sdim                                           IdentifierInfo *Identifier,
563221345Sdim                                           SourceLocation IdentifierLoc,
564221345Sdim                                           SourceLocation ColonColonLoc) {
565221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
566221345Sdim                                               Identifier);
567221345Sdim
568221345Sdim  // Push source-location info into the buffer.
569221345Sdim  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
570221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
571221345Sdim}
572221345Sdim
573221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
574221345Sdim                                           NamespaceDecl *Namespace,
575221345Sdim                                           SourceLocation NamespaceLoc,
576221345Sdim                                           SourceLocation ColonColonLoc) {
577221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
578221345Sdim                                               Namespace);
579221345Sdim
580221345Sdim  // Push source-location info into the buffer.
581221345Sdim  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
582221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
583221345Sdim}
584221345Sdim
585221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
586221345Sdim                                           NamespaceAliasDecl *Alias,
587221345Sdim                                           SourceLocation AliasLoc,
588221345Sdim                                           SourceLocation ColonColonLoc) {
589221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
590221345Sdim
591221345Sdim  // Push source-location info into the buffer.
592221345Sdim  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
593221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
594221345Sdim}
595221345Sdim
596221345Sdimvoid NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
597221345Sdim                                               SourceLocation ColonColonLoc) {
598221345Sdim  assert(!Representation && "Already have a nested-name-specifier!?");
599221345Sdim  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
600221345Sdim
601221345Sdim  // Push source-location info into the buffer.
602221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
603221345Sdim}
604221345Sdim
605280031Sdimvoid NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
606280031Sdim                                              CXXRecordDecl *RD,
607280031Sdim                                              SourceLocation SuperLoc,
608280031Sdim                                              SourceLocation ColonColonLoc) {
609280031Sdim  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
610280031Sdim
611280031Sdim  // Push source-location info into the buffer.
612280031Sdim  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
613280031Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
614280031Sdim}
615280031Sdim
616221345Sdimvoid NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
617221345Sdim                                                NestedNameSpecifier *Qualifier,
618221345Sdim                                                SourceRange R) {
619221345Sdim  Representation = Qualifier;
620221345Sdim
621221345Sdim  // Construct bogus (but well-formed) source information for the
622221345Sdim  // nested-name-specifier.
623221345Sdim  BufferSize = 0;
624226633Sdim  SmallVector<NestedNameSpecifier *, 4> Stack;
625221345Sdim  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
626221345Sdim    Stack.push_back(NNS);
627221345Sdim  while (!Stack.empty()) {
628261991Sdim    NestedNameSpecifier *NNS = Stack.pop_back_val();
629221345Sdim    switch (NNS->getKind()) {
630221345Sdim      case NestedNameSpecifier::Identifier:
631221345Sdim      case NestedNameSpecifier::Namespace:
632221345Sdim      case NestedNameSpecifier::NamespaceAlias:
633221345Sdim        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
634221345Sdim        break;
635221345Sdim
636221345Sdim      case NestedNameSpecifier::TypeSpec:
637221345Sdim      case NestedNameSpecifier::TypeSpecWithTemplate: {
638221345Sdim        TypeSourceInfo *TSInfo
639221345Sdim        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
640221345Sdim                                           R.getBegin());
641221345Sdim        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
642221345Sdim                    BufferCapacity);
643221345Sdim        break;
644221345Sdim      }
645221345Sdim
646221345Sdim      case NestedNameSpecifier::Global:
647280031Sdim      case NestedNameSpecifier::Super:
648221345Sdim        break;
649221345Sdim    }
650221345Sdim
651221345Sdim    // Save the location of the '::'.
652221345Sdim    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
653221345Sdim                       Buffer, BufferSize, BufferCapacity);
654221345Sdim  }
655221345Sdim}
656221345Sdim
657221345Sdimvoid NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
658221345Sdim  if (BufferCapacity)
659221345Sdim    free(Buffer);
660221345Sdim
661221345Sdim  if (!Other) {
662276479Sdim    Representation = nullptr;
663221345Sdim    BufferSize = 0;
664221345Sdim    return;
665221345Sdim  }
666221345Sdim
667221345Sdim  // Rather than copying the data (which is wasteful), "adopt" the
668221345Sdim  // pointer (which points into the ASTContext) but set the capacity to zero to
669221345Sdim  // indicate that we don't own it.
670221345Sdim  Representation = Other.getNestedNameSpecifier();
671221345Sdim  Buffer = static_cast<char *>(Other.getOpaqueData());
672221345Sdim  BufferSize = Other.getDataLength();
673221345Sdim  BufferCapacity = 0;
674221345Sdim}
675221345Sdim
676221345SdimNestedNameSpecifierLoc
677221345SdimNestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
678221345Sdim  if (!Representation)
679221345Sdim    return NestedNameSpecifierLoc();
680221345Sdim
681221345Sdim  // If we adopted our data pointer from elsewhere in the AST context, there's
682221345Sdim  // no need to copy the memory.
683221345Sdim  if (BufferCapacity == 0)
684221345Sdim    return NestedNameSpecifierLoc(Representation, Buffer);
685221345Sdim
686221345Sdim  // FIXME: After copying the source-location information, should we free
687221345Sdim  // our (temporary) buffer and adopt the ASTContext-allocated memory?
688221345Sdim  // Doing so would optimize repeated calls to getWithLocInContext().
689314564Sdim  void *Mem = Context.Allocate(BufferSize, alignof(void *));
690221345Sdim  memcpy(Mem, Buffer, BufferSize);
691221345Sdim  return NestedNameSpecifierLoc(Representation, Mem);
692221345Sdim}
693