NestedNameSpecifier.cpp revision 327952
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"
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,
88219077Sdim                            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
167280031Sdim/// \brief 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
175280031Sdim/// \brief 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
183280031Sdim/// \brief 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
200193326Sed/// \brief 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
230224145Sdim/// \brief 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;
237224145Sdim
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
271193326Sed/// \brief Print this nested name specifier to the given output
272193326Sed/// stream.
273198092Srdivackyvoid
274226633SdimNestedNameSpecifier::print(raw_ostream &OS,
275193326Sed                           const PrintingPolicy &Policy) 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;
287234353Sdim
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: {
308218893Sdim    const Type *T = getAsType();
309193326Sed
310193326Sed    PrintingPolicy InnerPolicy(Policy);
311198092Srdivacky    InnerPolicy.SuppressScope = true;
312198092Srdivacky
313198092Srdivacky    // Nested-name-specifiers are intended to contain minimally-qualified
314208600Srdivacky    // types. An actual ElaboratedType will not occur, since we'll store
315198092Srdivacky    // just the type that is referred to in the nested-name-specifier (e.g.,
316198092Srdivacky    // a TypedefType, TagType, etc.). However, when we are dealing with
317198092Srdivacky    // dependent template-id types (e.g., Outer<T>::template Inner<U>),
318198092Srdivacky    // the type requires its own nested-name-specifier for uniqueness, so we
319198092Srdivacky    // suppress that nested-name-specifier during printing.
320208600Srdivacky    assert(!isa<ElaboratedType>(T) &&
321208600Srdivacky           "Elaborated type in nested-name-specifier");
322198092Srdivacky    if (const TemplateSpecializationType *SpecType
323198092Srdivacky          = dyn_cast<TemplateSpecializationType>(T)) {
324198092Srdivacky      // Print the template name without its corresponding
325198092Srdivacky      // nested-name-specifier.
326198092Srdivacky      SpecType->getTemplateName().print(OS, InnerPolicy, true);
327198092Srdivacky
328198092Srdivacky      // Print the template argument list.
329327952Sdim      printTemplateArgumentList(OS, SpecType->template_arguments(),
330327952Sdim                                InnerPolicy);
331198092Srdivacky    } else {
332198092Srdivacky      // Print the type normally
333249423Sdim      QualType(T, 0).print(OS, InnerPolicy);
334198092Srdivacky    }
335193326Sed    break;
336193326Sed  }
337193326Sed  }
338193326Sed
339193326Sed  OS << "::";
340193326Sed}
341193326Sed
342296417Sdimvoid NestedNameSpecifier::dump(const LangOptions &LO) const {
343195341Sed  print(llvm::errs(), PrintingPolicy(LO));
344193326Sed}
345219077Sdim
346309124SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump() const {
347296417Sdim  LangOptions LO;
348296417Sdim  print(llvm::errs(), PrintingPolicy(LO));
349296417Sdim}
350296417Sdim
351219077Sdimunsigned
352219077SdimNestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
353219077Sdim  assert(Qualifier && "Expected a non-NULL qualifier");
354219077Sdim
355219077Sdim  // Location of the trailing '::'.
356219077Sdim  unsigned Length = sizeof(unsigned);
357219077Sdim
358219077Sdim  switch (Qualifier->getKind()) {
359219077Sdim  case NestedNameSpecifier::Global:
360219077Sdim    // Nothing more to add.
361219077Sdim    break;
362219077Sdim
363219077Sdim  case NestedNameSpecifier::Identifier:
364219077Sdim  case NestedNameSpecifier::Namespace:
365219077Sdim  case NestedNameSpecifier::NamespaceAlias:
366280031Sdim  case NestedNameSpecifier::Super:
367219077Sdim    // The location of the identifier or namespace name.
368219077Sdim    Length += sizeof(unsigned);
369219077Sdim    break;
370219077Sdim
371219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
372219077Sdim  case NestedNameSpecifier::TypeSpec:
373219077Sdim    // The "void*" that points at the TypeLoc data.
374219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
375219077Sdim    Length += sizeof(void *);
376219077Sdim    break;
377219077Sdim  }
378219077Sdim
379219077Sdim  return Length;
380219077Sdim}
381219077Sdim
382219077Sdimunsigned
383219077SdimNestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
384219077Sdim  unsigned Length = 0;
385219077Sdim  for (; Qualifier; Qualifier = Qualifier->getPrefix())
386219077Sdim    Length += getLocalDataLength(Qualifier);
387219077Sdim  return Length;
388219077Sdim}
389219077Sdim
390327952Sdim/// \brief Load a (possibly unaligned) source location from a given address
391327952Sdim/// and offset.
392327952Sdimstatic SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
393327952Sdim  unsigned Raw;
394327952Sdim  memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
395327952Sdim  return SourceLocation::getFromRawEncoding(Raw);
396327952Sdim}
397219077Sdim
398327952Sdim/// \brief Load a (possibly unaligned) pointer from a given address and
399327952Sdim/// offset.
400327952Sdimstatic void *LoadPointer(void *Data, unsigned Offset) {
401327952Sdim  void *Result;
402327952Sdim  memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
403327952Sdim  return Result;
404219077Sdim}
405219077Sdim
406219077SdimSourceRange NestedNameSpecifierLoc::getSourceRange() const {
407219077Sdim  if (!Qualifier)
408219077Sdim    return SourceRange();
409219077Sdim
410219077Sdim  NestedNameSpecifierLoc First = *this;
411219077Sdim  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
412219077Sdim    First = Prefix;
413219077Sdim
414219077Sdim  return SourceRange(First.getLocalSourceRange().getBegin(),
415219077Sdim                     getLocalSourceRange().getEnd());
416219077Sdim}
417219077Sdim
418219077SdimSourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
419219077Sdim  if (!Qualifier)
420219077Sdim    return SourceRange();
421219077Sdim
422219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
423219077Sdim  switch (Qualifier->getKind()) {
424219077Sdim  case NestedNameSpecifier::Global:
425219077Sdim    return LoadSourceLocation(Data, Offset);
426219077Sdim
427219077Sdim  case NestedNameSpecifier::Identifier:
428219077Sdim  case NestedNameSpecifier::Namespace:
429219077Sdim  case NestedNameSpecifier::NamespaceAlias:
430280031Sdim  case NestedNameSpecifier::Super:
431219077Sdim    return SourceRange(LoadSourceLocation(Data, Offset),
432219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
433219077Sdim
434219077Sdim  case NestedNameSpecifier::TypeSpecWithTemplate:
435219077Sdim  case NestedNameSpecifier::TypeSpec: {
436219077Sdim    // The "void*" that points at the TypeLoc data.
437219077Sdim    // Note: the 'template' keyword is part of the TypeLoc.
438219077Sdim    void *TypeData = LoadPointer(Data, Offset);
439219077Sdim    TypeLoc TL(Qualifier->getAsType(), TypeData);
440219077Sdim    return SourceRange(TL.getBeginLoc(),
441219077Sdim                       LoadSourceLocation(Data, Offset + sizeof(void*)));
442219077Sdim  }
443219077Sdim  }
444234353Sdim
445234353Sdim  llvm_unreachable("Invalid NNS Kind!");
446219077Sdim}
447219077Sdim
448219077SdimTypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
449219077Sdim  assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec ||
450219077Sdim          Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) &&
451219077Sdim         "Nested-name-specifier location is not a type");
452219077Sdim
453219077Sdim  // The "void*" that points at the TypeLoc data.
454219077Sdim  unsigned Offset = getDataLength(Qualifier->getPrefix());
455219077Sdim  void *TypeData = LoadPointer(Data, Offset);
456219077Sdim  return TypeLoc(Qualifier->getAsType(), TypeData);
457219077Sdim}
458221345Sdim
459327952Sdimstatic void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
460221345Sdim              unsigned &BufferCapacity) {
461327952Sdim  if (Start == End)
462327952Sdim    return;
463288943Sdim
464327952Sdim  if (BufferSize + (End - Start) > BufferCapacity) {
465327952Sdim    // Reallocate the buffer.
466327952Sdim    unsigned NewCapacity = std::max(
467327952Sdim        (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
468327952Sdim        (unsigned)(BufferSize + (End - Start)));
469327952Sdim    char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
470327952Sdim    if (BufferCapacity) {
471327952Sdim      memcpy(NewBuffer, Buffer, BufferSize);
472327952Sdim      free(Buffer);
473221345Sdim    }
474327952Sdim    Buffer = NewBuffer;
475327952Sdim    BufferCapacity = NewCapacity;
476221345Sdim  }
477327952Sdim
478327952Sdim  memcpy(Buffer + BufferSize, Start, End - Start);
479327952Sdim  BufferSize += End-Start;
480327952Sdim}
481221345Sdim
482327952Sdim/// \brief Save a source location to the given buffer.
483327952Sdimstatic void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
484327952Sdim                               unsigned &BufferSize, unsigned &BufferCapacity) {
485327952Sdim  unsigned Raw = Loc.getRawEncoding();
486327952Sdim  Append(reinterpret_cast<char *>(&Raw),
487327952Sdim         reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
488327952Sdim         Buffer, BufferSize, BufferCapacity);
489327952Sdim}
490221345Sdim
491327952Sdim/// \brief Save a pointer to the given buffer.
492327952Sdimstatic void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
493327952Sdim                        unsigned &BufferCapacity) {
494327952Sdim  Append(reinterpret_cast<char *>(&Ptr),
495327952Sdim         reinterpret_cast<char *>(&Ptr) + sizeof(void *),
496327952Sdim         Buffer, BufferSize, BufferCapacity);
497221345Sdim}
498221345Sdim
499221345SdimNestedNameSpecifierLocBuilder::
500221345SdimNestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
501327952Sdim    : Representation(Other.Representation) {
502221345Sdim  if (!Other.Buffer)
503221345Sdim    return;
504221345Sdim
505221345Sdim  if (Other.BufferCapacity == 0) {
506221345Sdim    // Shallow copy is okay.
507221345Sdim    Buffer = Other.Buffer;
508221345Sdim    BufferSize = Other.BufferSize;
509221345Sdim    return;
510221345Sdim  }
511221345Sdim
512221345Sdim  // Deep copy
513276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
514276479Sdim         BufferCapacity);
515221345Sdim}
516221345Sdim
517221345SdimNestedNameSpecifierLocBuilder &
518221345SdimNestedNameSpecifierLocBuilder::
519221345Sdimoperator=(const NestedNameSpecifierLocBuilder &Other) {
520221345Sdim  Representation = Other.Representation;
521221345Sdim
522221345Sdim  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
523221345Sdim    // Re-use our storage.
524221345Sdim    BufferSize = Other.BufferSize;
525221345Sdim    memcpy(Buffer, Other.Buffer, BufferSize);
526221345Sdim    return *this;
527221345Sdim  }
528221345Sdim
529221345Sdim  // Free our storage, if we have any.
530221345Sdim  if (BufferCapacity) {
531221345Sdim    free(Buffer);
532221345Sdim    BufferCapacity = 0;
533221345Sdim  }
534221345Sdim
535221345Sdim  if (!Other.Buffer) {
536221345Sdim    // Empty.
537276479Sdim    Buffer = nullptr;
538221345Sdim    BufferSize = 0;
539221345Sdim    return *this;
540221345Sdim  }
541221345Sdim
542221345Sdim  if (Other.BufferCapacity == 0) {
543221345Sdim    // Shallow copy is okay.
544221345Sdim    Buffer = Other.Buffer;
545221345Sdim    BufferSize = Other.BufferSize;
546221345Sdim    return *this;
547221345Sdim  }
548221345Sdim
549221345Sdim  // Deep copy.
550276479Sdim  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
551276479Sdim         BufferCapacity);
552221345Sdim  return *this;
553221345Sdim}
554221345Sdim
555221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
556221345Sdim                                           SourceLocation TemplateKWLoc,
557221345Sdim                                           TypeLoc TL,
558221345Sdim                                           SourceLocation ColonColonLoc) {
559221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
560221345Sdim                                               TemplateKWLoc.isValid(),
561221345Sdim                                               TL.getTypePtr());
562221345Sdim
563221345Sdim  // Push source-location info into the buffer.
564221345Sdim  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
565221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
566221345Sdim}
567221345Sdim
568221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
569221345Sdim                                           IdentifierInfo *Identifier,
570221345Sdim                                           SourceLocation IdentifierLoc,
571221345Sdim                                           SourceLocation ColonColonLoc) {
572221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
573221345Sdim                                               Identifier);
574221345Sdim
575221345Sdim  // Push source-location info into the buffer.
576221345Sdim  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
577221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
578221345Sdim}
579221345Sdim
580221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
581221345Sdim                                           NamespaceDecl *Namespace,
582221345Sdim                                           SourceLocation NamespaceLoc,
583221345Sdim                                           SourceLocation ColonColonLoc) {
584221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation,
585221345Sdim                                               Namespace);
586221345Sdim
587221345Sdim  // Push source-location info into the buffer.
588221345Sdim  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
589221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
590221345Sdim}
591221345Sdim
592221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
593221345Sdim                                           NamespaceAliasDecl *Alias,
594221345Sdim                                           SourceLocation AliasLoc,
595221345Sdim                                           SourceLocation ColonColonLoc) {
596221345Sdim  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
597221345Sdim
598221345Sdim  // Push source-location info into the buffer.
599221345Sdim  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
600221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
601221345Sdim}
602221345Sdim
603221345Sdimvoid NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
604221345Sdim                                               SourceLocation ColonColonLoc) {
605221345Sdim  assert(!Representation && "Already have a nested-name-specifier!?");
606221345Sdim  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
607221345Sdim
608221345Sdim  // Push source-location info into the buffer.
609221345Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
610221345Sdim}
611221345Sdim
612280031Sdimvoid NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
613280031Sdim                                              CXXRecordDecl *RD,
614280031Sdim                                              SourceLocation SuperLoc,
615280031Sdim                                              SourceLocation ColonColonLoc) {
616280031Sdim  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
617280031Sdim
618280031Sdim  // Push source-location info into the buffer.
619280031Sdim  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
620280031Sdim  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
621280031Sdim}
622280031Sdim
623221345Sdimvoid NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
624221345Sdim                                                NestedNameSpecifier *Qualifier,
625221345Sdim                                                SourceRange R) {
626221345Sdim  Representation = Qualifier;
627221345Sdim
628221345Sdim  // Construct bogus (but well-formed) source information for the
629221345Sdim  // nested-name-specifier.
630221345Sdim  BufferSize = 0;
631226633Sdim  SmallVector<NestedNameSpecifier *, 4> Stack;
632221345Sdim  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
633221345Sdim    Stack.push_back(NNS);
634221345Sdim  while (!Stack.empty()) {
635261991Sdim    NestedNameSpecifier *NNS = Stack.pop_back_val();
636221345Sdim    switch (NNS->getKind()) {
637221345Sdim      case NestedNameSpecifier::Identifier:
638221345Sdim      case NestedNameSpecifier::Namespace:
639221345Sdim      case NestedNameSpecifier::NamespaceAlias:
640221345Sdim        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
641221345Sdim        break;
642221345Sdim
643221345Sdim      case NestedNameSpecifier::TypeSpec:
644221345Sdim      case NestedNameSpecifier::TypeSpecWithTemplate: {
645221345Sdim        TypeSourceInfo *TSInfo
646221345Sdim        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
647221345Sdim                                           R.getBegin());
648221345Sdim        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
649221345Sdim                    BufferCapacity);
650221345Sdim        break;
651221345Sdim      }
652221345Sdim
653221345Sdim      case NestedNameSpecifier::Global:
654280031Sdim      case NestedNameSpecifier::Super:
655221345Sdim        break;
656221345Sdim    }
657221345Sdim
658221345Sdim    // Save the location of the '::'.
659221345Sdim    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
660221345Sdim                       Buffer, BufferSize, BufferCapacity);
661221345Sdim  }
662221345Sdim}
663221345Sdim
664221345Sdimvoid NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
665221345Sdim  if (BufferCapacity)
666221345Sdim    free(Buffer);
667221345Sdim
668221345Sdim  if (!Other) {
669276479Sdim    Representation = nullptr;
670221345Sdim    BufferSize = 0;
671221345Sdim    return;
672221345Sdim  }
673221345Sdim
674221345Sdim  // Rather than copying the data (which is wasteful), "adopt" the
675221345Sdim  // pointer (which points into the ASTContext) but set the capacity to zero to
676221345Sdim  // indicate that we don't own it.
677221345Sdim  Representation = Other.getNestedNameSpecifier();
678221345Sdim  Buffer = static_cast<char *>(Other.getOpaqueData());
679221345Sdim  BufferSize = Other.getDataLength();
680221345Sdim  BufferCapacity = 0;
681221345Sdim}
682221345Sdim
683221345SdimNestedNameSpecifierLoc
684221345SdimNestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
685221345Sdim  if (!Representation)
686221345Sdim    return NestedNameSpecifierLoc();
687221345Sdim
688221345Sdim  // If we adopted our data pointer from elsewhere in the AST context, there's
689221345Sdim  // no need to copy the memory.
690221345Sdim  if (BufferCapacity == 0)
691221345Sdim    return NestedNameSpecifierLoc(Representation, Buffer);
692221345Sdim
693221345Sdim  // FIXME: After copying the source-location information, should we free
694221345Sdim  // our (temporary) buffer and adopt the ASTContext-allocated memory?
695221345Sdim  // Doing so would optimize repeated calls to getWithLocInContext().
696314564Sdim  void *Mem = Context.Allocate(BufferSize, alignof(void *));
697221345Sdim  memcpy(Mem, Buffer, BufferSize);
698221345Sdim  return NestedNameSpecifierLoc(Representation, Mem);
699221345Sdim}
700