NestedNameSpecifier.cpp revision 263508
1//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the NestedNameSpecifier class, which represents
11//  a C++ nested-name-specifier.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/AST/NestedNameSpecifier.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/PrettyPrinter.h"
19#include "clang/AST/Type.h"
20#include "clang/AST/TypeLoc.h"
21#include "llvm/Support/AlignOf.h"
22#include "llvm/Support/raw_ostream.h"
23#include <cassert>
24
25using namespace clang;
26
27NestedNameSpecifier *
28NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
29                                  const NestedNameSpecifier &Mockup) {
30  llvm::FoldingSetNodeID ID;
31  Mockup.Profile(ID);
32
33  void *InsertPos = 0;
34  NestedNameSpecifier *NNS
35    = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
36  if (!NNS) {
37    NNS = new (Context, llvm::alignOf<NestedNameSpecifier>())
38        NestedNameSpecifier(Mockup);
39    Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
40  }
41
42  return NNS;
43}
44
45NestedNameSpecifier *
46NestedNameSpecifier::Create(const ASTContext &Context,
47                            NestedNameSpecifier *Prefix, IdentifierInfo *II) {
48  assert(II && "Identifier cannot be NULL");
49  assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
50
51  NestedNameSpecifier Mockup;
52  Mockup.Prefix.setPointer(Prefix);
53  Mockup.Prefix.setInt(StoredIdentifier);
54  Mockup.Specifier = II;
55  return FindOrInsert(Context, Mockup);
56}
57
58NestedNameSpecifier *
59NestedNameSpecifier::Create(const ASTContext &Context,
60                            NestedNameSpecifier *Prefix,
61                            const NamespaceDecl *NS) {
62  assert(NS && "Namespace cannot be NULL");
63  assert((!Prefix ||
64          (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
65         "Broken nested name specifier");
66  NestedNameSpecifier Mockup;
67  Mockup.Prefix.setPointer(Prefix);
68  Mockup.Prefix.setInt(StoredNamespaceOrAlias);
69  Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
70  return FindOrInsert(Context, Mockup);
71}
72
73NestedNameSpecifier *
74NestedNameSpecifier::Create(const ASTContext &Context,
75                            NestedNameSpecifier *Prefix,
76                            NamespaceAliasDecl *Alias) {
77  assert(Alias && "Namespace alias cannot be NULL");
78  assert((!Prefix ||
79          (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
80         "Broken nested name specifier");
81  NestedNameSpecifier Mockup;
82  Mockup.Prefix.setPointer(Prefix);
83  Mockup.Prefix.setInt(StoredNamespaceOrAlias);
84  Mockup.Specifier = Alias;
85  return FindOrInsert(Context, Mockup);
86}
87
88NestedNameSpecifier *
89NestedNameSpecifier::Create(const ASTContext &Context,
90                            NestedNameSpecifier *Prefix,
91                            bool Template, const Type *T) {
92  assert(T && "Type cannot be NULL");
93  NestedNameSpecifier Mockup;
94  Mockup.Prefix.setPointer(Prefix);
95  Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
96  Mockup.Specifier = const_cast<Type*>(T);
97  return FindOrInsert(Context, Mockup);
98}
99
100NestedNameSpecifier *
101NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
102  assert(II && "Identifier cannot be NULL");
103  NestedNameSpecifier Mockup;
104  Mockup.Prefix.setPointer(0);
105  Mockup.Prefix.setInt(StoredIdentifier);
106  Mockup.Specifier = II;
107  return FindOrInsert(Context, Mockup);
108}
109
110NestedNameSpecifier *
111NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
112  if (!Context.GlobalNestedNameSpecifier)
113    Context.GlobalNestedNameSpecifier =
114        new (Context, llvm::alignOf<NestedNameSpecifier>())
115            NestedNameSpecifier();
116  return Context.GlobalNestedNameSpecifier;
117}
118
119NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
120  if (Specifier == 0)
121    return Global;
122
123  switch (Prefix.getInt()) {
124  case StoredIdentifier:
125    return Identifier;
126
127  case StoredNamespaceOrAlias:
128    return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace
129                                                            : NamespaceAlias;
130
131  case StoredTypeSpec:
132    return TypeSpec;
133
134  case StoredTypeSpecWithTemplate:
135    return TypeSpecWithTemplate;
136  }
137
138  llvm_unreachable("Invalid NNS Kind!");
139}
140
141/// \brief Retrieve the namespace stored in this nested name
142/// specifier.
143NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
144  if (Prefix.getInt() == StoredNamespaceOrAlias)
145    return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
146
147  return 0;
148}
149
150/// \brief Retrieve the namespace alias stored in this nested name
151/// specifier.
152NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
153  if (Prefix.getInt() == StoredNamespaceOrAlias)
154    return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
155
156  return 0;
157}
158
159
160/// \brief Whether this nested name specifier refers to a dependent
161/// type or not.
162bool NestedNameSpecifier::isDependent() const {
163  switch (getKind()) {
164  case Identifier:
165    // Identifier specifiers always represent dependent types
166    return true;
167
168  case Namespace:
169  case NamespaceAlias:
170  case Global:
171    return false;
172
173  case TypeSpec:
174  case TypeSpecWithTemplate:
175    return getAsType()->isDependentType();
176  }
177
178  llvm_unreachable("Invalid NNS Kind!");
179}
180
181/// \brief Whether this nested name specifier refers to a dependent
182/// type or not.
183bool NestedNameSpecifier::isInstantiationDependent() const {
184  switch (getKind()) {
185  case Identifier:
186    // Identifier specifiers always represent dependent types
187    return true;
188
189  case Namespace:
190  case NamespaceAlias:
191  case Global:
192    return false;
193
194  case TypeSpec:
195  case TypeSpecWithTemplate:
196    return getAsType()->isInstantiationDependentType();
197  }
198
199  llvm_unreachable("Invalid NNS Kind!");
200}
201
202bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
203  switch (getKind()) {
204  case Identifier:
205    return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
206
207  case Namespace:
208  case NamespaceAlias:
209  case Global:
210    return false;
211
212  case TypeSpec:
213  case TypeSpecWithTemplate:
214    return getAsType()->containsUnexpandedParameterPack();
215  }
216
217  llvm_unreachable("Invalid NNS Kind!");
218}
219
220/// \brief Print this nested name specifier to the given output
221/// stream.
222void
223NestedNameSpecifier::print(raw_ostream &OS,
224                           const PrintingPolicy &Policy) const {
225  if (getPrefix())
226    getPrefix()->print(OS, Policy);
227
228  switch (getKind()) {
229  case Identifier:
230    OS << getAsIdentifier()->getName();
231    break;
232
233  case Namespace:
234    if (getAsNamespace()->isAnonymousNamespace())
235      return;
236
237    OS << getAsNamespace()->getName();
238    break;
239
240  case NamespaceAlias:
241    OS << getAsNamespaceAlias()->getName();
242    break;
243
244  case Global:
245    break;
246
247  case TypeSpecWithTemplate:
248    OS << "template ";
249    // Fall through to print the type.
250
251  case TypeSpec: {
252    const Type *T = getAsType();
253
254    PrintingPolicy InnerPolicy(Policy);
255    InnerPolicy.SuppressScope = true;
256
257    // Nested-name-specifiers are intended to contain minimally-qualified
258    // types. An actual ElaboratedType will not occur, since we'll store
259    // just the type that is referred to in the nested-name-specifier (e.g.,
260    // a TypedefType, TagType, etc.). However, when we are dealing with
261    // dependent template-id types (e.g., Outer<T>::template Inner<U>),
262    // the type requires its own nested-name-specifier for uniqueness, so we
263    // suppress that nested-name-specifier during printing.
264    assert(!isa<ElaboratedType>(T) &&
265           "Elaborated type in nested-name-specifier");
266    if (const TemplateSpecializationType *SpecType
267          = dyn_cast<TemplateSpecializationType>(T)) {
268      // Print the template name without its corresponding
269      // nested-name-specifier.
270      SpecType->getTemplateName().print(OS, InnerPolicy, true);
271
272      // Print the template argument list.
273      TemplateSpecializationType::PrintTemplateArgumentList(
274          OS, SpecType->getArgs(), SpecType->getNumArgs(), InnerPolicy);
275    } else {
276      // Print the type normally
277      QualType(T, 0).print(OS, InnerPolicy);
278    }
279    break;
280  }
281  }
282
283  OS << "::";
284}
285
286void NestedNameSpecifier::dump(const LangOptions &LO) {
287  print(llvm::errs(), PrintingPolicy(LO));
288}
289
290unsigned
291NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
292  assert(Qualifier && "Expected a non-NULL qualifier");
293
294  // Location of the trailing '::'.
295  unsigned Length = sizeof(unsigned);
296
297  switch (Qualifier->getKind()) {
298  case NestedNameSpecifier::Global:
299    // Nothing more to add.
300    break;
301
302  case NestedNameSpecifier::Identifier:
303  case NestedNameSpecifier::Namespace:
304  case NestedNameSpecifier::NamespaceAlias:
305    // The location of the identifier or namespace name.
306    Length += sizeof(unsigned);
307    break;
308
309  case NestedNameSpecifier::TypeSpecWithTemplate:
310  case NestedNameSpecifier::TypeSpec:
311    // The "void*" that points at the TypeLoc data.
312    // Note: the 'template' keyword is part of the TypeLoc.
313    Length += sizeof(void *);
314    break;
315  }
316
317  return Length;
318}
319
320unsigned
321NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
322  unsigned Length = 0;
323  for (; Qualifier; Qualifier = Qualifier->getPrefix())
324    Length += getLocalDataLength(Qualifier);
325  return Length;
326}
327
328namespace {
329  /// \brief Load a (possibly unaligned) source location from a given address
330  /// and offset.
331  SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
332    unsigned Raw;
333    memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
334    return SourceLocation::getFromRawEncoding(Raw);
335  }
336
337  /// \brief Load a (possibly unaligned) pointer from a given address and
338  /// offset.
339  void *LoadPointer(void *Data, unsigned Offset) {
340    void *Result;
341    memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
342    return Result;
343  }
344}
345
346SourceRange NestedNameSpecifierLoc::getSourceRange() const {
347  if (!Qualifier)
348    return SourceRange();
349
350  NestedNameSpecifierLoc First = *this;
351  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
352    First = Prefix;
353
354  return SourceRange(First.getLocalSourceRange().getBegin(),
355                     getLocalSourceRange().getEnd());
356}
357
358SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
359  if (!Qualifier)
360    return SourceRange();
361
362  unsigned Offset = getDataLength(Qualifier->getPrefix());
363  switch (Qualifier->getKind()) {
364  case NestedNameSpecifier::Global:
365    return LoadSourceLocation(Data, Offset);
366
367  case NestedNameSpecifier::Identifier:
368  case NestedNameSpecifier::Namespace:
369  case NestedNameSpecifier::NamespaceAlias:
370    return SourceRange(LoadSourceLocation(Data, Offset),
371                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
372
373  case NestedNameSpecifier::TypeSpecWithTemplate:
374  case NestedNameSpecifier::TypeSpec: {
375    // The "void*" that points at the TypeLoc data.
376    // Note: the 'template' keyword is part of the TypeLoc.
377    void *TypeData = LoadPointer(Data, Offset);
378    TypeLoc TL(Qualifier->getAsType(), TypeData);
379    return SourceRange(TL.getBeginLoc(),
380                       LoadSourceLocation(Data, Offset + sizeof(void*)));
381  }
382  }
383
384  llvm_unreachable("Invalid NNS Kind!");
385}
386
387TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
388  assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec ||
389          Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) &&
390         "Nested-name-specifier location is not a type");
391
392  // The "void*" that points at the TypeLoc data.
393  unsigned Offset = getDataLength(Qualifier->getPrefix());
394  void *TypeData = LoadPointer(Data, Offset);
395  return TypeLoc(Qualifier->getAsType(), TypeData);
396}
397
398namespace {
399  void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
400              unsigned &BufferCapacity) {
401    if (BufferSize + (End - Start) > BufferCapacity) {
402      // Reallocate the buffer.
403      unsigned NewCapacity
404      = std::max((unsigned)(BufferCapacity? BufferCapacity * 2
405                            : sizeof(void*) * 2),
406                 (unsigned)(BufferSize + (End - Start)));
407      char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
408      memcpy(NewBuffer, Buffer, BufferSize);
409
410      if (BufferCapacity)
411        free(Buffer);
412      Buffer = NewBuffer;
413      BufferCapacity = NewCapacity;
414    }
415
416    memcpy(Buffer + BufferSize, Start, End - Start);
417    BufferSize += End-Start;
418  }
419
420  /// \brief Save a source location to the given buffer.
421  void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
422                          unsigned &BufferSize, unsigned &BufferCapacity) {
423    unsigned Raw = Loc.getRawEncoding();
424    Append(reinterpret_cast<char *>(&Raw),
425           reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
426           Buffer, BufferSize, BufferCapacity);
427  }
428
429  /// \brief Save a pointer to the given buffer.
430  void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
431                   unsigned &BufferCapacity) {
432    Append(reinterpret_cast<char *>(&Ptr),
433           reinterpret_cast<char *>(&Ptr) + sizeof(void *),
434           Buffer, BufferSize, BufferCapacity);
435  }
436}
437
438NestedNameSpecifierLocBuilder::
439NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
440  : Representation(Other.Representation), Buffer(0),
441    BufferSize(0), BufferCapacity(0)
442{
443  if (!Other.Buffer)
444    return;
445
446  if (Other.BufferCapacity == 0) {
447    // Shallow copy is okay.
448    Buffer = Other.Buffer;
449    BufferSize = Other.BufferSize;
450    return;
451  }
452
453  // Deep copy
454  BufferSize = Other.BufferSize;
455  BufferCapacity = Other.BufferSize;
456  Buffer = static_cast<char *>(malloc(BufferCapacity));
457  memcpy(Buffer, Other.Buffer, BufferSize);
458}
459
460NestedNameSpecifierLocBuilder &
461NestedNameSpecifierLocBuilder::
462operator=(const NestedNameSpecifierLocBuilder &Other) {
463  Representation = Other.Representation;
464
465  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
466    // Re-use our storage.
467    BufferSize = Other.BufferSize;
468    memcpy(Buffer, Other.Buffer, BufferSize);
469    return *this;
470  }
471
472  // Free our storage, if we have any.
473  if (BufferCapacity) {
474    free(Buffer);
475    BufferCapacity = 0;
476  }
477
478  if (!Other.Buffer) {
479    // Empty.
480    Buffer = 0;
481    BufferSize = 0;
482    return *this;
483  }
484
485  if (Other.BufferCapacity == 0) {
486    // Shallow copy is okay.
487    Buffer = Other.Buffer;
488    BufferSize = Other.BufferSize;
489    return *this;
490  }
491
492  // Deep copy.
493  BufferSize = Other.BufferSize;
494  BufferCapacity = BufferSize;
495  Buffer = static_cast<char *>(malloc(BufferSize));
496  memcpy(Buffer, Other.Buffer, BufferSize);
497  return *this;
498}
499
500void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
501                                           SourceLocation TemplateKWLoc,
502                                           TypeLoc TL,
503                                           SourceLocation ColonColonLoc) {
504  Representation = NestedNameSpecifier::Create(Context, Representation,
505                                               TemplateKWLoc.isValid(),
506                                               TL.getTypePtr());
507
508  // Push source-location info into the buffer.
509  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
510  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
511}
512
513void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
514                                           IdentifierInfo *Identifier,
515                                           SourceLocation IdentifierLoc,
516                                           SourceLocation ColonColonLoc) {
517  Representation = NestedNameSpecifier::Create(Context, Representation,
518                                               Identifier);
519
520  // Push source-location info into the buffer.
521  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
522  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
523}
524
525void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
526                                           NamespaceDecl *Namespace,
527                                           SourceLocation NamespaceLoc,
528                                           SourceLocation ColonColonLoc) {
529  Representation = NestedNameSpecifier::Create(Context, Representation,
530                                               Namespace);
531
532  // Push source-location info into the buffer.
533  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
534  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
535}
536
537void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
538                                           NamespaceAliasDecl *Alias,
539                                           SourceLocation AliasLoc,
540                                           SourceLocation ColonColonLoc) {
541  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
542
543  // Push source-location info into the buffer.
544  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
545  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
546}
547
548void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
549                                               SourceLocation ColonColonLoc) {
550  assert(!Representation && "Already have a nested-name-specifier!?");
551  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
552
553  // Push source-location info into the buffer.
554  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
555}
556
557void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
558                                                NestedNameSpecifier *Qualifier,
559                                                SourceRange R) {
560  Representation = Qualifier;
561
562  // Construct bogus (but well-formed) source information for the
563  // nested-name-specifier.
564  BufferSize = 0;
565  SmallVector<NestedNameSpecifier *, 4> Stack;
566  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
567    Stack.push_back(NNS);
568  while (!Stack.empty()) {
569    NestedNameSpecifier *NNS = Stack.pop_back_val();
570    switch (NNS->getKind()) {
571      case NestedNameSpecifier::Identifier:
572      case NestedNameSpecifier::Namespace:
573      case NestedNameSpecifier::NamespaceAlias:
574        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
575        break;
576
577      case NestedNameSpecifier::TypeSpec:
578      case NestedNameSpecifier::TypeSpecWithTemplate: {
579        TypeSourceInfo *TSInfo
580        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
581                                           R.getBegin());
582        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
583                    BufferCapacity);
584        break;
585      }
586
587      case NestedNameSpecifier::Global:
588        break;
589    }
590
591    // Save the location of the '::'.
592    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
593                       Buffer, BufferSize, BufferCapacity);
594  }
595}
596
597void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
598  if (BufferCapacity)
599    free(Buffer);
600
601  if (!Other) {
602    Representation = 0;
603    BufferSize = 0;
604    return;
605  }
606
607  // Rather than copying the data (which is wasteful), "adopt" the
608  // pointer (which points into the ASTContext) but set the capacity to zero to
609  // indicate that we don't own it.
610  Representation = Other.getNestedNameSpecifier();
611  Buffer = static_cast<char *>(Other.getOpaqueData());
612  BufferSize = Other.getDataLength();
613  BufferCapacity = 0;
614}
615
616NestedNameSpecifierLoc
617NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
618  if (!Representation)
619    return NestedNameSpecifierLoc();
620
621  // If we adopted our data pointer from elsewhere in the AST context, there's
622  // no need to copy the memory.
623  if (BufferCapacity == 0)
624    return NestedNameSpecifierLoc(Representation, Buffer);
625
626  // FIXME: After copying the source-location information, should we free
627  // our (temporary) buffer and adopt the ASTContext-allocated memory?
628  // Doing so would optimize repeated calls to getWithLocInContext().
629  void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
630  memcpy(Mem, Buffer, BufferSize);
631  return NestedNameSpecifierLoc(Representation, Mem);
632}
633