clang 20.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
14namespace clang {
15
16namespace TypeName {
17
18/// Create a NestedNameSpecifier for Namesp and its enclosing
19/// scopes.
20///
21/// \param[in] Ctx - the AST Context to be used.
22/// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
23/// is requested.
24/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
25/// specifier "::" should be prepended or not.
26static NestedNameSpecifier *createNestedNameSpecifier(
27 const ASTContext &Ctx,
28 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(
42 const ASTContext &Ctx, const TypeDecl *TD,
43 bool FullyQualify, bool WithGlobalNsPrefix);
44
45static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
46 const ASTContext &Ctx, const Decl *decl,
47 bool FullyQualified, bool WithGlobalNsPrefix);
48
49static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
50 const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
51
53 TemplateName &TName,
54 bool WithGlobalNsPrefix) {
55 bool Changed = false;
56 NestedNameSpecifier *NNS = nullptr;
57
58 TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
59 // ArgTDecl won't be NULL because we asserted that this isn't a
60 // dependent context very early in the call chain.
61 assert(ArgTDecl != nullptr);
63
64 if (QTName &&
65 !QTName->hasTemplateKeyword() &&
66 (NNS = QTName->getQualifier())) {
68 Ctx, NNS, WithGlobalNsPrefix);
69 if (QNNS != NNS) {
70 Changed = true;
71 NNS = QNNS;
72 } else {
73 NNS = nullptr;
74 }
75 } else {
77 Ctx, ArgTDecl, true, WithGlobalNsPrefix);
78 }
79 if (NNS) {
80 TemplateName UnderlyingTN(ArgTDecl);
81 if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl())
82 UnderlyingTN = TemplateName(USD);
83 TName =
85 /*TemplateKeyword=*/false, UnderlyingTN);
86 Changed = true;
87 }
88 return Changed;
89}
90
93 bool WithGlobalNsPrefix) {
94 bool Changed = false;
95
96 // Note: we do not handle TemplateArgument::Expression, to replace it
97 // we need the information for the template instance decl.
98
100 TemplateName TName = Arg.getAsTemplate();
101 Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
102 if (Changed) {
103 Arg = TemplateArgument(TName);
104 }
105 } else if (Arg.getKind() == TemplateArgument::Type) {
106 QualType SubTy = Arg.getAsType();
107 // Check if the type needs more desugaring and recurse.
108 QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
109 if (QTFQ != SubTy) {
110 Arg = TemplateArgument(QTFQ);
111 Changed = true;
112 }
113 }
114 return Changed;
115}
116
118 const Type *TypePtr,
119 bool WithGlobalNsPrefix) {
120 // DependentTemplateTypes exist within template declarations and
121 // definitions. Therefore we shouldn't encounter them at the end of
122 // a translation unit. If we do, the caller has made an error.
123 assert(!isa<DependentTemplateSpecializationType>(TypePtr));
124 // In case of template specializations, iterate over the arguments
125 // and fully qualify them as well.
126 if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) {
127 bool MightHaveChanged = false;
129 // Cheap to copy and potentially modified by
130 // getFullyQualifedTemplateArgument.
131 for (TemplateArgument Arg : TST->template_arguments()) {
132 MightHaveChanged |= getFullyQualifiedTemplateArgument(
133 Ctx, Arg, WithGlobalNsPrefix);
134 FQArgs.push_back(Arg);
135 }
136
137 // If a fully qualified arg is different from the unqualified arg,
138 // allocate new type in the AST.
139 if (MightHaveChanged) {
141 TST->getTemplateName(), FQArgs,
142 TST->getCanonicalTypeInternal());
143 // getTemplateSpecializationType returns a fully qualified
144 // version of the specialization itself, so no need to qualify
145 // it.
146 return QT.getTypePtr();
147 }
148 } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) {
149 // We are asked to fully qualify and we have a Record Type,
150 // which can point to a template instantiation with no sugar in any of
151 // its template argument, however we still need to fully qualify them.
152
153 if (const auto *TSTDecl =
154 dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
155 const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
156
157 bool MightHaveChanged = false;
159 for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
160 // cheap to copy and potentially modified by
161 // getFullyQualifedTemplateArgument
162 TemplateArgument Arg(TemplateArgs[I]);
163 MightHaveChanged |= getFullyQualifiedTemplateArgument(
164 Ctx, Arg, WithGlobalNsPrefix);
165 FQArgs.push_back(Arg);
166 }
167
168 // If a fully qualified arg is different from the unqualified arg,
169 // allocate new type in the AST.
170 if (MightHaveChanged) {
171 TemplateName TN(TSTDecl->getSpecializedTemplate());
173 TN, FQArgs,
174 TSTRecord->getCanonicalTypeInternal());
175 // getTemplateSpecializationType returns a fully qualified
176 // version of the specialization itself, so no need to qualify
177 // it.
178 return QT.getTypePtr();
179 }
180 }
181 }
182 return TypePtr;
183}
184
186 bool FullyQualify,
187 bool WithGlobalNsPrefix) {
188 const DeclContext *DC = D->getDeclContext();
189 if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
190 while (NS && NS->isInline()) {
191 // Ignore inline namespace;
192 NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
193 }
194 if (NS && NS->getDeclName()) {
195 return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
196 }
197 return nullptr; // no starting '::', no anonymous
198 } else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
199 return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
200 } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
202 Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
203 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
205 }
206 return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
207}
208
209/// Return a fully qualified version of this name specifier.
212 bool WithGlobalNsPrefix) {
213 switch (Scope->getKind()) {
215 // Already fully qualified
216 return Scope;
219 Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix);
221 // Namespace aliases are only valid for the duration of the
222 // scope where they were introduced, and therefore are often
223 // invalid at the end of the TU. So use the namespace name more
224 // likely to be valid at the end of the TU.
226 Ctx,
227 Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(),
228 WithGlobalNsPrefix);
230 // A function or some other construct that makes it un-namable
231 // at the end of the TU. Skip the current component of the name,
232 // but use the name of it's prefix.
234 Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
238 const Type *Type = Scope->getAsType();
239 // Find decl context.
240 const TagDecl *TD = nullptr;
241 if (const TagType *TagDeclType = Type->getAs<TagType>()) {
242 TD = TagDeclType->getDecl();
243 } else {
244 TD = Type->getAsCXXRecordDecl();
245 }
246 if (TD) {
248 true /*FullyQualified*/,
249 WithGlobalNsPrefix);
250 } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
251 return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
252 true /*FullyQualified*/,
253 WithGlobalNsPrefix);
254 }
255 return Scope;
256 }
257 }
258 llvm_unreachable("bad NNS kind");
259}
260
261/// Create a nested name specifier for the declaring context of
262/// the type.
264 const ASTContext &Ctx, const Decl *Decl,
265 bool FullyQualified, bool WithGlobalNsPrefix) {
266 assert(Decl);
267
269 const auto *Outer = dyn_cast<NamedDecl>(DC);
270 const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
271 if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
272 if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
273 if (ClassTemplateDecl *ClassTempl =
274 CxxDecl->getDescribedClassTemplate()) {
275 // We are in the case of a type(def) that was declared in a
276 // class template but is *not* type dependent. In clang, it
277 // gets attached to the class template declaration rather than
278 // any specific class template instantiation. This result in
279 // 'odd' fully qualified typename:
280 //
281 // vector<_Tp,_Alloc>::size_type
282 //
283 // Make the situation is 'useable' but looking a bit odd by
284 // picking a random instance as the declaring context.
285 if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
286 Decl = *(ClassTempl->spec_begin());
287 Outer = dyn_cast<NamedDecl>(Decl);
288 OuterNS = dyn_cast<NamespaceDecl>(Decl);
289 }
290 }
291 }
292
293 if (OuterNS) {
294 return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
295 } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
297 Ctx, TD, FullyQualified, WithGlobalNsPrefix);
298 } else if (isa<TranslationUnitDecl>(Outer)) {
299 // Context is the TU. Nothing needs to be done.
300 return nullptr;
301 } else {
302 // Decl's context was neither the TU, a namespace, nor a
303 // TagDecl, which means it is a type local to a scope, and not
304 // accessible at the end of the TU.
305 return nullptr;
306 }
307 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
309 }
310 return nullptr;
311}
312
313/// Create a nested name specifier for the declaring context of
314/// the type.
316 const ASTContext &Ctx, const Type *TypePtr,
317 bool FullyQualified, bool WithGlobalNsPrefix) {
318 if (!TypePtr) return nullptr;
319
320 Decl *Decl = nullptr;
321 // There are probably other cases ...
322 if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
323 Decl = TDT->getDecl();
324 } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
325 Decl = TagDeclType->getDecl();
326 } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
327 Decl = TST->getTemplateName().getAsTemplateDecl();
328 } else {
329 Decl = TypePtr->getAsCXXRecordDecl();
330 }
331
332 if (!Decl) return nullptr;
333
335 Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
336}
337
339 const NamespaceDecl *Namespace,
340 bool WithGlobalNsPrefix) {
341 while (Namespace && Namespace->isInline()) {
342 // Ignore inline namespace;
343 Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
344 }
345 if (!Namespace) return nullptr;
346
347 bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
349 Ctx,
350 createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
351 Namespace);
352}
353
355 const TypeDecl *TD,
356 bool FullyQualify,
357 bool WithGlobalNsPrefix) {
358 const Type *TypePtr = TD->getTypeForDecl();
359 if (isa<const TemplateSpecializationType>(TypePtr) ||
360 isa<const RecordType>(TypePtr)) {
361 // We are asked to fully qualify and we have a Record Type (which
362 // may point to a template specialization) or Template
363 // Specialization Type. We need to fully qualify their arguments.
364
365 TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix);
366 }
367
369 Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
370 false /*No TemplateKeyword*/, TypePtr);
371}
372
373/// Return the fully qualified type, including fully-qualified
374/// versions of any template parameters.
376 bool WithGlobalNsPrefix) {
377 // In case of myType* we need to strip the pointer first, fully
378 // qualify and attach the pointer once again.
379 if (isa<PointerType>(QT.getTypePtr())) {
380 // Get the qualifiers.
381 Qualifiers Quals = QT.getQualifiers();
382 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
383 QT = Ctx.getPointerType(QT);
384 // Add back the qualifiers.
385 QT = Ctx.getQualifiedType(QT, Quals);
386 return QT;
387 }
388
389 if (auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) {
390 // Get the qualifiers.
391 Qualifiers Quals = QT.getQualifiers();
392 // Fully qualify the pointee and class types.
393 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
394 QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx,
395 WithGlobalNsPrefix);
396 QT = Ctx.getMemberPointerType(QT, Class.getTypePtr());
397 // Add back the qualifiers.
398 QT = Ctx.getQualifiedType(QT, Quals);
399 return QT;
400 }
401
402 // In case of myType& we need to strip the reference first, fully
403 // qualify and attach the reference once again.
404 if (isa<ReferenceType>(QT.getTypePtr())) {
405 // Get the qualifiers.
406 bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
407 Qualifiers Quals = QT.getQualifiers();
408 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
409 // Add the r- or l-value reference type back to the fully
410 // qualified one.
411 if (IsLValueRefTy)
412 QT = Ctx.getLValueReferenceType(QT);
413 else
414 QT = Ctx.getRValueReferenceType(QT);
415 // Add back the qualifiers.
416 QT = Ctx.getQualifiedType(QT, Quals);
417 return QT;
418 }
419
420 // Remove the part of the type related to the type being a template
421 // parameter (we won't report it as part of the 'type name' and it
422 // is actually make the code below to be more complex (to handle
423 // those)
424 while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
425 // Get the qualifiers.
426 Qualifiers Quals = QT.getQualifiers();
427
428 QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
429
430 // Add back the qualifiers.
431 QT = Ctx.getQualifiedType(QT, Quals);
432 }
433
434 NestedNameSpecifier *Prefix = nullptr;
435 // Local qualifiers are attached to the QualType outside of the
436 // elaborated type. Retrieve them before descending into the
437 // elaborated type.
438 Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
439 QT = QualType(QT.getTypePtr(), 0);
441 if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
442 QT = ETypeInput->getNamedType();
443 assert(!QT.hasLocalQualifiers());
444 Keyword = ETypeInput->getKeyword();
445 }
446
447 // We don't consider the alias introduced by `using a::X` as a new type.
448 // The qualified name is still a::X.
449 if (const auto *UT = QT->getAs<UsingType>()) {
450 QT = Ctx.getQualifiedType(UT->getUnderlyingType(), PrefixQualifiers);
451 return getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
452 }
453
454 // Create a nested name specifier if needed.
456 true /*FullyQualified*/,
457 WithGlobalNsPrefix);
458
459 // In case of template specializations iterate over the arguments and
460 // fully qualify them as well.
461 if (isa<const TemplateSpecializationType>(QT.getTypePtr()) ||
462 isa<const RecordType>(QT.getTypePtr())) {
463 // We are asked to fully qualify and we have a Record Type (which
464 // may point to a template specialization) or Template
465 // Specialization Type. We need to fully qualify their arguments.
466
467 const Type *TypePtr = getFullyQualifiedTemplateType(
468 Ctx, QT.getTypePtr(), WithGlobalNsPrefix);
469 QT = QualType(TypePtr, 0);
470 }
471 if (Prefix || Keyword != ElaboratedTypeKeyword::None) {
472 QT = Ctx.getElaboratedType(Keyword, Prefix, QT);
473 }
474 QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
475 return QT;
476}
477
479 const ASTContext &Ctx,
480 const PrintingPolicy &Policy,
481 bool WithGlobalNsPrefix) {
482 QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
483 return FQQT.getAsString(Policy);
484}
485
486} // end namespace TypeName
487} // end namespace clang
const Decl * D
Expr * E
Defines the C++ template declaration subclasses.
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 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 ...
QualType getTemplateSpecializationType(TemplateName T, ArrayRef< TemplateArgument > Args, QualType Canon=QualType()) const
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateName Template) const
Retrieve the template name that represents a qualified template name such as std::vector.
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.
Definition: ASTContext.h:2289
QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, TagDecl *OwnedTagDecl=nullptr) 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:1435
bool isTranslationUnit() const
Definition: DeclBase.h:2165
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
Definition: DeclBase.cpp:1990
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
DeclContext * getDeclContext()
Definition: DeclBase.h:451
Represent a C++ namespace.
Definition: Decl.h:551
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
static NestedNameSpecifier * Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const IdentifierInfo *II)
Builds a specifier combining a prefix and an identifier.
static NestedNameSpecifier * GlobalSpecifier(const ASTContext &Context)
Returns the nested name specifier representing the global scope.
@ NamespaceAlias
A namespace alias, stored as a NamespaceAliasDecl*.
@ TypeSpec
A type, stored as a Type*.
@ TypeSpecWithTemplate
A type that was preceded by the 'template' keyword, stored as a Type*.
@ Super
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Identifier
An identifier, stored as an IdentifierInfo*.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace, stored as a NamespaceDecl*.
A (possibly-)qualified type.
Definition: Type.h:929
bool hasLocalQualifiers() const
Determine whether this particular QualType instance has any qualifiers, without looking through any t...
Definition: Type.h:1056
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7931
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:7971
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:1327
Qualifiers getLocalQualifiers() const
Retrieve the set of qualifiers local to this particular QualType instance, not including any qualifie...
Definition: Type.h:7963
Represents a template name as written in source code.
Definition: TemplateName.h:491
NestedNameSpecifier * getQualifier() const
Return the nested name specifier that qualifies this name.
Definition: TemplateName.h:519
bool hasTemplateKeyword() const
Whether the template name was prefixed by the "template" keyword.
Definition: TemplateName.h:523
The collection of all-type qualifiers we support.
Definition: Type.h:324
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3564
A template argument list.
Definition: DeclTemplate.h:250
unsigned size() const
Retrieve the number of template arguments in this template argument list.
Definition: DeclTemplate.h:286
Represents a template argument.
Definition: TemplateBase.h:61
QualType getAsType() const
Retrieve the type for a type template argument.
Definition: TemplateBase.h:319
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
Definition: TemplateBase.h:343
@ Template
The template argument is a template name that was provided for a template template parameter.
Definition: TemplateBase.h:93
@ Type
The template argument is a type.
Definition: TemplateBase.h:70
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:295
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:399
Represents a C++ template name within the type system.
Definition: TemplateName.h:220
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:3370
const Type * getTypeForDecl() const
Definition: Decl.h:3395
The base class of the type hierarchy.
Definition: Type.h:1828
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1916
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Definition: DeclCXX.h:3338
static NestedNameSpecifier * createOuterNNS(const ASTContext &Ctx, const Decl *D, bool FullyQualify, bool WithGlobalNsPrefix)
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, TemplateName &TName, bool WithGlobalNsPrefix)
static const Type * getFullyQualifiedTemplateType(const ASTContext &Ctx, const Type *TypePtr, bool WithGlobalNsPrefix)
static NestedNameSpecifier * getFullyQualifiedNestedNameSpecifier(const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix)
Return a fully qualified version of this name specifier.
static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, TemplateArgument &Arg, bool WithGlobalNsPrefix)
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.
std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, const PrintingPolicy &Policy, bool WithGlobalNsPrefix=false)
Get the fully qualified name for a type.
static NestedNameSpecifier * createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp, bool WithGlobalNsPrefix)
Create a NestedNameSpecifier for Namesp and its enclosing scopes.
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.
ElaboratedTypeKeyword
The elaboration keyword that precedes a qualified type name or introduces an elaborated-type-specifie...
Definition: Type.h:6846
@ None
No keyword precedes the qualified type name.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57