clang  3.9.0
QualTypeNames.cpp
Go to the documentation of this file.
1 //===------- QualTypeNames.cpp - Generate Complete QualType Names ---------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 //===----------------------------------------------------------------------===//
6 //
7 // This file is distributed under the University of Illinois Open Source
8 // License. See LICENSE.TXT for details.
9 //
10 //===----------------------------------------------------------------------===//
11 
13 #include "clang/AST/DeclTemplate.h"
15 #include "clang/AST/GlobalDecl.h"
16 #include "clang/AST/Mangle.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringRef.h"
19 
20 #include <stdio.h>
21 #include <memory>
22 
23 namespace clang {
24 
25 namespace TypeName {
26 /// \brief Generates a QualType that can be used to name the same type
27 /// if used at the end of the current translation unit. This ignores
28 /// issues such as type shadowing.
29 ///
30 /// \param[in] QT - the type for which the fully qualified type will be
31 /// returned.
32 /// \param[in] Ctx - the ASTContext to be used.
33 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
34 /// specifier "::" should be prepended or not.
35 static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
36  bool WithGlobalNsPrefix);
37 
38 /// \brief Create a NestedNameSpecifier for Namesp and its enclosing
39 /// scopes.
40 ///
41 /// \param[in] Ctx - the AST Context to be used.
42 /// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
43 /// is requested.
44 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
45 /// specifier "::" should be prepended or not.
46 static NestedNameSpecifier *createNestedNameSpecifier(
47  const ASTContext &Ctx,
48  const NamespaceDecl *Namesp,
49  bool WithGlobalNsPrefix);
50 
51 /// \brief Create a NestedNameSpecifier for TagDecl and its enclosing
52 /// scopes.
53 ///
54 /// \param[in] Ctx - the AST Context to be used.
55 /// \param[in] TD - the TagDecl for which a NestedNameSpecifier is
56 /// requested.
57 /// \param[in] FullyQualify - Convert all template arguments into fully
58 /// qualified names.
59 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
60 /// specifier "::" should be prepended or not.
61 static NestedNameSpecifier *createNestedNameSpecifier(
62  const ASTContext &Ctx, const TypeDecl *TD,
63  bool FullyQualify, bool WithGlobalNsPrefix);
64 
65 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
66  const ASTContext &Ctx, const Decl *decl,
67  bool FullyQualified, bool WithGlobalNsPrefix);
68 
69 static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
70  const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
71 
73  TemplateName &TName,
74  bool WithGlobalNsPrefix) {
75  bool Changed = false;
76  NestedNameSpecifier *NNS = nullptr;
77 
78  TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
79  // ArgTDecl won't be NULL because we asserted that this isn't a
80  // dependent context very early in the call chain.
81  assert(ArgTDecl != nullptr);
83 
84  if (QTName && !QTName->hasTemplateKeyword()) {
85  NNS = QTName->getQualifier();
87  Ctx, NNS, WithGlobalNsPrefix);
88  if (QNNS != NNS) {
89  Changed = true;
90  NNS = QNNS;
91  } else {
92  NNS = nullptr;
93  }
94  } else {
96  Ctx, ArgTDecl, true, WithGlobalNsPrefix);
97  }
98  if (NNS) {
99  TName = Ctx.getQualifiedTemplateName(NNS,
100  /*TemplateKeyword=*/false, ArgTDecl);
101  Changed = true;
102  }
103  return Changed;
104 }
105 
107  TemplateArgument &Arg,
108  bool WithGlobalNsPrefix) {
109  bool Changed = false;
110 
111  // Note: we do not handle TemplateArgument::Expression, to replace it
112  // we need the information for the template instance decl.
113 
114  if (Arg.getKind() == TemplateArgument::Template) {
115  TemplateName TName = Arg.getAsTemplate();
116  Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
117  if (Changed) {
118  Arg = TemplateArgument(TName);
119  }
120  } else if (Arg.getKind() == TemplateArgument::Type) {
121  QualType SubTy = Arg.getAsType();
122  // Check if the type needs more desugaring and recurse.
123  QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
124  if (QTFQ != SubTy) {
125  Arg = TemplateArgument(QTFQ);
126  Changed = true;
127  }
128  }
129  return Changed;
130 }
131 
133  const Type *TypePtr,
134  bool WithGlobalNsPrefix) {
135  // DependentTemplateTypes exist within template declarations and
136  // definitions. Therefore we shouldn't encounter them at the end of
137  // a translation unit. If we do, the caller has made an error.
138  assert(!isa<DependentTemplateSpecializationType>(TypePtr));
139  // In case of template specializations, iterate over the arguments
140  // and fully qualify them as well.
141  if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) {
142  bool MightHaveChanged = false;
144  for (TemplateSpecializationType::iterator I = TST->begin(), E = TST->end();
145  I != E; ++I) {
146  // Cheap to copy and potentially modified by
147  // getFullyQualifedTemplateArgument.
148  TemplateArgument Arg(*I);
149  MightHaveChanged |= getFullyQualifiedTemplateArgument(
150  Ctx, Arg, WithGlobalNsPrefix);
151  FQArgs.push_back(Arg);
152  }
153 
154  // If a fully qualified arg is different from the unqualified arg,
155  // allocate new type in the AST.
156  if (MightHaveChanged) {
158  TST->getTemplateName(), FQArgs,
159  TST->getCanonicalTypeInternal());
160  // getTemplateSpecializationType returns a fully qualified
161  // version of the specialization itself, so no need to qualify
162  // it.
163  return QT.getTypePtr();
164  }
165  } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) {
166  // We are asked to fully qualify and we have a Record Type,
167  // which can point to a template instantiation with no sugar in any of
168  // its template argument, however we still need to fully qualify them.
169 
170  if (const auto *TSTDecl =
171  dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
172  const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
173 
174  bool MightHaveChanged = false;
176  for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
177  // cheap to copy and potentially modified by
178  // getFullyQualifedTemplateArgument
179  TemplateArgument Arg(TemplateArgs[I]);
180  MightHaveChanged |= getFullyQualifiedTemplateArgument(
181  Ctx, Arg, WithGlobalNsPrefix);
182  FQArgs.push_back(Arg);
183  }
184 
185  // If a fully qualified arg is different from the unqualified arg,
186  // allocate new type in the AST.
187  if (MightHaveChanged) {
188  TemplateName TN(TSTDecl->getSpecializedTemplate());
190  TN, FQArgs,
191  TSTRecord->getCanonicalTypeInternal());
192  // getTemplateSpecializationType returns a fully qualified
193  // version of the specialization itself, so no need to qualify
194  // it.
195  return QT.getTypePtr();
196  }
197  }
198  }
199  return TypePtr;
200 }
201 
202 static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
203  bool FullyQualify,
204  bool WithGlobalNsPrefix) {
205  const DeclContext *DC = D->getDeclContext();
206  if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
207  while (NS && NS->isInline()) {
208  // Ignore inline namespace;
209  NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
210  }
211  if (NS->getDeclName()) {
212  return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
213  }
214  return nullptr; // no starting '::', no anonymous
215  } else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
216  return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
217  } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
219  Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
220  } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
222  }
223  return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
224 }
225 
226 /// \brief Return a fully qualified version of this name specifier.
228  const ASTContext &Ctx, NestedNameSpecifier *Scope,
229  bool WithGlobalNsPrefix) {
230  switch (Scope->getKind()) {
232  // Already fully qualified
233  return Scope;
236  Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix);
238  // Namespace aliases are only valid for the duration of the
239  // scope where they were introduced, and therefore are often
240  // invalid at the end of the TU. So use the namespace name more
241  // likely to be valid at the end of the TU.
243  Ctx,
245  WithGlobalNsPrefix);
247  // A function or some other construct that makes it un-namable
248  // at the end of the TU. Skip the current component of the name,
249  // but use the name of it's prefix.
251  Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
255  const Type *Type = Scope->getAsType();
256  // Find decl context.
257  const TagDecl *TD = nullptr;
258  if (const TagType *TagDeclType = Type->getAs<TagType>()) {
259  TD = TagDeclType->getDecl();
260  } else {
261  TD = Type->getAsCXXRecordDecl();
262  }
263  if (TD) {
265  true /*FullyQualified*/,
266  WithGlobalNsPrefix);
267  } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
268  return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
269  true /*FullyQualified*/,
270  WithGlobalNsPrefix);
271  }
272  return Scope;
273  }
274  }
275  llvm_unreachable("bad NNS kind");
276 }
277 
278 /// \brief Create a nested name specifier for the declaring context of
279 /// the type.
281  const ASTContext &Ctx, const Decl *Decl,
282  bool FullyQualified, bool WithGlobalNsPrefix) {
283  assert(Decl);
284 
285  const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
286  const auto *Outer = dyn_cast_or_null<NamedDecl>(DC);
287  const auto *OuterNS = dyn_cast_or_null<NamespaceDecl>(DC);
288  if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
289  if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
290  if (ClassTemplateDecl *ClassTempl =
291  CxxDecl->getDescribedClassTemplate()) {
292  // We are in the case of a type(def) that was declared in a
293  // class template but is *not* type dependent. In clang, it
294  // gets attached to the class template declaration rather than
295  // any specific class template instantiation. This result in
296  // 'odd' fully qualified typename:
297  //
298  // vector<_Tp,_Alloc>::size_type
299  //
300  // Make the situation is 'useable' but looking a bit odd by
301  // picking a random instance as the declaring context.
302  if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
303  Decl = *(ClassTempl->spec_begin());
304  Outer = dyn_cast<NamedDecl>(Decl);
305  OuterNS = dyn_cast<NamespaceDecl>(Decl);
306  }
307  }
308  }
309 
310  if (OuterNS) {
311  return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
312  } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
314  Ctx, TD, FullyQualified, WithGlobalNsPrefix);
315  } else if (dyn_cast<TranslationUnitDecl>(Outer)) {
316  // Context is the TU. Nothing needs to be done.
317  return nullptr;
318  } else {
319  // Decl's context was neither the TU, a namespace, nor a
320  // TagDecl, which means it is a type local to a scope, and not
321  // accessible at the end of the TU.
322  return nullptr;
323  }
324  } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
326  }
327  return nullptr;
328 }
329 
330 /// \brief Create a nested name specifier for the declaring context of
331 /// the type.
333  const ASTContext &Ctx, const Type *TypePtr,
334  bool FullyQualified, bool WithGlobalNsPrefix) {
335  if (!TypePtr) return nullptr;
336 
337  Decl *Decl = nullptr;
338  // There are probably other cases ...
339  if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
340  Decl = TDT->getDecl();
341  } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
342  Decl = TagDeclType->getDecl();
343  } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
344  Decl = TST->getTemplateName().getAsTemplateDecl();
345  } else {
346  Decl = TypePtr->getAsCXXRecordDecl();
347  }
348 
349  if (!Decl) return nullptr;
350 
352  Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
353 }
354 
356  const NamespaceDecl *Namespace,
357  bool WithGlobalNsPrefix) {
358  while (Namespace && Namespace->isInline()) {
359  // Ignore inline namespace;
360  Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
361  }
362  if (!Namespace) return nullptr;
363 
364  bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
366  Ctx,
367  createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
368  Namespace);
369 }
370 
372  const TypeDecl *TD,
373  bool FullyQualify,
374  bool WithGlobalNsPrefix) {
376  Ctx,
377  createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
378  false /*No TemplateKeyword*/,
379  TD->getTypeForDecl());
380 }
381 
382 /// \brief Return the fully qualified type, including fully-qualified
383 /// versions of any template parameters.
385  bool WithGlobalNsPrefix) {
386  // In case of myType* we need to strip the pointer first, fully
387  // qualify and attach the pointer once again.
388  if (isa<PointerType>(QT.getTypePtr())) {
389  // Get the qualifiers.
390  Qualifiers Quals = QT.getQualifiers();
391  QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
392  QT = Ctx.getPointerType(QT);
393  // Add back the qualifiers.
394  QT = Ctx.getQualifiedType(QT, Quals);
395  return QT;
396  }
397 
398  // In case of myType& we need to strip the reference first, fully
399  // qualify and attach the reference once again.
400  if (isa<ReferenceType>(QT.getTypePtr())) {
401  // Get the qualifiers.
402  bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
403  Qualifiers Quals = QT.getQualifiers();
404  QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
405  // Add the r- or l-value reference type back to the fully
406  // qualified one.
407  if (IsLValueRefTy)
408  QT = Ctx.getLValueReferenceType(QT);
409  else
410  QT = Ctx.getRValueReferenceType(QT);
411  // Add back the qualifiers.
412  QT = Ctx.getQualifiedType(QT, Quals);
413  return QT;
414  }
415 
416  // Remove the part of the type related to the type being a template
417  // parameter (we won't report it as part of the 'type name' and it
418  // is actually make the code below to be more complex (to handle
419  // those)
420  while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
421  // Get the qualifiers.
422  Qualifiers Quals = QT.getQualifiers();
423 
424  QT = dyn_cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
425 
426  // Add back the qualifiers.
427  QT = Ctx.getQualifiedType(QT, Quals);
428  }
429 
430  NestedNameSpecifier *Prefix = nullptr;
431  // Local qualifiers are attached to the QualType outside of the
432  // elaborated type. Retrieve them before descending into the
433  // elaborated type.
434  Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
435  QT = QualType(QT.getTypePtr(), 0);
437  if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
438  QT = ETypeInput->getNamedType();
439  assert(!QT.hasLocalQualifiers());
440  Keyword = ETypeInput->getKeyword();
441  }
442  // Create a nested name specifier if needed.
444  true /*FullyQualified*/,
445  WithGlobalNsPrefix);
446 
447  // In case of template specializations iterate over the arguments and
448  // fully qualify them as well.
449  if (isa<const TemplateSpecializationType>(QT.getTypePtr()) ||
450  isa<const RecordType>(QT.getTypePtr())) {
451  // We are asked to fully qualify and we have a Record Type (which
452  // may point to a template specialization) or Template
453  // Specialization Type. We need to fully qualify their arguments.
454 
455  const Type *TypePtr = getFullyQualifiedTemplateType(
456  Ctx, QT.getTypePtr(), WithGlobalNsPrefix);
457  QT = QualType(TypePtr, 0);
458  }
459  if (Prefix || Keyword != ETK_None) {
460  QT = Ctx.getElaboratedType(Keyword, Prefix, QT);
461  }
462  QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
463  return QT;
464 }
465 
467  const ASTContext &Ctx,
468  bool WithGlobalNsPrefix) {
469  PrintingPolicy Policy(Ctx.getPrintingPolicy());
470  Policy.SuppressScope = false;
471  Policy.AnonymousTagLocations = false;
472  Policy.PolishForDeclaration = true;
473  Policy.SuppressUnwrittenScope = true;
474  QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
475  return FQQT.getAsString(Policy);
476 }
477 
478 } // end namespace TypeName
479 } // end namespace clang
QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType) const
Qualifiers getLocalQualifiers() const
Retrieve the set of qualifiers local to this particular QualType instance, not including any qualifie...
Definition: Type.h:5278
static NestedNameSpecifier * createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *decl, bool FullyQualified, bool WithGlobalNsPrefix)
Create a nested name specifier for the declaring context of the type.
A (possibly-)qualified type.
Definition: Type.h:598
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, TemplateName &TName, bool WithGlobalNsPrefix)
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Definition: ASTContext.h:1693
static NestedNameSpecifier * createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp, bool WithGlobalNsPrefix)
Create a NestedNameSpecifier for Namesp and its enclosing scopes.
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known...
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type...
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in...
Defines the C++ template declaration subclasses.
std::string getAsString() const
Definition: Type.h:924
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type...
The base class of the type hierarchy.
Definition: Type.h:1281
NamespaceDecl - Represent a C++ namespace.
Definition: Decl.h:471
NestedNameSpecifier * getPrefix() const
Return the prefix of this nested name specifier.
An identifier, stored as an IdentifierInfo*.
static NestedNameSpecifier * Create(const ASTContext &Context, NestedNameSpecifier *Prefix, IdentifierInfo *II)
Builds a specifier combining a prefix and an identifier.
NamespaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this namespace.
Definition: Decl.h:557
A namespace, stored as a NamespaceDecl*.
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:38
Represents the result of substituting a type for a template type parameter.
Definition: Type.h:3983
The collection of all-type qualifiers we support.
Definition: Type.h:117
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:92
NamespaceDecl * getNamespace()
Retrieve the namespace declaration aliased by this directive.
Definition: DeclCXX.h:2789
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
Definition: ASTMatchers.h:283
bool isTranslationUnit() const
Definition: DeclBase.h:1283
unsigned size() const
Retrieve the number of template arguments in this template argument list.
Definition: DeclTemplate.h:231
static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix)
Generates a QualType that can be used to name the same type if used at the end of the current transla...
bool isInline() const
Returns true if this is an inline namespace declaration.
Definition: Decl.h:526
TypeDecl - Represents a declaration of a type.
Definition: Decl.h:2569
bool SuppressScope
Suppresses printing of scope specifiers.
QualifiedTemplateName * getAsQualifiedTemplateName() const
Retrieve the underlying qualified template name structure, if any.
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:39
detail::InMemoryDirectory::const_iterator I
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:415
bool hasLocalQualifiers() const
Determine whether this particular QualType instance has any qualifiers, without looking through any t...
Definition: Type.h:702
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
const Type * getTypeForDecl() const
Definition: Decl.h:2590
friend class ASTContext
Definition: Type.h:4178
ElaboratedTypeKeyword
The elaboration keyword that precedes a qualified type name or introduces an elaborated-type-specifie...
Definition: Type.h:4357
static const Type * getFullyQualifiedTemplateType(const ASTContext &Ctx, const Type *TypePtr, bool WithGlobalNsPrefix)
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:216
Represents a C++ template name within the type system.
Definition: TemplateName.h:176
A namespace alias, stored as a NamespaceAliasDecl*.
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
const clang::PrintingPolicy & getPrintingPolicy() const
Definition: ASTContext.h:553
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template) const
Retrieve the template name that represents a qualified template name such as std::vector.
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:5259
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
Definition: TemplateBase.h:262
const TemplateArgument * iterator
Definition: Type.h:4233
TagDecl - Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:2727
QualType getTemplateSpecializationType(TemplateName T, ArrayRef< TemplateArgument > Args, QualType Canon=QualType()) const
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
Represents a template argument.
Definition: TemplateBase.h:40
QualType getAsType() const
Retrieve the type for a type template argument.
Definition: TemplateBase.h:238
Represents a template name that was expressed as a qualified name.
Definition: TemplateName.h:355
static NestedNameSpecifier * createOuterNNS(const ASTContext &Ctx, const Decl *D, bool FullyQualify, bool WithGlobalNsPrefix)
bool hasTemplateKeyword() const
Whether the template name was prefixed by the "template" keyword.
Definition: TemplateName.h:382
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1135
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:330
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
detail::InMemoryDirectory::const_iterator E
A type that was preceded by the 'template' keyword, stored as a Type*.
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:5818
std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix=false)
Get the fully qualified name for a type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1528
The template argument is a type.
Definition: TemplateBase.h:48
static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, TemplateArgument &Arg, bool WithGlobalNsPrefix)
A template argument list.
Definition: DeclTemplate.h:173
The template argument is a template name that was provided for a template template parameter...
Definition: TemplateBase.h:60
Declaration of a class template.
NestedNameSpecifier * getQualifier() const
Return the nested name specifier that qualifies this name.
Definition: TemplateName.h:378
QualType desugar() const
Definition: Type.h:4260
static NestedNameSpecifier * getFullyQualifiedNestedNameSpecifier(const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix)
Return a fully qualified version of this name specifier.
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
No keyword precedes the qualified type name.
Definition: Type.h:4372
The global specifier '::'. There is no stored value.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:5286
static NestedNameSpecifier * GlobalSpecifier(const ASTContext &Context)
Returns the nested name specifier representing the global scope.