clang 22.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"
13#include "clang/AST/Type.h"
14
15namespace clang {
16
17namespace TypeName {
18
19/// Create a NestedNameSpecifier for Namesp and its enclosing
20/// scopes.
21///
22/// \param[in] Ctx - the AST Context to be used.
23/// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
24/// is requested.
25/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
26/// specifier "::" should be prepended or not.
27static NestedNameSpecifier
28createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp,
29 bool WithGlobalNsPrefix);
30
31/// Create a NestedNameSpecifier for TagDecl and its enclosing
32/// scopes.
33///
34/// \param[in] Ctx - the AST Context to be used.
35/// \param[in] TD - the TagDecl for which a NestedNameSpecifier is
36/// requested.
37/// \param[in] FullyQualify - Convert all template arguments into fully
38/// qualified names.
39/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
40/// specifier "::" should be prepended or not.
41static NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx,
42 const TypeDecl *TD,
43 bool FullyQualify,
44 bool WithGlobalNsPrefix);
45
46static NestedNameSpecifier
47createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *decl,
48 bool FullyQualified,
49 bool WithGlobalNsPrefix);
50
51static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(
52 const ASTContext &Ctx, NestedNameSpecifier NNS, bool WithGlobalNsPrefix);
53
55 TemplateName &TName,
56 bool WithGlobalNsPrefix) {
57 bool Changed = false;
58 NestedNameSpecifier NNS = std::nullopt;
59
60 TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
61 // ArgTDecl won't be NULL because we asserted that this isn't a
62 // dependent context very early in the call chain.
63 assert(ArgTDecl != nullptr);
65
66 if (QTName &&
67 !QTName->hasTemplateKeyword() &&
68 (NNS = QTName->getQualifier())) {
70 getFullyQualifiedNestedNameSpecifier(Ctx, NNS, WithGlobalNsPrefix);
71 if (QNNS != NNS) {
72 Changed = true;
73 NNS = QNNS;
74 } else {
75 NNS = std::nullopt;
76 }
77 } else {
79 Ctx, ArgTDecl, true, WithGlobalNsPrefix);
80 }
81 if (NNS) {
82 TemplateName UnderlyingTN(ArgTDecl);
83 if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl())
84 UnderlyingTN = TemplateName(USD);
85 TName =
87 /*TemplateKeyword=*/false, UnderlyingTN);
88 Changed = true;
89 }
90 return Changed;
91}
92
95 bool WithGlobalNsPrefix) {
96 bool Changed = false;
97
98 // Note: we do not handle TemplateArgument::Expression, to replace it
99 // we need the information for the template instance decl.
100
101 if (Arg.getKind() == TemplateArgument::Template) {
102 TemplateName TName = Arg.getAsTemplate();
103 Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
104 if (Changed) {
105 Arg = TemplateArgument(TName);
106 }
107 } else if (Arg.getKind() == TemplateArgument::Type) {
108 QualType SubTy = Arg.getAsType();
109 // Check if the type needs more desugaring and recurse.
110 QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
111 if (QTFQ != SubTy) {
112 Arg = TemplateArgument(QTFQ);
113 Changed = true;
114 }
115 }
116 return Changed;
117}
118
120 const TagType *TSTRecord,
122 NestedNameSpecifier Qualifier,
123 bool WithGlobalNsPrefix) {
124 // We are asked to fully qualify and we have a Record Type,
125 // which can point to a template instantiation with no sugar in any of
126 // its template argument, however we still need to fully qualify them.
127
128 const auto *TD = TSTRecord->getOriginalDecl();
129 const auto *TSTDecl = dyn_cast<ClassTemplateSpecializationDecl>(TD);
130 if (!TSTDecl)
131 return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
132 .getTypePtr();
133
134 const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
135
136 bool MightHaveChanged = false;
138 for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
139 // cheap to copy and potentially modified by
140 // getFullyQualifedTemplateArgument
141 TemplateArgument Arg(TemplateArgs[I]);
142 MightHaveChanged |=
143 getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
144 FQArgs.push_back(Arg);
145 }
146
147 if (!MightHaveChanged)
148 return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false)
149 .getTypePtr();
150 // If a fully qualified arg is different from the unqualified arg,
151 // allocate new type in the AST.
153 Qualifier, /*TemplateKeyword=*/false,
154 TemplateName(TSTDecl->getSpecializedTemplate()));
156 Keyword, TN, FQArgs,
157 /*CanonicalArgs=*/{}, TSTRecord->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
164static const Type *
166 const TemplateSpecializationType *TST,
167 bool WithGlobalNsPrefix) {
168 TemplateName TName = TST->getTemplateName();
169 bool MightHaveChanged =
170 getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
172 // Cheap to copy and potentially modified by
173 // getFullyQualifedTemplateArgument.
174 for (TemplateArgument Arg : TST->template_arguments()) {
175 MightHaveChanged |=
176 getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
177 FQArgs.push_back(Arg);
178 }
179
180 if (!MightHaveChanged)
181 return TST;
182
183 QualType NewQT =
184 Ctx.getTemplateSpecializationType(TST->getKeyword(), TName, FQArgs,
185 /*CanonicalArgs=*/{}, TST->desugar());
186 // getTemplateSpecializationType returns a fully qualified
187 // version of the specialization itself, so no need to qualify
188 // it.
189 return NewQT.getTypePtr();
190}
191
193 bool FullyQualify,
194 bool WithGlobalNsPrefix) {
195 const DeclContext *DC = D->getDeclContext();
196 if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
197 while (NS && NS->isInline()) {
198 // Ignore inline namespace;
199 NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
200 }
201 if (NS && NS->getDeclName()) {
202 return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
203 }
204 return std::nullopt; // no starting '::', no anonymous
205 }
206 if (const auto *TD = dyn_cast<TagDecl>(DC))
207 return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
208 if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC))
209 return createNestedNameSpecifier(Ctx, TDD, FullyQualify,
210 WithGlobalNsPrefix);
211 if (WithGlobalNsPrefix && DC->isTranslationUnit())
213 return std::nullopt; // no starting '::' if |WithGlobalNsPrefix| is false
214}
215
216/// Return a fully qualified version of this name specifier.
218 const ASTContext &Ctx, NestedNameSpecifier Scope, bool WithGlobalNsPrefix) {
219 switch (Scope.getKind()) {
221 llvm_unreachable("can't fully qualify the empty nested name specifier");
224 // Already fully qualified
225 return Scope;
228 Ctx, Scope.getAsNamespaceAndPrefix().Namespace->getNamespace(),
229 WithGlobalNsPrefix);
231 const Type *Type = Scope.getAsType();
232 // Find decl context.
233 const TypeDecl *TD;
234 if (const TagType *TagDeclType = Type->getAs<TagType>())
235 TD = TagDeclType->getOriginalDecl();
236 else if (const auto *D = dyn_cast<TypedefType>(Type))
237 TD = D->getDecl();
238 else
239 return Scope;
240 return TypeName::createNestedNameSpecifier(Ctx, TD, /*FullyQualify=*/true,
241 WithGlobalNsPrefix);
242 }
243 }
244 llvm_unreachable("bad NNS kind");
245}
246
247/// Create a nested name specifier for the declaring context of
248/// the type.
251 bool FullyQualified,
252 bool WithGlobalNsPrefix) {
253 assert(Decl);
254
256 const auto *Outer = dyn_cast<NamedDecl>(DC);
257 const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
258 if (OuterNS && OuterNS->isAnonymousNamespace())
259 OuterNS = dyn_cast<NamespaceDecl>(OuterNS->getParent());
260 if (Outer) {
261 if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
262 if (ClassTemplateDecl *ClassTempl =
263 CxxDecl->getDescribedClassTemplate()) {
264 // We are in the case of a type(def) that was declared in a
265 // class template but is *not* type dependent. In clang, it
266 // gets attached to the class template declaration rather than
267 // any specific class template instantiation. This result in
268 // 'odd' fully qualified typename:
269 //
270 // vector<_Tp,_Alloc>::size_type
271 //
272 // Make the situation is 'useable' but looking a bit odd by
273 // picking a random instance as the declaring context.
274 if (!ClassTempl->specializations().empty()) {
275 Decl = *(ClassTempl->spec_begin());
276 Outer = dyn_cast<NamedDecl>(Decl);
277 OuterNS = dyn_cast<NamespaceDecl>(Decl);
278 }
279 }
280 }
281
282 if (OuterNS) {
283 return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
284 } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
286 Ctx, TD, FullyQualified, WithGlobalNsPrefix);
287 } else if (isa<TranslationUnitDecl>(Outer)) {
288 // Context is the TU. Nothing needs to be done.
289 return std::nullopt;
290 } else {
291 // Decl's context was neither the TU, a namespace, nor a
292 // TagDecl, which means it is a type local to a scope, and not
293 // accessible at the end of the TU.
294 return std::nullopt;
295 }
296 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
298 }
299 return std::nullopt;
300}
301
302/// Create a nested name specifier for the declaring context of
303/// the type.
306 bool FullyQualified,
307 bool WithGlobalNsPrefix) {
308 if (!TypePtr)
309 return std::nullopt;
310
311 Decl *Decl = nullptr;
312 // There are probably other cases ...
313 if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
314 Decl = TDT->getDecl();
315 } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
316 Decl = TagDeclType->getOriginalDecl();
317 } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
318 Decl = TST->getTemplateName().getAsTemplateDecl();
319 } else {
320 Decl = TypePtr->getAsCXXRecordDecl();
321 }
322
323 if (!Decl)
324 return std::nullopt;
325
327 Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
328}
329
332 bool WithGlobalNsPrefix) {
333 while (Namespace && Namespace->isInline()) {
334 // Ignore inline namespace;
335 Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
336 }
337 if (!Namespace)
338 return std::nullopt;
339
340 bool FullyQualify = true; // doesn't matter, DeclContexts are namespaces
341 return NestedNameSpecifier(
342 Ctx, Namespace,
343 createOuterNNS(Ctx, Namespace, FullyQualify, WithGlobalNsPrefix));
344}
345
347 const TypeDecl *TD,
348 bool FullyQualify,
349 bool WithGlobalNsPrefix) {
350 const Type *TypePtr = Ctx.getTypeDeclType(TD).getTypePtr();
351 if (auto *RD = dyn_cast<TagType>(TypePtr)) {
352 // We are asked to fully qualify and we have a Record Type (which
353 // may point to a template specialization) or Template
354 // Specialization Type. We need to fully qualify their arguments.
357 createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
358 WithGlobalNsPrefix);
359 } else if (auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
360 TypePtr = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
361 }
362 return NestedNameSpecifier(TypePtr);
363}
364
365/// Return the fully qualified type, including fully-qualified
366/// versions of any template parameters.
368 bool WithGlobalNsPrefix) {
369 // In case of myType* we need to strip the pointer first, fully
370 // qualify and attach the pointer once again.
371 if (isa<PointerType>(QT.getTypePtr())) {
372 // Get the qualifiers.
373 Qualifiers Quals = QT.getQualifiers();
374 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
375 QT = Ctx.getPointerType(QT);
376 // Add back the qualifiers.
377 QT = Ctx.getQualifiedType(QT, Quals);
378 return QT;
379 }
380
381 if (auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) {
382 // Get the qualifiers.
383 Qualifiers Quals = QT.getQualifiers();
384 // Fully qualify the pointee and class types.
385 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
387 Ctx, MPT->getQualifier(), WithGlobalNsPrefix);
388 QT = Ctx.getMemberPointerType(QT, Qualifier,
389 MPT->getMostRecentCXXRecordDecl());
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 // Handle types with attributes such as `unique_ptr<int> _Nonnull`.
414 if (auto *AT = dyn_cast<AttributedType>(QT.getTypePtr())) {
415 QualType NewModified =
416 getFullyQualifiedType(AT->getModifiedType(), Ctx, WithGlobalNsPrefix);
417 QualType NewEquivalent =
418 getFullyQualifiedType(AT->getEquivalentType(), Ctx, WithGlobalNsPrefix);
420 return Ctx.getQualifiedType(
421 Ctx.getAttributedType(AT->getAttrKind(), NewModified, NewEquivalent),
422 Qualifiers);
423 }
424
425 // Remove the part of the type related to the type being a template
426 // parameter (we won't report it as part of the 'type name' and it
427 // is actually make the code below to be more complex (to handle
428 // those)
430 // Get the qualifiers.
431 Qualifiers Quals = QT.getQualifiers();
432
433 QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
434
435 // Add back the qualifiers.
436 QT = Ctx.getQualifiedType(QT, Quals);
437 }
438
439 if (const auto *TST =
440 dyn_cast<const TemplateSpecializationType>(QT.getTypePtr())) {
441
442 const Type *T = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
443 if (T == TST)
444 return QT;
445 return Ctx.getQualifiedType(T, QT.getQualifiers());
446 }
447
448 // Local qualifiers are attached to the QualType outside of the
449 // elaborated type. Retrieve them before descending into the
450 // elaborated type.
451 Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
452 QT = QualType(QT.getTypePtr(), 0);
453
454 // We don't consider the alias introduced by `using a::X` as a new type.
455 // The qualified name is still a::X.
456 if (const auto *UT = QT->getAs<UsingType>()) {
457 QT = Ctx.getQualifiedType(UT->desugar(), PrefixQualifiers);
458 return getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
459 }
460
461 // Create a nested name specifier if needed.
463 Ctx, QT.getTypePtr(), true /*FullyQualified*/, WithGlobalNsPrefix);
464
465 // In case of template specializations iterate over the arguments and
466 // fully qualify them as well.
467 if (const auto *TT = dyn_cast<TagType>(QT.getTypePtr())) {
468 // We are asked to fully qualify and we have a Record Type (which
469 // may point to a template specialization) or Template
470 // Specialization Type. We need to fully qualify their arguments.
471
472 const Type *TypePtr = getFullyQualifiedTemplateType(
473 Ctx, TT, TT->getKeyword(), Prefix, WithGlobalNsPrefix);
474 QT = QualType(TypePtr, 0);
475 } else if (const auto *TT = dyn_cast<TypedefType>(QT.getTypePtr())) {
476 QT = Ctx.getTypedefType(
477 TT->getKeyword(), Prefix, TT->getDecl(),
478 getFullyQualifiedType(TT->desugar(), Ctx, WithGlobalNsPrefix));
479 } else {
480 assert(!Prefix && "Unhandled type node");
481 }
482 QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
483 return QT;
484}
485
487 const ASTContext &Ctx,
488 const PrintingPolicy &Policy,
489 bool WithGlobalNsPrefix) {
490 QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
491 return FQQT.getAsString(Policy);
492}
493
495 const Decl *Decl,
496 bool WithGlobalNsPrefix) {
497 return createNestedNameSpecifierForScopeOf(Ctx, Decl, /*FullyQualified=*/true,
498 WithGlobalNsPrefix);
499}
500
501} // end namespace TypeName
502} // 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:188
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:1449
bool isTranslationUnit() const
Definition DeclBase.h:2185
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
DeclContext * getDeclContext()
Definition DeclBase.h:448
Represent a C++ namespace.
Definition Decl.h:591
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:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8285
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8325
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1332
Qualifiers getLocalQualifiers() const
Retrieve the set of qualifiers local to this particular QualType instance, not including any qualifie...
Definition TypeBase.h:8317
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:331
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:3510
The base class of the type hierarchy.
Definition TypeBase.h:1833
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:752
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9101
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Definition DeclCXX.h:3393
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.
The JSON file list parser is used to communicate input to InstallAPI.
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:560
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:5863
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:5884
Describes how types, statements, expressions, and declarations should be printed.