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 
9 #include "clang/AST/DeclTemplate.h"
10 #include "clang/AST/DeclarationName.h"
11 #include "clang/AST/GlobalDecl.h"
12 #include "clang/AST/Mangle.h"
13 #include "clang/AST/QualTypeNames.h"
14 
15 #include <stdio.h>
16 #include <memory>
17 
18 namespace clang {
19 
20 namespace TypeName {
21 
22 /// Create a NestedNameSpecifier for Namesp and its enclosing
23 /// scopes.
24 ///
25 /// \param[in] Ctx - the AST Context to be used.
26 /// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
27 /// is requested.
28 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
29 /// specifier "::" should be prepended or not.
30 static NestedNameSpecifier *createNestedNameSpecifier(
31     const ASTContext &Ctx,
32     const NamespaceDecl *Namesp,
33     bool WithGlobalNsPrefix);
34 
35 /// Create a NestedNameSpecifier for TagDecl and its enclosing
36 /// scopes.
37 ///
38 /// \param[in] Ctx - the AST Context to be used.
39 /// \param[in] TD - the TagDecl for which a NestedNameSpecifier is
40 /// requested.
41 /// \param[in] FullyQualify - Convert all template arguments into fully
42 /// qualified names.
43 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
44 /// specifier "::" should be prepended or not.
45 static NestedNameSpecifier *createNestedNameSpecifier(
46     const ASTContext &Ctx, const TypeDecl *TD,
47     bool FullyQualify, bool WithGlobalNsPrefix);
48 
49 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
50     const ASTContext &Ctx, const Decl *decl,
51     bool FullyQualified, bool WithGlobalNsPrefix);
52 
53 static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
54     const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
55 
56 static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
57                                           TemplateName &TName,
58                                           bool WithGlobalNsPrefix) {
59   bool Changed = false;
60   NestedNameSpecifier *NNS = nullptr;
61 
62   TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
63   // ArgTDecl won't be NULL because we asserted that this isn't a
64   // dependent context very early in the call chain.
65   assert(ArgTDecl != nullptr);
66   QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName();
67 
68   if (QTName && !QTName->hasTemplateKeyword()) {
69     NNS = QTName->getQualifier();
70     NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier(
71         Ctx, NNS, WithGlobalNsPrefix);
72     if (QNNS != NNS) {
73       Changed = true;
74       NNS = QNNS;
75     } else {
76       NNS = nullptr;
77     }
78   } else {
79     NNS = createNestedNameSpecifierForScopeOf(
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 =
87         Ctx.getQualifiedTemplateName(NNS,
88                                      /*TemplateKeyword=*/false, UnderlyingTN);
89     Changed = true;
90   }
91   return Changed;
92 }
93 
94 static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx,
95                                               TemplateArgument &Arg,
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 
120 static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
121                                                  const Type *TypePtr,
122                                                  bool WithGlobalNsPrefix) {
123   // DependentTemplateTypes exist within template declarations and
124   // definitions. Therefore we shouldn't encounter them at the end of
125   // a translation unit. If we do, the caller has made an error.
126   assert(!isa<DependentTemplateSpecializationType>(TypePtr));
127   // In case of template specializations, iterate over the arguments
128   // and fully qualify them as well.
129   if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) {
130     bool MightHaveChanged = false;
131     SmallVector<TemplateArgument, 4> FQArgs;
132     for (TemplateSpecializationType::iterator I = TST->begin(), E = TST->end();
133          I != E; ++I) {
134       // Cheap to copy and potentially modified by
135       // getFullyQualifedTemplateArgument.
136       TemplateArgument Arg(*I);
137       MightHaveChanged |= getFullyQualifiedTemplateArgument(
138           Ctx, Arg, WithGlobalNsPrefix);
139       FQArgs.push_back(Arg);
140     }
141 
142     // If a fully qualified arg is different from the unqualified arg,
143     // allocate new type in the AST.
144     if (MightHaveChanged) {
145       QualType QT = Ctx.getTemplateSpecializationType(
146           TST->getTemplateName(), FQArgs,
147           TST->getCanonicalTypeInternal());
148       // getTemplateSpecializationType returns a fully qualified
149       // version of the specialization itself, so no need to qualify
150       // it.
151       return QT.getTypePtr();
152     }
153   } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) {
154     // We are asked to fully qualify and we have a Record Type,
155     // which can point to a template instantiation with no sugar in any of
156     // its template argument, however we still need to fully qualify them.
157 
158     if (const auto *TSTDecl =
159         dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
160       const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
161 
162       bool MightHaveChanged = false;
163       SmallVector<TemplateArgument, 4> FQArgs;
164       for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
165         // cheap to copy and potentially modified by
166         // getFullyQualifedTemplateArgument
167         TemplateArgument Arg(TemplateArgs[I]);
168         MightHaveChanged |= getFullyQualifiedTemplateArgument(
169             Ctx, Arg, WithGlobalNsPrefix);
170         FQArgs.push_back(Arg);
171       }
172 
173       // If a fully qualified arg is different from the unqualified arg,
174       // allocate new type in the AST.
175       if (MightHaveChanged) {
176         TemplateName TN(TSTDecl->getSpecializedTemplate());
177         QualType QT = Ctx.getTemplateSpecializationType(
178             TN, FQArgs,
179             TSTRecord->getCanonicalTypeInternal());
180         // getTemplateSpecializationType returns a fully qualified
181         // version of the specialization itself, so no need to qualify
182         // it.
183         return QT.getTypePtr();
184       }
185     }
186   }
187   return TypePtr;
188 }
189 
190 static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
191                                            bool FullyQualify,
192                                            bool WithGlobalNsPrefix) {
193   const DeclContext *DC = D->getDeclContext();
194   if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
195     while (NS && NS->isInline()) {
196       // Ignore inline namespace;
197       NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
198     }
199     if (NS && NS->getDeclName()) {
200       return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
201     }
202     return nullptr;  // no starting '::', no anonymous
203   } else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
204     return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
205   } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
206     return createNestedNameSpecifier(
207         Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
208   } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
209     return NestedNameSpecifier::GlobalSpecifier(Ctx);
210   }
211   return nullptr;  // no starting '::' if |WithGlobalNsPrefix| is false
212 }
213 
214 /// Return a fully qualified version of this name specifier.
215 static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
216     const ASTContext &Ctx, NestedNameSpecifier *Scope,
217     bool WithGlobalNsPrefix) {
218   switch (Scope->getKind()) {
219     case NestedNameSpecifier::Global:
220       // Already fully qualified
221       return Scope;
222     case NestedNameSpecifier::Namespace:
223       return TypeName::createNestedNameSpecifier(
224           Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix);
225     case NestedNameSpecifier::NamespaceAlias:
226       // Namespace aliases are only valid for the duration of the
227       // scope where they were introduced, and therefore are often
228       // invalid at the end of the TU.  So use the namespace name more
229       // likely to be valid at the end of the TU.
230       return TypeName::createNestedNameSpecifier(
231           Ctx,
232           Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(),
233           WithGlobalNsPrefix);
234     case NestedNameSpecifier::Identifier:
235       // A function or some other construct that makes it un-namable
236       // at the end of the TU. Skip the current component of the name,
237       // but use the name of it's prefix.
238       return getFullyQualifiedNestedNameSpecifier(
239           Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
240     case NestedNameSpecifier::Super:
241     case NestedNameSpecifier::TypeSpec:
242     case NestedNameSpecifier::TypeSpecWithTemplate: {
243       const Type *Type = Scope->getAsType();
244       // Find decl context.
245       const TagDecl *TD = nullptr;
246       if (const TagType *TagDeclType = Type->getAs<TagType>()) {
247         TD = TagDeclType->getDecl();
248       } else {
249         TD = Type->getAsCXXRecordDecl();
250       }
251       if (TD) {
252         return TypeName::createNestedNameSpecifier(Ctx, TD,
253                                                    true /*FullyQualified*/,
254                                                    WithGlobalNsPrefix);
255       } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
256         return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
257                                                    true /*FullyQualified*/,
258                                                    WithGlobalNsPrefix);
259       }
260       return Scope;
261     }
262   }
263   llvm_unreachable("bad NNS kind");
264 }
265 
266 /// Create a nested name specifier for the declaring context of
267 /// the type.
268 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
269     const ASTContext &Ctx, const Decl *Decl,
270     bool FullyQualified, bool WithGlobalNsPrefix) {
271   assert(Decl);
272 
273   const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
274   const auto *Outer = dyn_cast_or_null<NamedDecl>(DC);
275   const auto *OuterNS = dyn_cast_or_null<NamespaceDecl>(DC);
276   if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
277     if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
278       if (ClassTemplateDecl *ClassTempl =
279               CxxDecl->getDescribedClassTemplate()) {
280         // We are in the case of a type(def) that was declared in a
281         // class template but is *not* type dependent.  In clang, it
282         // gets attached to the class template declaration rather than
283         // any specific class template instantiation.  This result in
284         // 'odd' fully qualified typename:
285         //
286         //    vector<_Tp,_Alloc>::size_type
287         //
288         // Make the situation is 'useable' but looking a bit odd by
289         // picking a random instance as the declaring context.
290         if (ClassTempl->spec_begin() != ClassTempl->spec_end()) {
291           Decl = *(ClassTempl->spec_begin());
292           Outer = dyn_cast<NamedDecl>(Decl);
293           OuterNS = dyn_cast<NamespaceDecl>(Decl);
294         }
295       }
296     }
297 
298     if (OuterNS) {
299       return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
300     } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
301       return createNestedNameSpecifier(
302           Ctx, TD, FullyQualified, WithGlobalNsPrefix);
303     } else if (isa<TranslationUnitDecl>(Outer)) {
304       // Context is the TU. Nothing needs to be done.
305       return nullptr;
306     } else {
307       // Decl's context was neither the TU, a namespace, nor a
308       // TagDecl, which means it is a type local to a scope, and not
309       // accessible at the end of the TU.
310       return nullptr;
311     }
312   } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
313     return NestedNameSpecifier::GlobalSpecifier(Ctx);
314   }
315   return nullptr;
316 }
317 
318 /// Create a nested name specifier for the declaring context of
319 /// the type.
320 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
321     const ASTContext &Ctx, const Type *TypePtr,
322     bool FullyQualified, bool WithGlobalNsPrefix) {
323   if (!TypePtr) return nullptr;
324 
325   Decl *Decl = nullptr;
326   // There are probably other cases ...
327   if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
328     Decl = TDT->getDecl();
329   } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
330     Decl = TagDeclType->getDecl();
331   } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
332     Decl = TST->getTemplateName().getAsTemplateDecl();
333   } else {
334     Decl = TypePtr->getAsCXXRecordDecl();
335   }
336 
337   if (!Decl) return nullptr;
338 
339   return createNestedNameSpecifierForScopeOf(
340       Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
341 }
342 
343 NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
344                                                const NamespaceDecl *Namespace,
345                                                bool WithGlobalNsPrefix) {
346   while (Namespace && Namespace->isInline()) {
347     // Ignore inline namespace;
348     Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
349   }
350   if (!Namespace) return nullptr;
351 
352   bool FullyQualified = true;  // doesn't matter, DeclContexts are namespaces
353   return NestedNameSpecifier::Create(
354       Ctx,
355       createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
356       Namespace);
357 }
358 
359 NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
360                                                const TypeDecl *TD,
361                                                bool FullyQualify,
362                                                bool WithGlobalNsPrefix) {
363   const Type *TypePtr = TD->getTypeForDecl();
364   if (isa<const TemplateSpecializationType>(TypePtr) ||
365       isa<const RecordType>(TypePtr)) {
366     // We are asked to fully qualify and we have a Record Type (which
367     // may point to a template specialization) or Template
368     // Specialization Type. We need to fully qualify their arguments.
369 
370     TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix);
371   }
372 
373   return NestedNameSpecifier::Create(
374       Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
375       false /*No TemplateKeyword*/, TypePtr);
376 }
377 
378 /// Return the fully qualified type, including fully-qualified
379 /// versions of any template parameters.
380 QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
381                                bool WithGlobalNsPrefix) {
382   // In case of myType* we need to strip the pointer first, fully
383   // qualify and attach the pointer once again.
384   if (isa<PointerType>(QT.getTypePtr())) {
385     // Get the qualifiers.
386     Qualifiers Quals = QT.getQualifiers();
387     QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
388     QT = Ctx.getPointerType(QT);
389     // Add back the qualifiers.
390     QT = Ctx.getQualifiedType(QT, Quals);
391     return QT;
392   }
393 
394   if (auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) {
395     // Get the qualifiers.
396     Qualifiers Quals = QT.getQualifiers();
397     // Fully qualify the pointee and class types.
398     QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
399     QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx,
400                                            WithGlobalNsPrefix);
401     QT = Ctx.getMemberPointerType(QT, Class.getTypePtr());
402     // Add back the qualifiers.
403     QT = Ctx.getQualifiedType(QT, Quals);
404     return QT;
405   }
406 
407   // In case of myType& we need to strip the reference first, fully
408   // qualify and attach the reference once again.
409   if (isa<ReferenceType>(QT.getTypePtr())) {
410     // Get the qualifiers.
411     bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
412     Qualifiers Quals = QT.getQualifiers();
413     QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
414     // Add the r- or l-value reference type back to the fully
415     // qualified one.
416     if (IsLValueRefTy)
417       QT = Ctx.getLValueReferenceType(QT);
418     else
419       QT = Ctx.getRValueReferenceType(QT);
420     // Add back the qualifiers.
421     QT = Ctx.getQualifiedType(QT, Quals);
422     return QT;
423   }
424 
425   // We don't consider the alias introduced by `using a::X` as a new type.
426   // The qualified name is still a::X.
427   if (isa<UsingType>(QT.getTypePtr())) {
428     return getFullyQualifiedType(QT.getSingleStepDesugaredType(Ctx), Ctx,
429                                  WithGlobalNsPrefix);
430   }
431 
432   // Remove the part of the type related to the type being a template
433   // parameter (we won't report it as part of the 'type name' and it
434   // is actually make the code below to be more complex (to handle
435   // those)
436   while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
437     // Get the qualifiers.
438     Qualifiers Quals = QT.getQualifiers();
439 
440     QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
441 
442     // Add back the qualifiers.
443     QT = Ctx.getQualifiedType(QT, Quals);
444   }
445 
446   NestedNameSpecifier *Prefix = nullptr;
447   // Local qualifiers are attached to the QualType outside of the
448   // elaborated type.  Retrieve them before descending into the
449   // elaborated type.
450   Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
451   QT = QualType(QT.getTypePtr(), 0);
452   ElaboratedTypeKeyword Keyword = ETK_None;
453   if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
454     QT = ETypeInput->getNamedType();
455     assert(!QT.hasLocalQualifiers());
456     Keyword = ETypeInput->getKeyword();
457   }
458   // Create a nested name specifier if needed.
459   Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(),
460                                                true /*FullyQualified*/,
461                                                WithGlobalNsPrefix);
462 
463   // In case of template specializations iterate over the arguments and
464   // fully qualify them as well.
465   if (isa<const TemplateSpecializationType>(QT.getTypePtr()) ||
466       isa<const RecordType>(QT.getTypePtr())) {
467     // We are asked to fully qualify and we have a Record Type (which
468     // may point to a template specialization) or Template
469     // Specialization Type. We need to fully qualify their arguments.
470 
471     const Type *TypePtr = getFullyQualifiedTemplateType(
472         Ctx, QT.getTypePtr(), WithGlobalNsPrefix);
473     QT = QualType(TypePtr, 0);
474   }
475   if (Prefix || Keyword != ETK_None) {
476     QT = Ctx.getElaboratedType(Keyword, Prefix, QT);
477   }
478   QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
479   return QT;
480 }
481 
482 std::string getFullyQualifiedName(QualType QT,
483                                   const ASTContext &Ctx,
484                                   const PrintingPolicy &Policy,
485                                   bool WithGlobalNsPrefix) {
486   QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
487   return FQQT.getAsString(Policy);
488 }
489 
490 }  // end namespace TypeName
491 }  // end namespace clang
492