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