1 //===------- QualTypeNames.cpp - Generate Complete QualType Names ---------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/AST/QualTypeNames.h"
10 #include "clang/AST/DeclTemplate.h"
11 #include "clang/AST/DeclarationName.h"
12 #include "clang/AST/Mangle.h"
18 /// Create a NestedNameSpecifier for Namesp and its enclosing
21 /// \param[in] Ctx - the AST Context to be used.
22 /// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
24 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
25 /// specifier "::" should be prepended or not.
26 static NestedNameSpecifier
*createNestedNameSpecifier(
27 const ASTContext
&Ctx
,
28 const NamespaceDecl
*Namesp
,
29 bool WithGlobalNsPrefix
);
31 /// Create a NestedNameSpecifier for TagDecl and its enclosing
34 /// \param[in] Ctx - the AST Context to be used.
35 /// \param[in] TD - the TagDecl for which a NestedNameSpecifier is
37 /// \param[in] FullyQualify - Convert all template arguments into fully
39 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
40 /// specifier "::" should be prepended or not.
41 static NestedNameSpecifier
*createNestedNameSpecifier(
42 const ASTContext
&Ctx
, const TypeDecl
*TD
,
43 bool FullyQualify
, bool WithGlobalNsPrefix
);
45 static NestedNameSpecifier
*createNestedNameSpecifierForScopeOf(
46 const ASTContext
&Ctx
, const Decl
*decl
,
47 bool FullyQualified
, bool WithGlobalNsPrefix
);
49 static NestedNameSpecifier
*getFullyQualifiedNestedNameSpecifier(
50 const ASTContext
&Ctx
, NestedNameSpecifier
*scope
, bool WithGlobalNsPrefix
);
52 static bool getFullyQualifiedTemplateName(const ASTContext
&Ctx
,
54 bool WithGlobalNsPrefix
) {
56 NestedNameSpecifier
*NNS
= nullptr;
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);
62 QualifiedTemplateName
*QTName
= TName
.getAsQualifiedTemplateName();
65 !QTName
->hasTemplateKeyword() &&
66 (NNS
= QTName
->getQualifier())) {
67 NestedNameSpecifier
*QNNS
= getFullyQualifiedNestedNameSpecifier(
68 Ctx
, NNS
, WithGlobalNsPrefix
);
76 NNS
= createNestedNameSpecifierForScopeOf(
77 Ctx
, ArgTDecl
, true, WithGlobalNsPrefix
);
80 TemplateName
UnderlyingTN(ArgTDecl
);
81 if (UsingShadowDecl
*USD
= TName
.getAsUsingShadowDecl())
82 UnderlyingTN
= TemplateName(USD
);
84 Ctx
.getQualifiedTemplateName(NNS
,
85 /*TemplateKeyword=*/false, UnderlyingTN
);
91 static bool getFullyQualifiedTemplateArgument(const ASTContext
&Ctx
,
92 TemplateArgument
&Arg
,
93 bool WithGlobalNsPrefix
) {
96 // Note: we do not handle TemplateArgument::Expression, to replace it
97 // we need the information for the template instance decl.
99 if (Arg
.getKind() == TemplateArgument::Template
) {
100 TemplateName TName
= Arg
.getAsTemplate();
101 Changed
= getFullyQualifiedTemplateName(Ctx
, TName
, WithGlobalNsPrefix
);
103 Arg
= TemplateArgument(TName
);
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
);
110 Arg
= TemplateArgument(QTFQ
);
117 static const Type
*getFullyQualifiedTemplateType(const ASTContext
&Ctx
,
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;
128 SmallVector
<TemplateArgument
, 4> FQArgs
;
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
);
137 // If a fully qualified arg is different from the unqualified arg,
138 // allocate new type in the AST.
139 if (MightHaveChanged
) {
140 QualType QT
= Ctx
.getTemplateSpecializationType(
141 TST
->getTemplateName(), FQArgs
,
142 TST
->getCanonicalTypeInternal());
143 // getTemplateSpecializationType returns a fully qualified
144 // version of the specialization itself, so no need to qualify
146 return QT
.getTypePtr();
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.
153 if (const auto *TSTDecl
=
154 dyn_cast
<ClassTemplateSpecializationDecl
>(TSTRecord
->getDecl())) {
155 const TemplateArgumentList
&TemplateArgs
= TSTDecl
->getTemplateArgs();
157 bool MightHaveChanged
= false;
158 SmallVector
<TemplateArgument
, 4> FQArgs
;
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
);
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());
172 QualType QT
= Ctx
.getTemplateSpecializationType(
174 TSTRecord
->getCanonicalTypeInternal());
175 // getTemplateSpecializationType returns a fully qualified
176 // version of the specialization itself, so no need to qualify
178 return QT
.getTypePtr();
185 static NestedNameSpecifier
*createOuterNNS(const ASTContext
&Ctx
, const Decl
*D
,
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());
194 if (NS
&& NS
->getDeclName()) {
195 return createNestedNameSpecifier(Ctx
, NS
, WithGlobalNsPrefix
);
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
)) {
201 return createNestedNameSpecifier(
202 Ctx
, TDD
, FullyQualify
, WithGlobalNsPrefix
);
203 } else if (WithGlobalNsPrefix
&& DC
->isTranslationUnit()) {
204 return NestedNameSpecifier::GlobalSpecifier(Ctx
);
206 return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
209 /// Return a fully qualified version of this name specifier.
210 static NestedNameSpecifier
*getFullyQualifiedNestedNameSpecifier(
211 const ASTContext
&Ctx
, NestedNameSpecifier
*Scope
,
212 bool WithGlobalNsPrefix
) {
213 switch (Scope
->getKind()) {
214 case NestedNameSpecifier::Global
:
215 // Already fully qualified
217 case NestedNameSpecifier::Namespace
:
218 return TypeName::createNestedNameSpecifier(
219 Ctx
, Scope
->getAsNamespace(), WithGlobalNsPrefix
);
220 case NestedNameSpecifier::NamespaceAlias
:
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.
225 return TypeName::createNestedNameSpecifier(
227 Scope
->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(),
229 case NestedNameSpecifier::Identifier
:
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.
233 return getFullyQualifiedNestedNameSpecifier(
234 Ctx
, Scope
->getPrefix(), WithGlobalNsPrefix
);
235 case NestedNameSpecifier::Super
:
236 case NestedNameSpecifier::TypeSpec
:
237 case NestedNameSpecifier::TypeSpecWithTemplate
: {
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();
244 TD
= Type
->getAsCXXRecordDecl();
247 return TypeName::createNestedNameSpecifier(Ctx
, TD
,
248 true /*FullyQualified*/,
250 } else if (const auto *TDD
= dyn_cast
<TypedefType
>(Type
)) {
251 return TypeName::createNestedNameSpecifier(Ctx
, TDD
->getDecl(),
252 true /*FullyQualified*/,
258 llvm_unreachable("bad NNS kind");
261 /// Create a nested name specifier for the declaring context of
263 static NestedNameSpecifier
*createNestedNameSpecifierForScopeOf(
264 const ASTContext
&Ctx
, const Decl
*Decl
,
265 bool FullyQualified
, bool WithGlobalNsPrefix
) {
268 const DeclContext
*DC
= Decl
->getDeclContext()->getRedeclContext();
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:
281 // vector<_Tp,_Alloc>::size_type
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
);
294 return createNestedNameSpecifier(Ctx
, OuterNS
, WithGlobalNsPrefix
);
295 } else if (const auto *TD
= dyn_cast
<TagDecl
>(Outer
)) {
296 return createNestedNameSpecifier(
297 Ctx
, TD
, FullyQualified
, WithGlobalNsPrefix
);
298 } else if (isa
<TranslationUnitDecl
>(Outer
)) {
299 // Context is the TU. Nothing needs to be done.
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.
307 } else if (WithGlobalNsPrefix
&& DC
->isTranslationUnit()) {
308 return NestedNameSpecifier::GlobalSpecifier(Ctx
);
313 /// Create a nested name specifier for the declaring context of
315 static NestedNameSpecifier
*createNestedNameSpecifierForScopeOf(
316 const ASTContext
&Ctx
, const Type
*TypePtr
,
317 bool FullyQualified
, bool WithGlobalNsPrefix
) {
318 if (!TypePtr
) return nullptr;
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();
329 Decl
= TypePtr
->getAsCXXRecordDecl();
332 if (!Decl
) return nullptr;
334 return createNestedNameSpecifierForScopeOf(
335 Ctx
, Decl
, FullyQualified
, WithGlobalNsPrefix
);
338 NestedNameSpecifier
*createNestedNameSpecifier(const ASTContext
&Ctx
,
339 const NamespaceDecl
*Namespace
,
340 bool WithGlobalNsPrefix
) {
341 while (Namespace
&& Namespace
->isInline()) {
342 // Ignore inline namespace;
343 Namespace
= dyn_cast
<NamespaceDecl
>(Namespace
->getDeclContext());
345 if (!Namespace
) return nullptr;
347 bool FullyQualified
= true; // doesn't matter, DeclContexts are namespaces
348 return NestedNameSpecifier::Create(
350 createOuterNNS(Ctx
, Namespace
, FullyQualified
, WithGlobalNsPrefix
),
354 NestedNameSpecifier
*createNestedNameSpecifier(const ASTContext
&Ctx
,
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.
365 TypePtr
= getFullyQualifiedTemplateType(Ctx
, TypePtr
, WithGlobalNsPrefix
);
368 return NestedNameSpecifier::Create(
369 Ctx
, createOuterNNS(Ctx
, TD
, FullyQualify
, WithGlobalNsPrefix
),
370 false /*No TemplateKeyword*/, TypePtr
);
373 /// Return the fully qualified type, including fully-qualified
374 /// versions of any template parameters.
375 QualType
getFullyQualifiedType(QualType QT
, const ASTContext
&Ctx
,
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
);
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
,
396 QT
= Ctx
.getMemberPointerType(QT
, Class
.getTypePtr());
397 // Add back the qualifiers.
398 QT
= Ctx
.getQualifiedType(QT
, Quals
);
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
412 QT
= Ctx
.getLValueReferenceType(QT
);
414 QT
= Ctx
.getRValueReferenceType(QT
);
415 // Add back the qualifiers.
416 QT
= Ctx
.getQualifiedType(QT
, Quals
);
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
424 while (isa
<SubstTemplateTypeParmType
>(QT
.getTypePtr())) {
425 // Get the qualifiers.
426 Qualifiers Quals
= QT
.getQualifiers();
428 QT
= cast
<SubstTemplateTypeParmType
>(QT
.getTypePtr())->desugar();
430 // Add back the qualifiers.
431 QT
= Ctx
.getQualifiedType(QT
, Quals
);
434 NestedNameSpecifier
*Prefix
= nullptr;
435 // Local qualifiers are attached to the QualType outside of the
436 // elaborated type. Retrieve them before descending into the
438 Qualifiers PrefixQualifiers
= QT
.getLocalQualifiers();
439 QT
= QualType(QT
.getTypePtr(), 0);
440 ElaboratedTypeKeyword Keyword
= ElaboratedTypeKeyword::None
;
441 if (const auto *ETypeInput
= dyn_cast
<ElaboratedType
>(QT
.getTypePtr())) {
442 QT
= ETypeInput
->getNamedType();
443 assert(!QT
.hasLocalQualifiers());
444 Keyword
= ETypeInput
->getKeyword();
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
);
454 // Create a nested name specifier if needed.
455 Prefix
= createNestedNameSpecifierForScopeOf(Ctx
, QT
.getTypePtr(),
456 true /*FullyQualified*/,
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.
467 const Type
*TypePtr
= getFullyQualifiedTemplateType(
468 Ctx
, QT
.getTypePtr(), WithGlobalNsPrefix
);
469 QT
= QualType(TypePtr
, 0);
471 if (Prefix
|| Keyword
!= ElaboratedTypeKeyword::None
) {
472 QT
= Ctx
.getElaboratedType(Keyword
, Prefix
, QT
);
474 QT
= Ctx
.getQualifiedType(QT
, PrefixQualifiers
);
478 std::string
getFullyQualifiedName(QualType QT
,
479 const ASTContext
&Ctx
,
480 const PrintingPolicy
&Policy
,
481 bool WithGlobalNsPrefix
) {
482 QualType FQQT
= getFullyQualifiedType(QT
, Ctx
, WithGlobalNsPrefix
);
483 return FQQT
.getAsString(Policy
);
486 } // end namespace TypeName
487 } // end namespace clang