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 =
86 Ctx.getQualifiedTemplateName(NNS,
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.
152 TemplateName TN = Ctx.getQualifiedTemplateName(
153 Qualifier, /*TemplateKeyword=*/false,
154 TemplateName(TSTDecl->getSpecializedTemplate()));
155 QualType QT = Ctx.getTemplateSpecializationType(
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 *
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)
429 while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
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
const Decl * D
Expr * E
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
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 ...
Definition: DeclBase.cpp:2022
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
DeclContext * getDeclContext()
Definition: DeclBase.h:448
ElaboratedTypeKeyword getKeyword() const
Definition: TypeBase.h:5959
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.
@ Type
A type, stored as a Type*.
@ 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:8343
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: TypeBase.h:8383
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:8375
Represents a template name as written in source code.
Definition: TemplateName.h:504
NestedNameSpecifier getQualifier() const
Return the nested name specifier that qualifies this name.
Definition: TemplateName.h:532
bool hasTemplateKeyword() const
Whether the template name was prefixed by the "template" keyword.
Definition: TemplateName.h:536
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
TagDecl * getOriginalDecl() const
Definition: TypeBase.h:6441
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:322
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
Definition: TemplateBase.h:346
@ 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:296
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:396
Represents a C++ template name within the type system.
Definition: TemplateName.h:222
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 type template specialization; the template must be a class template, a type alias templa...
Definition: TypeBase.h:7290
ArrayRef< TemplateArgument > template_arguments() const
Definition: TypeBase.h:7357
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
Definition: TypeBase.h:7355
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
QualType getCanonicalTypeInternal() const
Definition: TypeBase.h:3137
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
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.
@ Keyword
The name has been typo-corrected to a keyword.
const FunctionProtoType * T
ElaboratedTypeKeyword
The elaboration keyword that precedes a qualified type name or introduces an elaborated-type-specifie...
Definition: TypeBase.h:5881
@ None
No keyword precedes the qualified type name.
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57