clang 24.0.0git
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
12#include "clang/AST/Mangle.h"
14#include "clang/AST/Type.h"
15
16namespace clang {
17
18namespace TypeName {
19
20/// Create a NestedNameSpecifier for Namesp and its enclosing
21/// scopes.
22///
23/// \param[in] Ctx - the AST Context to be used.
24/// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
25/// is requested.
26/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
27/// specifier "::" should be prepended or not.
28static NestedNameSpecifier
29createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp,
30 bool WithGlobalNsPrefix);
31
32/// Create a NestedNameSpecifier for TagDecl and its enclosing
33/// scopes.
34///
35/// \param[in] Ctx - the AST Context to be used.
36/// \param[in] TD - the TagDecl for which a NestedNameSpecifier is
37/// requested.
38/// \param[in] FullyQualify - Convert all template arguments into fully
39/// qualified names.
40/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
41/// specifier "::" should be prepended or not.
42static NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx,
43 const TypeDecl *TD,
44 bool FullyQualify,
45 bool WithGlobalNsPrefix);
46
47static NestedNameSpecifier
48createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *decl,
49 bool FullyQualified,
50 bool WithGlobalNsPrefix);
51
52static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(
53 const ASTContext &Ctx, NestedNameSpecifier NNS, bool WithGlobalNsPrefix);
54
56 TemplateName &TName,
57 bool WithGlobalNsPrefix) {
58 bool Changed = false;
59 NestedNameSpecifier NNS = std::nullopt;
60
61 TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
62 if (!ArgTDecl) // ArgTDecl can be null in dependent contexts.
63 return false;
64
66
67 if (QTName &&
68 !QTName->hasTemplateKeyword() &&
69 (NNS = QTName->getQualifier())) {
71 getFullyQualifiedNestedNameSpecifier(Ctx, NNS, WithGlobalNsPrefix);
72 if (QNNS != NNS) {
73 Changed = true;
74 NNS = QNNS;
75 } else {
76 NNS = std::nullopt;
77 }
78 } else {
80 Ctx, ArgTDecl, true, WithGlobalNsPrefix);
81 }
82 if (NNS) {
83 TemplateName UnderlyingTN(ArgTDecl);
84 if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl())
85 UnderlyingTN = TemplateName(USD);
86 TName =
88 /*TemplateKeyword=*/false, UnderlyingTN);
89 Changed = true;
90 }
91 return Changed;
92}
93
96 bool WithGlobalNsPrefix) {
97 bool Changed = false;
98
99 // Note: we do not handle TemplateArgument::Expression, to replace it
100 // we need the information for the template instance decl.
101
102 if (Arg.getKind() == TemplateArgument::Template) {
103 TemplateName TName = Arg.getAsTemplate();
104 Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
105 if (Changed) {
106 Arg = TemplateArgument(TName);
107 }
108 } else if (Arg.getKind() == TemplateArgument::Type) {
109 QualType SubTy = Arg.getAsType();
110 // Check if the type needs more desugaring and recurse.
111 QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
112 if (QTFQ != SubTy) {
113 Arg = TemplateArgument(QTFQ);
114 Changed = true;
115 }
116 }
117 return Changed;
118}
119
121 const TagType *TSTRecord,
123 NestedNameSpecifier Qualifier,
124 bool WithGlobalNsPrefix) {
125 // We are asked to fully qualify and we have a Record Type,
126 // which can point to a template instantiation with no sugar in any of
127 // its template argument, however we still need to fully qualify them.
128
129 const auto *TD = TSTRecord->getDecl();
130 const auto *TSTDecl = dyn_cast<ClassTemplateSpecializationDecl>(TD);
131 if (!TSTDecl)
132 return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
133 .getTypePtr();
134
135 const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
136
137 bool MightHaveChanged = false;
139 for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
140 // cheap to copy and potentially modified by
141 // getFullyQualifedTemplateArgument
142 TemplateArgument Arg(TemplateArgs[I]);
143 MightHaveChanged |=
144 getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
145 FQArgs.push_back(Arg);
146 }
147
148 if (!MightHaveChanged)
149 return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
150 .getTypePtr();
151 // If a fully qualified arg is different from the unqualified arg,
152 // allocate new type in the AST.
154 Qualifier, /*TemplateKeyword=*/false,
155 TemplateName(TSTDecl->getSpecializedTemplate()));
157 Keyword, TN, FQArgs,
158 /*CanonicalArgs=*/{}, TSTRecord->getCanonicalTypeInternal());
159 // getTemplateSpecializationType returns a fully qualified
160 // version of the specialization itself, so no need to qualify
161 // it.
162 return QT.getTypePtr();
163}
164
165static const Type *
167 const TemplateSpecializationType *TST,
168 bool WithGlobalNsPrefix) {
169 TemplateName TName = TST->getTemplateName();
170 bool MightHaveChanged =
171 getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
173 // Cheap to copy and potentially modified by
174 // getFullyQualifedTemplateArgument.
175 for (TemplateArgument Arg : TST->template_arguments()) {
176 MightHaveChanged |=
177 getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
178 FQArgs.push_back(Arg);
179 }
180
181 if (!MightHaveChanged)
182 return TST;
183
184 QualType NewQT =
185 Ctx.getTemplateSpecializationType(TST->getKeyword(), TName, FQArgs,
186 /*CanonicalArgs=*/{}, TST->desugar());
187 // getTemplateSpecializationType returns a fully qualified
188 // version of the specialization itself, so no need to qualify
189 // it.
190 return NewQT.getTypePtr();
191}
192
194 bool FullyQualify,
195 bool WithGlobalNsPrefix) {
196 const DeclContext *DC = D->getDeclContext();
197 if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
198 while (NS && NS->isInline()) {
199 // Ignore inline namespace;
200 NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
201 }
202 if (NS && NS->getDeclName()) {
203 return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
204 }
205 return std::nullopt; // no starting '::', no anonymous
206 }
207 if (const auto *TD = dyn_cast<TagDecl>(DC))
208 return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
209 if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC))
210 return createNestedNameSpecifier(Ctx, TDD, FullyQualify,
211 WithGlobalNsPrefix);
212 if (WithGlobalNsPrefix && DC->isTranslationUnit())
214 return std::nullopt; // no starting '::' if |WithGlobalNsPrefix| is false
215}
216
217/// Return a fully qualified version of this name specifier.
219 const ASTContext &Ctx, NestedNameSpecifier Scope, bool WithGlobalNsPrefix) {
220 switch (Scope.getKind()) {
222 llvm_unreachable("can't fully qualify the empty nested name specifier");
225 // Already fully qualified
226 return Scope;
229 Ctx, Scope.getAsNamespaceAndPrefix().Namespace->getNamespace(),
230 WithGlobalNsPrefix);
232 const Type *Type = Scope.getAsType();
233 // Find decl context.
234 const TypeDecl *TD;
235 if (const TagType *TagDeclType = Type->getAs<TagType>())
236 TD = TagDeclType->getDecl();
237 else if (const auto *D = dyn_cast<TypedefType>(Type))
238 TD = D->getDecl();
239 else
240 return Scope;
241 return TypeName::createNestedNameSpecifier(Ctx, TD, /*FullyQualify=*/true,
242 WithGlobalNsPrefix);
243 }
244 }
245 llvm_unreachable("bad NNS kind");
246}
247
248/// Create a nested name specifier for the declaring context of
249/// the type.
252 bool FullyQualified,
253 bool WithGlobalNsPrefix) {
254 assert(Decl);
255
256 // Some declaration cannot be qualified.
258 return std::nullopt;
260 const auto *Outer = dyn_cast<NamedDecl>(DC);
261 const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
262 if (OuterNS && OuterNS->isAnonymousNamespace())
263 OuterNS = dyn_cast<NamespaceDecl>(OuterNS->getParent());
264 if (Outer) {
265 if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
266 if (ClassTemplateDecl *ClassTempl =
267 CxxDecl->getDescribedClassTemplate()) {
268 // We are in the case of a type(def) that was declared in a
269 // class template but is *not* type dependent. In clang, it
270 // gets attached to the class template declaration rather than
271 // any specific class template instantiation. This result in
272 // 'odd' fully qualified typename:
273 //
274 // vector<_Tp,_Alloc>::size_type
275 //
276 // Make the situation is 'useable' but looking a bit odd by
277 // picking a random instance as the declaring context.
278 if (!ClassTempl->specializations().empty()) {
279 Decl = *(ClassTempl->spec_begin());
280 Outer = dyn_cast<NamedDecl>(Decl);
281 OuterNS = dyn_cast<NamespaceDecl>(Decl);
282 }
283 }
284 }
285
286 if (OuterNS) {
287 return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
288 } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
290 Ctx, TD, FullyQualified, WithGlobalNsPrefix);
291 } else if (isa<TranslationUnitDecl>(Outer)) {
292 // Context is the TU. Nothing needs to be done.
293 return std::nullopt;
294 } else {
295 // Decl's context was neither the TU, a namespace, nor a
296 // TagDecl, which means it is a type local to a scope, and not
297 // accessible at the end of the TU.
298 return std::nullopt;
299 }
300 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
302 }
303 return std::nullopt;
304}
305
306/// Create a nested name specifier for the declaring context of
307/// the type.
310 bool FullyQualified,
311 bool WithGlobalNsPrefix) {
312 if (!TypePtr)
313 return std::nullopt;
314
315 Decl *Decl = nullptr;
316 // There are probably other cases ...
317 if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
318 Decl = TDT->getDecl();
319 } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
320 Decl = TagDeclType->getDecl();
321 } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
322 Decl = TST->getTemplateName().getAsTemplateDecl();
323 } else {
324 Decl = TypePtr->getAsCXXRecordDecl();
325 }
326
327 if (!Decl)
328 return std::nullopt;
329
331 Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
332}
333
336 bool WithGlobalNsPrefix) {
337 while (Namespace && Namespace->isInline()) {
338 // Ignore inline namespace;
339 Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
340 }
341 if (!Namespace)
342 return std::nullopt;
343
344 bool FullyQualify = true; // doesn't matter, DeclContexts are namespaces
345 return NestedNameSpecifier(
346 Ctx, Namespace,
347 createOuterNNS(Ctx, Namespace, FullyQualify, WithGlobalNsPrefix));
348}
349
351 const TypeDecl *TD,
352 bool FullyQualify,
353 bool WithGlobalNsPrefix) {
354 const Type *TypePtr = Ctx.getTypeDeclType(TD).getTypePtr();
355 if (auto *RD = dyn_cast<TagType>(TypePtr)) {
356 // We are asked to fully qualify and we have a Record Type (which
357 // may point to a template specialization) or Template
358 // Specialization Type. We need to fully qualify their arguments.
361 createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
362 WithGlobalNsPrefix);
363 } else if (auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
364 TypePtr = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
365 }
366 return NestedNameSpecifier(TypePtr);
367}
368
369/// Return the fully qualified type, including fully-qualified
370/// versions of any template parameters.
372 bool WithGlobalNsPrefix) {
373 // In case of myType* we need to strip the pointer first, fully
374 // qualify and attach the pointer once again.
375 if (isa<PointerType>(QT.getTypePtr())) {
376 // Get the qualifiers.
377 Qualifiers Quals = QT.getQualifiers();
378 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
379 QT = Ctx.getPointerType(QT);
380 // Add back the qualifiers.
381 QT = Ctx.getQualifiedType(QT, Quals);
382 return QT;
383 }
384
385 if (auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) {
386 // Get the qualifiers.
387 Qualifiers Quals = QT.getQualifiers();
388 // Fully qualify the pointee and class types.
389 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
391 Ctx, MPT->getQualifier(), WithGlobalNsPrefix);
392 QT = Ctx.getMemberPointerType(QT, Qualifier,
393 MPT->getMostRecentCXXRecordDecl());
394 // Add back the qualifiers.
395 QT = Ctx.getQualifiedType(QT, Quals);
396 return QT;
397 }
398
399 // In case of myType& we need to strip the reference first, fully
400 // qualify and attach the reference once again.
401 if (isa<ReferenceType>(QT.getTypePtr())) {
402 // Get the qualifiers.
403 bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
404 Qualifiers Quals = QT.getQualifiers();
405 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
406 // Add the r- or l-value reference type back to the fully
407 // qualified one.
408 if (IsLValueRefTy)
409 QT = Ctx.getLValueReferenceType(QT);
410 else
411 QT = Ctx.getRValueReferenceType(QT);
412 // Add back the qualifiers.
413 QT = Ctx.getQualifiedType(QT, Quals);
414 return QT;
415 }
416
417 // Handle types with attributes such as `unique_ptr<int> _Nonnull`.
418 if (auto *AT = dyn_cast<AttributedType>(QT.getTypePtr())) {
419 QualType NewModified =
420 getFullyQualifiedType(AT->getModifiedType(), Ctx, WithGlobalNsPrefix);
421 QualType NewEquivalent =
422 getFullyQualifiedType(AT->getEquivalentType(), Ctx, WithGlobalNsPrefix);
424 return Ctx.getQualifiedType(
425 Ctx.getAttributedType(AT->getAttrKind(), NewModified, NewEquivalent),
426 Qualifiers);
427 }
428
429 // Remove the part of the type related to the type being a template
430 // parameter (we won't report it as part of the 'type name' and it
431 // is actually make the code below to be more complex (to handle
432 // those)
434 // Get the qualifiers.
435 Qualifiers Quals = QT.getQualifiers();
436
437 QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
438
439 // Add back the qualifiers.
440 QT = Ctx.getQualifiedType(QT, Quals);
441 }
442
443 if (const auto *TST =
444 dyn_cast<const TemplateSpecializationType>(QT.getTypePtr())) {
445
446 const Type *T = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
447 if (T == TST)
448 return QT;
449 return Ctx.getQualifiedType(T, QT.getQualifiers());
450 }
451
452 // Local qualifiers are attached to the QualType outside of the
453 // elaborated type. Retrieve them before descending into the
454 // elaborated type.
455 Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
456 QT = QualType(QT.getTypePtr(), 0);
457
458 // We don't consider the alias introduced by `using a::X` as a new type.
459 // The qualified name is still a::X.
460 if (const auto *UT = QT->getAs<UsingType>()) {
461 QT = Ctx.getQualifiedType(UT->desugar(), PrefixQualifiers);
462 return getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
463 }
464
465 // Create a nested name specifier if needed.
467 Ctx, QT.getTypePtr(), true /*FullyQualified*/, WithGlobalNsPrefix);
468
469 // In case of template specializations iterate over the arguments and
470 // fully qualify them as well.
471 if (const auto *TT = dyn_cast<TagType>(QT.getTypePtr())) {
472 // We are asked to fully qualify and we have a Record Type (which
473 // may point to a template specialization) or Template
474 // Specialization Type. We need to fully qualify their arguments.
475
476 const Type *TypePtr = getFullyQualifiedTemplateType(
477 Ctx, TT, TT->getKeyword(), Prefix, WithGlobalNsPrefix);
478 QT = QualType(TypePtr, 0);
479 } else if (const auto *TT = dyn_cast<TypedefType>(QT.getTypePtr())) {
480 QT = Ctx.getTypedefType(
481 TT->getKeyword(), Prefix, TT->getDecl(),
482 getFullyQualifiedType(TT->desugar(), Ctx, WithGlobalNsPrefix));
483 } else {
484 assert(!Prefix && "Unhandled type node");
485 }
486 QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
487 return QT;
488}
489
491 const ASTContext &Ctx,
492 const PrintingPolicy &Policy,
493 bool WithGlobalNsPrefix) {
494 QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
495 return FQQT.getAsString(Policy);
496}
497
499 const Decl *Decl,
500 bool WithGlobalNsPrefix) {
501 return createNestedNameSpecifierForScopeOf(Ctx, Decl, /*FullyQualified=*/true,
502 WithGlobalNsPrefix);
503}
504
505} // end namespace TypeName
506} // end namespace clang
Defines the C++ template declaration subclasses.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
QualType getAttributedType(attr::Kind attrKind, QualType modifiedType, QualType equivalentType, const Attr *attr=nullptr) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
QualType getTypedefType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypedefNameDecl *Decl, QualType UnderlyingType=QualType(), std::optional< bool > TypeMatchesDeclOrNone=std::nullopt) const
Return the unique reference to the type for the specified typedef-name decl.
QualType getTemplateSpecializationType(ElaboratedTypeKeyword Keyword, TemplateName T, ArrayRef< TemplateArgument > SpecifiedArgs, ArrayRef< TemplateArgument > CanonicalArgs, QualType Underlying=QualType()) const
TemplateName getQualifiedTemplateName(NestedNameSpecifier Qualifier, bool TemplateKeyword, TemplateName Template) const
Retrieve the template name that represents a qualified template name such as std::vector.
QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType getTagType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *TD, bool OwnsTag) const
Declaration of a class template.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
bool isTranslationUnit() const
Definition DeclBase.h:2202
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isTemplateParameter() const
isTemplateParameter - Determines whether this declaration is a template parameter.
Definition DeclBase.h:2823
DeclContext * getDeclContext()
Definition DeclBase.h:456
Represent a C++ namespace.
Definition Decl.h:593
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
static constexpr NestedNameSpecifier getGlobal()
@ MicrosoftSuper
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace-like entity, stored as a NamespaceBaseDecl*.
A (possibly-)qualified type.
Definition TypeBase.h:938
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8501
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8541
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1348
Qualifiers getLocalQualifiers() const
Retrieve the set of qualifiers local to this particular QualType instance, not including any qualifie...
Definition TypeBase.h:8533
Represents a template name as written in source code.
NestedNameSpecifier getQualifier() const
Return the nested name specifier that qualifies this name.
bool hasTemplateKeyword() const
Whether the template name was prefixed by the "template" keyword.
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
A template argument list.
unsigned size() const
Retrieve the number of template arguments in this template argument list.
Represents a template argument.
QualType getAsType() const
Retrieve the type for a type template argument.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
@ Template
The template argument is a template name that was provided for a template template parameter.
@ Type
The template argument is a type.
ArgKind getKind() const
Return the kind of stored template argument.
The base class of all kinds of template declarations (e.g., class, function, etc.).
Represents a C++ template name within the type system.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
QualifiedTemplateName * getAsQualifiedTemplateName() const
Retrieve the underlying qualified template name structure, if any.
UsingShadowDecl * getAsUsingShadowDecl() const
Retrieve the using shadow declaration through which the underlying template declaration is introduced...
Represents a declaration of a type.
Definition Decl.h:3648
The base class of the type hierarchy.
Definition TypeBase.h:1879
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9337
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Definition DeclCXX.h:3428
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, TemplateName &TName, bool WithGlobalNsPrefix)
static const Type * getFullyQualifiedTemplateType(const ASTContext &Ctx, const TagType *TSTRecord, ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, bool WithGlobalNsPrefix)
static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, TemplateArgument &Arg, bool WithGlobalNsPrefix)
static NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp, bool WithGlobalNsPrefix)
Create a NestedNameSpecifier for Namesp and its enclosing scopes.
static NestedNameSpecifier createOuterNNS(const ASTContext &Ctx, const Decl *D, bool FullyQualify, bool WithGlobalNsPrefix)
std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, const PrintingPolicy &Policy, bool WithGlobalNsPrefix=false)
Get the fully qualified name for a type.
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.
static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(const ASTContext &Ctx, NestedNameSpecifier NNS, bool WithGlobalNsPrefix)
Return a fully qualified version of this name specifier.
NestedNameSpecifier getFullyQualifiedDeclaredContext(const ASTContext &Ctx, const Decl *Decl, bool WithGlobalNsPrefix=false)
Get the fully qualified name for the declared context of a declaration.
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...
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
const FunctionProtoType * T
@ Keyword
The name has been typo-corrected to a keyword.
Definition Sema.h:556
U cast(CodeGen::Address addr)
Definition Address.h:327
ElaboratedTypeKeyword
The elaboration keyword that precedes a qualified type name or introduces an elaborated-type-specifie...
Definition TypeBase.h:6019
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:6040
Describes how types, statements, expressions, and declarations should be printed.