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