clang  5.0.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 
18 #include <stdio.h>
19 #include <memory>
20 
21 namespace clang {
22 
23 namespace TypeName {
24 /// \brief Generates a QualType that can be used to name the same type
25 /// if used at the end of the current translation unit. This ignores
26 /// issues such as type shadowing.
27 ///
28 /// \param[in] QT - the type for which the fully qualified type will be
29 /// returned.
30 /// \param[in] Ctx - the ASTContext to be used.
31 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
32 /// specifier "::" should be prepended or not.
33 static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
34  bool WithGlobalNsPrefix);
35 
36 /// \brief Create a NestedNameSpecifier for Namesp and its enclosing
37 /// scopes.
38 ///
39 /// \param[in] Ctx - the AST Context to be used.
40 /// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
41 /// is requested.
42 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
43 /// specifier "::" should be prepended or not.
44 static NestedNameSpecifier *createNestedNameSpecifier(
45  const ASTContext &Ctx,
46  const NamespaceDecl *Namesp,
47  bool WithGlobalNsPrefix);
48 
49 /// \brief Create a NestedNameSpecifier for TagDecl and its enclosing
50 /// scopes.
51 ///
52 /// \param[in] Ctx - the AST Context to be used.
53 /// \param[in] TD - the TagDecl for which a NestedNameSpecifier is
54 /// requested.
55 /// \param[in] FullyQualify - Convert all template arguments into fully
56 /// qualified names.
57 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
58 /// specifier "::" should be prepended or not.
59 static NestedNameSpecifier *createNestedNameSpecifier(
60  const ASTContext &Ctx, const TypeDecl *TD,
61  bool FullyQualify, bool WithGlobalNsPrefix);
62 
63 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
64  const ASTContext &Ctx, const Decl *decl,
65  bool FullyQualified, bool WithGlobalNsPrefix);
66 
67 static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
68  const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
69 
71  TemplateName &TName,
72  bool WithGlobalNsPrefix) {
73  bool Changed = false;
74  NestedNameSpecifier *NNS = nullptr;
75 
76  TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
77  // ArgTDecl won't be NULL because we asserted that this isn't a
78  // dependent context very early in the call chain.
79  assert(ArgTDecl != nullptr);
81 
82  if (QTName && !QTName->hasTemplateKeyword()) {
83  NNS = QTName->getQualifier();
85  Ctx, NNS, WithGlobalNsPrefix);
86  if (QNNS != NNS) {
87  Changed = true;
88  NNS = QNNS;
89  } else {
90  NNS = nullptr;
91  }
92  } else {
94  Ctx, ArgTDecl, true, WithGlobalNsPrefix);
95  }
96  if (NNS) {
97  TName = Ctx.getQualifiedTemplateName(NNS,
98  /*TemplateKeyword=*/false, ArgTDecl);
99  Changed = true;
100  }
101  return Changed;
102 }
103 
105  TemplateArgument &Arg,
106  bool WithGlobalNsPrefix) {
107  bool Changed = false;
108 
109  // Note: we do not handle TemplateArgument::Expression, to replace it
110  // we need the information for the template instance decl.
111 
112  if (Arg.getKind() == TemplateArgument::Template) {
113  TemplateName TName = Arg.getAsTemplate();
114  Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
115  if (Changed) {
116  Arg = TemplateArgument(TName);
117  }
118  } else if (Arg.getKind() == TemplateArgument::Type) {
119  QualType SubTy = Arg.getAsType();
120  // Check if the type needs more desugaring and recurse.
121  QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
122  if (QTFQ != SubTy) {
123  Arg = TemplateArgument(QTFQ);
124  Changed = true;
125  }
126  }
127  return Changed;
128 }
129 
131  const Type *TypePtr,
132  bool WithGlobalNsPrefix) {
133  // DependentTemplateTypes exist within template declarations and
134  // definitions. Therefore we shouldn't encounter them at the end of
135  // a translation unit. If we do, the caller has made an error.
136  assert(!isa<DependentTemplateSpecializationType>(TypePtr));
137  // In case of template specializations, iterate over the arguments
138  // and fully qualify them as well.
139  if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) {
140  bool MightHaveChanged = false;
142  for (TemplateSpecializationType::iterator I = TST->begin(), E = TST->end();
143  I != E; ++I) {
144  // Cheap to copy and potentially modified by
145  // getFullyQualifedTemplateArgument.
146  TemplateArgument Arg(*I);
147  MightHaveChanged |= getFullyQualifiedTemplateArgument(
148  Ctx, Arg, WithGlobalNsPrefix);
149  FQArgs.push_back(Arg);
150  }
151 
152  // If a fully qualified arg is different from the unqualified arg,
153  // allocate new type in the AST.
154  if (MightHaveChanged) {
156  TST->getTemplateName(), FQArgs,
157  TST->getCanonicalTypeInternal());
158  // getTemplateSpecializationType returns a fully qualified
159  // version of the specialization itself, so no need to qualify
160  // it.
161  return QT.getTypePtr();
162  }
163  } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) {
164  // We are asked to fully qualify and we have a Record Type,
165  // which can point to a template instantiation with no sugar in any of
166  // its template argument, however we still need to fully qualify them.
167 
168  if (const auto *TSTDecl =
169  dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
170  const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
171 
172  bool MightHaveChanged = false;
174  for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
175  // cheap to copy and potentially modified by
176  // getFullyQualifedTemplateArgument
177  TemplateArgument Arg(TemplateArgs[I]);
178  MightHaveChanged |= getFullyQualifiedTemplateArgument(
179  Ctx, Arg, WithGlobalNsPrefix);
180  FQArgs.push_back(Arg);
181  }
182 
183  // If a fully qualified arg is different from the unqualified arg,
184  // allocate new type in the AST.
185  if (MightHaveChanged) {
186  TemplateName TN(TSTDecl->getSpecializedTemplate());
188  TN, FQArgs,
189  TSTRecord->getCanonicalTypeInternal());
190  // getTemplateSpecializationType returns a fully qualified
191  // version of the specialization itself, so no need to qualify
192  // it.
193  return QT.getTypePtr();
194  }
195  }
196  }
197  return TypePtr;
198 }
199 
200 static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
201  bool FullyQualify,
202  bool WithGlobalNsPrefix) {
203  const DeclContext *DC = D->getDeclContext();
204  if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
205  while (NS && NS->isInline()) {
206  // Ignore inline namespace;
207  NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
208  }
209  if (NS->getDeclName()) {
210  return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
211  }
212  return nullptr; // no starting '::', no anonymous
213  } else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
214  return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
215  } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
217  Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
218  } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
220  }
221  return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
222 }
223 
224 /// \brief Return a fully qualified version of this name specifier.
226  const ASTContext &Ctx, NestedNameSpecifier *Scope,
227  bool WithGlobalNsPrefix) {
228  switch (Scope->getKind()) {
230  // Already fully qualified
231  return Scope;
234  Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix);
236  // Namespace aliases are only valid for the duration of the
237  // scope where they were introduced, and therefore are often
238  // invalid at the end of the TU. So use the namespace name more
239  // likely to be valid at the end of the TU.
241  Ctx,
243  WithGlobalNsPrefix);
245  // A function or some other construct that makes it un-namable
246  // at the end of the TU. Skip the current component of the name,
247  // but use the name of it's prefix.
249  Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
253  const Type *Type = Scope->getAsType();
254  // Find decl context.
255  const TagDecl *TD = nullptr;
256  if (const TagType *TagDeclType = Type->getAs<TagType>()) {
257  TD = TagDeclType->getDecl();
258  } else {
259  TD = Type->getAsCXXRecordDecl();
260  }
261  if (TD) {
263  true /*FullyQualified*/,
264  WithGlobalNsPrefix);
265  } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
266  return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
267  true /*FullyQualified*/,
268  WithGlobalNsPrefix);
269  }
270  return Scope;
271  }
272  }
273  llvm_unreachable("bad NNS kind");
274 }
275 
276 /// \brief Create a nested name specifier for the declaring context of
277 /// the type.
279  const ASTContext &Ctx, const Decl *Decl,
280  bool FullyQualified, bool WithGlobalNsPrefix) {
281  assert(Decl);
282 
283  const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
284  const auto *Outer = dyn_cast_or_null<NamedDecl>(DC);
285  const auto *OuterNS = dyn_cast_or_null<NamespaceDecl>(DC);
286  if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
287  if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
288  if (ClassTemplateDecl *ClassTempl =
289  CxxDecl->getDescribedClassTemplate()) {
290  // We are in the case of a type(def) that was declared in a
291  // class template but is *not* type dependent. In clang, it
292  // gets attached to the class template declaration rather than
293  // any specific class template instantiation. This result in
294  // 'odd' fully qualified typename:
295  //
296  // vector<_Tp,_Alloc>::size_type
297  //
298  // Make the situation is 'useable' but looking a bit odd by
299  // picking a random instance as the declaring context.
300  if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
301  Decl = *(ClassTempl->spec_begin());
302  Outer = dyn_cast<NamedDecl>(Decl);
303  OuterNS = dyn_cast<NamespaceDecl>(Decl);
304  }
305  }
306  }
307 
308  if (OuterNS) {
309  return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
310  } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
312  Ctx, TD, FullyQualified, WithGlobalNsPrefix);
313  } else if (dyn_cast<TranslationUnitDecl>(Outer)) {
314  // Context is the TU. Nothing needs to be done.
315  return nullptr;
316  } else {
317  // Decl's context was neither the TU, a namespace, nor a
318  // TagDecl, which means it is a type local to a scope, and not
319  // accessible at the end of the TU.
320  return nullptr;
321  }
322  } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
324  }
325  return nullptr;
326 }
327 
328 /// \brief Create a nested name specifier for the declaring context of
329 /// the type.
331  const ASTContext &Ctx, const Type *TypePtr,
332  bool FullyQualified, bool WithGlobalNsPrefix) {
333  if (!TypePtr) return nullptr;
334 
335  Decl *Decl = nullptr;
336  // There are probably other cases ...
337  if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
338  Decl = TDT->getDecl();
339  } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
340  Decl = TagDeclType->getDecl();
341  } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
342  Decl = TST->getTemplateName().getAsTemplateDecl();
343  } else {
344  Decl = TypePtr->getAsCXXRecordDecl();
345  }
346 
347  if (!Decl) return nullptr;
348 
350  Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
351 }
352 
354  const NamespaceDecl *Namespace,
355  bool WithGlobalNsPrefix) {
356  while (Namespace && Namespace->isInline()) {
357  // Ignore inline namespace;
358  Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
359  }
360  if (!Namespace) return nullptr;
361 
362  bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
364  Ctx,
365  createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
366  Namespace);
367 }
368 
370  const TypeDecl *TD,
371  bool FullyQualify,
372  bool WithGlobalNsPrefix) {
374  Ctx,
375  createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
376  false /*No TemplateKeyword*/,
377  TD->getTypeForDecl());
378 }
379 
380 /// \brief Return the fully qualified type, including fully-qualified
381 /// versions of any template parameters.
383  bool WithGlobalNsPrefix) {
384  // In case of myType* we need to strip the pointer first, fully
385  // qualify and attach the pointer once again.
386  if (isa<PointerType>(QT.getTypePtr())) {
387  // Get the qualifiers.
388  Qualifiers Quals = QT.getQualifiers();
389  QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
390  QT = Ctx.getPointerType(QT);
391  // Add back the qualifiers.
392  QT = Ctx.getQualifiedType(QT, Quals);
393  return QT;
394  }
395 
396  // In case of myType& we need to strip the reference first, fully
397  // qualify and attach the reference once again.
398  if (isa<ReferenceType>(QT.getTypePtr())) {
399  // Get the qualifiers.
400  bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
401  Qualifiers Quals = QT.getQualifiers();
402  QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
403  // Add the r- or l-value reference type back to the fully
404  // qualified one.
405  if (IsLValueRefTy)
406  QT = Ctx.getLValueReferenceType(QT);
407  else
408  QT = Ctx.getRValueReferenceType(QT);
409  // Add back the qualifiers.
410  QT = Ctx.getQualifiedType(QT, Quals);
411  return QT;
412  }
413 
414  // Remove the part of the type related to the type being a template
415  // parameter (we won't report it as part of the 'type name' and it
416  // is actually make the code below to be more complex (to handle
417  // those)
418  while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
419  // Get the qualifiers.
420  Qualifiers Quals = QT.getQualifiers();
421 
422  QT = dyn_cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
423 
424  // Add back the qualifiers.
425  QT = Ctx.getQualifiedType(QT, Quals);
426  }
427 
428  NestedNameSpecifier *Prefix = nullptr;
429  // Local qualifiers are attached to the QualType outside of the
430  // elaborated type. Retrieve them before descending into the
431  // elaborated type.
432  Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
433  QT = QualType(QT.getTypePtr(), 0);
435  if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
436  QT = ETypeInput->getNamedType();
437  assert(!QT.hasLocalQualifiers());
438  Keyword = ETypeInput->getKeyword();
439  }
440  // Create a nested name specifier if needed.
442  true /*FullyQualified*/,
443  WithGlobalNsPrefix);
444 
445  // In case of template specializations iterate over the arguments and
446  // fully qualify them as well.
447  if (isa<const TemplateSpecializationType>(QT.getTypePtr()) ||
448  isa<const RecordType>(QT.getTypePtr())) {
449  // We are asked to fully qualify and we have a Record Type (which
450  // may point to a template specialization) or Template
451  // Specialization Type. We need to fully qualify their arguments.
452 
453  const Type *TypePtr = getFullyQualifiedTemplateType(
454  Ctx, QT.getTypePtr(), WithGlobalNsPrefix);
455  QT = QualType(TypePtr, 0);
456  }
457  if (Prefix || Keyword != ETK_None) {
458  QT = Ctx.getElaboratedType(Keyword, Prefix, QT);
459  }
460  QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
461  return QT;
462 }
463 
465  const ASTContext &Ctx,
466  bool WithGlobalNsPrefix) {
467  PrintingPolicy Policy(Ctx.getPrintingPolicy());
468  Policy.SuppressScope = false;
469  Policy.AnonymousTagLocations = false;
470  Policy.PolishForDeclaration = true;
471  Policy.SuppressUnwrittenScope = true;
472  QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
473  return FQQT.getAsString(Policy);
474 }
475 
476 } // end namespace TypeName
477 } // 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:5508
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:616
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, TemplateName &TName, bool WithGlobalNsPrefix)
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Definition: ASTContext.h:1804
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...
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
Defines the C++ template declaration subclasses.
std::string getAsString() const
Definition: Type.h:942
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:1303
NamespaceDecl - Represent a C++ namespace.
Definition: Decl.h:461
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:547
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:4062
The collection of all-type qualifiers we support.
Definition: Type.h:118
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:128
NamespaceDecl * getNamespace()
Retrieve the namespace declaration aliased by this directive.
Definition: DeclCXX.h:2932
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
Definition: ASTMatchers.h:281
bool isTranslationUnit() const
Definition: DeclBase.h:1364
unsigned size() const
Retrieve the number of template arguments in this template argument list.
Definition: DeclTemplate.h:253
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:516
TypeDecl - Represents a declaration of a type.
Definition: Decl.h:2642
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:414
bool hasLocalQualifiers() const
Determine whether this particular QualType instance has any qualifiers, without looking through any t...
Definition: Type.h:720
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
const Type * getTypeForDecl() const
Definition: Decl.h:2663
ElaboratedTypeKeyword
The elaboration keyword that precedes a qualified type name or introduces an elaborated-type-specifie...
Definition: Type.h:4503
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:213
DeclContext * getDeclContext()
Definition: DeclBase.h:416
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:608
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:5489
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
Definition: TemplateBase.h:259
TagDecl - Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:2816
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:235
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:1215
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:378
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:6042
std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix=false)
Get the fully qualified name for a type.
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
Definition: DeclBase.cpp:1634
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1548
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:195
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
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:4518
The global specifier '::'. There is no stored value.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:5516
static NestedNameSpecifier * GlobalSpecifier(const ASTContext &Context)
Returns the nested name specifier representing the global scope.