xref: /llvm-project/clang/lib/AST/TemplateName.cpp (revision 563c7c5539f05e7f8cbb42565c1f24466019f38b)
1 //===- TemplateName.cpp - C++ Template Name Representation ----------------===//
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 //  This file defines the TemplateName interface and subclasses.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/TemplateName.h"
14 #include "clang/AST/Decl.h"
15 #include "clang/AST/DeclBase.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclTemplate.h"
18 #include "clang/AST/DependenceFlags.h"
19 #include "clang/AST/NestedNameSpecifier.h"
20 #include "clang/AST/PrettyPrinter.h"
21 #include "clang/AST/TemplateBase.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "clang/Basic/LLVM.h"
24 #include "clang/Basic/LangOptions.h"
25 #include "clang/Basic/OperatorKinds.h"
26 #include "llvm/ADT/ArrayRef.h"
27 #include "llvm/ADT/FoldingSet.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include <cassert>
31 #include <optional>
32 #include <string>
33 
34 using namespace clang;
35 
36 DeducedTemplateStorage::DeducedTemplateStorage(TemplateName Underlying,
37                                                const DefaultArguments &DefArgs)
38     : UncommonTemplateNameStorage(Deduced, /*Index=*/DefArgs.StartPos,
39                                   DefArgs.Args.size()),
40       Underlying(Underlying) {
41   llvm::copy(DefArgs.Args, reinterpret_cast<TemplateArgument *>(this + 1));
42 }
43 
44 void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
45                                      const ASTContext &Context) const {
46   Profile(ID, Context, Underlying, getDefaultArguments());
47 }
48 
49 void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
50                                      const ASTContext &Context,
51                                      TemplateName Underlying,
52                                      const DefaultArguments &DefArgs) {
53   Underlying.Profile(ID);
54   ID.AddInteger(DefArgs.StartPos);
55   ID.AddInteger(DefArgs.Args.size());
56   for (const TemplateArgument &Arg : DefArgs.Args)
57     Arg.Profile(ID, Context);
58 }
59 
60 TemplateArgument
61 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
62   return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
63 }
64 
65 TemplateTemplateParmDecl *
66 SubstTemplateTemplateParmPackStorage::getParameterPack() const {
67   return cast<TemplateTemplateParmDecl>(
68       getReplacedTemplateParameterList(getAssociatedDecl())
69           ->asArray()[Bits.Index]);
70 }
71 
72 TemplateTemplateParmDecl *
73 SubstTemplateTemplateParmStorage::getParameter() const {
74   return cast<TemplateTemplateParmDecl>(
75       getReplacedTemplateParameterList(getAssociatedDecl())
76           ->asArray()[Bits.Index]);
77 }
78 
79 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
80   Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
81 }
82 
83 void SubstTemplateTemplateParmStorage::Profile(
84     llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
85     unsigned Index, std::optional<unsigned> PackIndex) {
86   Replacement.Profile(ID);
87   ID.AddPointer(AssociatedDecl);
88   ID.AddInteger(Index);
89   ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
90 }
91 
92 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
93     ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
94     bool Final)
95     : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
96                                   ArgPack.size()),
97       Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
98   assert(AssociatedDecl != nullptr);
99 }
100 
101 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
102                                                    ASTContext &Context) {
103   Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
104           getFinal());
105 }
106 
107 Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
108   return AssociatedDeclAndFinal.getPointer();
109 }
110 
111 bool SubstTemplateTemplateParmPackStorage::getFinal() const {
112   return AssociatedDeclAndFinal.getInt();
113 }
114 
115 void SubstTemplateTemplateParmPackStorage::Profile(
116     llvm::FoldingSetNodeID &ID, ASTContext &Context,
117     const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
118     bool Final) {
119   ArgPack.Profile(ID, Context);
120   ID.AddPointer(AssociatedDecl);
121   ID.AddInteger(Index);
122   ID.AddBoolean(Final);
123 }
124 
125 TemplateName::TemplateName(void *Ptr) {
126   Storage = StorageType::getFromOpaqueValue(Ptr);
127 }
128 
129 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
130 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
131     : Storage(Storage) {}
132 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
133     : Storage(Storage) {}
134 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
135     : Storage(Storage) {}
136 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
137     : Storage(Storage) {}
138 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
139 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
140 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
141 TemplateName::TemplateName(DeducedTemplateStorage *Deduced)
142     : Storage(Deduced) {}
143 
144 bool TemplateName::isNull() const { return Storage.isNull(); }
145 
146 TemplateName::NameKind TemplateName::getKind() const {
147   if (auto *ND = Storage.dyn_cast<Decl *>()) {
148     if (isa<UsingShadowDecl>(ND))
149       return UsingTemplate;
150     assert(isa<TemplateDecl>(ND));
151     return Template;
152   }
153 
154   if (isa<DependentTemplateName *>(Storage))
155     return DependentTemplate;
156   if (isa<QualifiedTemplateName *>(Storage))
157     return QualifiedTemplate;
158 
159   UncommonTemplateNameStorage *uncommon =
160       cast<UncommonTemplateNameStorage *>(Storage);
161   if (uncommon->getAsOverloadedStorage())
162     return OverloadedTemplate;
163   if (uncommon->getAsAssumedTemplateName())
164     return AssumedTemplate;
165   if (uncommon->getAsSubstTemplateTemplateParm())
166     return SubstTemplateTemplateParm;
167   if (uncommon->getAsDeducedTemplateName())
168     return DeducedTemplate;
169 
170   assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr);
171   return SubstTemplateTemplateParmPack;
172 }
173 
174 TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const {
175   TemplateName Name = *this;
176   while (std::optional<TemplateName> UnderlyingOrNone =
177              Name.desugar(IgnoreDeduced))
178     Name = *UnderlyingOrNone;
179 
180   if (!IgnoreDeduced)
181     assert(Name.getAsDeducedTemplateName() == nullptr &&
182            "Unexpected canonical DeducedTemplateName; Did you mean to use "
183            "getTemplateDeclAndDefaultArgs instead?");
184 
185   return cast_if_present<TemplateDecl>(
186       dyn_cast_if_present<Decl *>(Name.Storage));
187 }
188 
189 std::pair<TemplateDecl *, DefaultArguments>
190 TemplateName::getTemplateDeclAndDefaultArgs() const {
191   for (TemplateName Name = *this; /**/; /**/) {
192     if (Name.getKind() == TemplateName::DeducedTemplate) {
193       DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName();
194       TemplateDecl *TD =
195           DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true);
196       DefaultArguments DefArgs = DTS->getDefaultArguments();
197       if (TD && DefArgs)
198         assert(DefArgs.StartPos + DefArgs.Args.size() <=
199                TD->getTemplateParameters()->size());
200       return {TD, DTS->getDefaultArguments()};
201     }
202     if (std::optional<TemplateName> UnderlyingOrNone =
203             Name.desugar(/*IgnoreDeduced=*/false)) {
204       Name = *UnderlyingOrNone;
205       continue;
206     }
207     return {cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()), {}};
208   }
209 }
210 
211 std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const {
212   if (Decl *D = dyn_cast_if_present<Decl *>(Storage)) {
213     if (auto *USD = dyn_cast<UsingShadowDecl>(D))
214       return TemplateName(USD->getTargetDecl());
215     return std::nullopt;
216   }
217   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
218     return QTN->getUnderlyingTemplate();
219   if (SubstTemplateTemplateParmStorage *S = getAsSubstTemplateTemplateParm())
220     return S->getReplacement();
221   if (IgnoreDeduced)
222     if (DeducedTemplateStorage *S = getAsDeducedTemplateName())
223       return S->getUnderlying();
224   return std::nullopt;
225 }
226 
227 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
228   if (UncommonTemplateNameStorage *Uncommon =
229           Storage.dyn_cast<UncommonTemplateNameStorage *>())
230     return Uncommon->getAsOverloadedStorage();
231 
232   return nullptr;
233 }
234 
235 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
236   if (UncommonTemplateNameStorage *Uncommon =
237           Storage.dyn_cast<UncommonTemplateNameStorage *>())
238     return Uncommon->getAsAssumedTemplateName();
239 
240   return nullptr;
241 }
242 
243 SubstTemplateTemplateParmStorage *
244 TemplateName::getAsSubstTemplateTemplateParm() const {
245   if (UncommonTemplateNameStorage *uncommon =
246           dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
247     return uncommon->getAsSubstTemplateTemplateParm();
248 
249   return nullptr;
250 }
251 
252 SubstTemplateTemplateParmPackStorage *
253 TemplateName::getAsSubstTemplateTemplateParmPack() const {
254   if (UncommonTemplateNameStorage *Uncommon =
255           Storage.dyn_cast<UncommonTemplateNameStorage *>())
256     return Uncommon->getAsSubstTemplateTemplateParmPack();
257 
258   return nullptr;
259 }
260 
261 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
262   return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
263 }
264 
265 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
266   return Storage.dyn_cast<DependentTemplateName *>();
267 }
268 
269 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
270   if (Decl *D = Storage.dyn_cast<Decl *>())
271     if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
272       return USD;
273   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
274     return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
275   return nullptr;
276 }
277 
278 DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const {
279   if (UncommonTemplateNameStorage *Uncommon =
280           dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
281     return Uncommon->getAsDeducedTemplateName();
282 
283   return nullptr;
284 }
285 
286 TemplateNameDependence TemplateName::getDependence() const {
287   switch (getKind()) {
288   case NameKind::Template:
289   case NameKind::UsingTemplate: {
290     TemplateDecl *Template = getAsTemplateDecl();
291     auto D = TemplateNameDependence::None;
292     if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
293       D |= TemplateNameDependence::DependentInstantiation;
294       if (TTP->isParameterPack())
295         D |= TemplateNameDependence::UnexpandedPack;
296     }
297     // FIXME: Hack, getDeclContext() can be null if Template is still
298     // initializing due to PCH reading, so we check it before using it.
299     // Should probably modify TemplateSpecializationType to allow constructing
300     // it without the isDependent() checking.
301     if (Template->getDeclContext() &&
302         Template->getDeclContext()->isDependentContext())
303       D |= TemplateNameDependence::DependentInstantiation;
304     return D;
305   }
306   case NameKind::QualifiedTemplate: {
307     QualifiedTemplateName *S = getAsQualifiedTemplateName();
308     TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
309     if (NestedNameSpecifier *NNS = S->getQualifier())
310       D |= toTemplateNameDependence(NNS->getDependence());
311     return D;
312   }
313   case NameKind::DependentTemplate: {
314     DependentTemplateName *S = getAsDependentTemplateName();
315     auto D = TemplateNameDependence::DependentInstantiation;
316     D |= toTemplateNameDependence(S->getQualifier()->getDependence());
317     return D;
318   }
319   case NameKind::SubstTemplateTemplateParm: {
320     auto *S = getAsSubstTemplateTemplateParm();
321     return S->getReplacement().getDependence();
322   }
323   case NameKind::SubstTemplateTemplateParmPack:
324     return TemplateNameDependence::UnexpandedPack |
325            TemplateNameDependence::DependentInstantiation;
326   case NameKind::DeducedTemplate: {
327     DeducedTemplateStorage *DTS = getAsDeducedTemplateName();
328     TemplateNameDependence D = DTS->getUnderlying().getDependence();
329     for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args)
330       D |= toTemplateNameDependence(Arg.getDependence());
331     return D;
332   }
333   case NameKind::AssumedTemplate:
334     return TemplateNameDependence::DependentInstantiation;
335   case NameKind::OverloadedTemplate:
336     llvm_unreachable("overloaded templates shouldn't survive to here.");
337   }
338   llvm_unreachable("Unknown TemplateName kind");
339 }
340 
341 bool TemplateName::isDependent() const {
342   return getDependence() & TemplateNameDependence::Dependent;
343 }
344 
345 bool TemplateName::isInstantiationDependent() const {
346   return getDependence() & TemplateNameDependence::Instantiation;
347 }
348 
349 bool TemplateName::containsUnexpandedParameterPack() const {
350   return getDependence() & TemplateNameDependence::UnexpandedPack;
351 }
352 
353 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
354                          Qualified Qual) const {
355   auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
356     if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
357         TTP && TTP->getIdentifier() == nullptr) {
358       OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
359       return true;
360     }
361     return false;
362   };
363   if (NameKind Kind = getKind();
364       Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
365     // After `namespace ns { using std::vector }`, what is the fully-qualified
366     // name of the UsingTemplateName `vector` within ns?
367     //
368     // - ns::vector (the qualified name of the using-shadow decl)
369     // - std::vector (the qualified name of the underlying template decl)
370     //
371     // Similar to the UsingType behavior, using declarations are used to import
372     // names more often than to export them, thus using the original name is
373     // most useful in this case.
374     TemplateDecl *Template = getAsTemplateDecl();
375     if (handleAnonymousTTP(Template, OS))
376       return;
377     if (Qual == Qualified::None)
378       OS << *Template;
379     else
380       Template->printQualifiedName(OS, Policy);
381   } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
382     if (NestedNameSpecifier *NNS = QTN->getQualifier();
383         Qual != Qualified::None && NNS)
384       NNS->print(OS, Policy);
385     if (QTN->hasTemplateKeyword())
386       OS << "template ";
387 
388     TemplateName Underlying = QTN->getUnderlyingTemplate();
389     assert(Underlying.getKind() == TemplateName::Template ||
390            Underlying.getKind() == TemplateName::UsingTemplate);
391 
392     TemplateDecl *UTD = Underlying.getAsTemplateDecl();
393 
394     if (handleAnonymousTTP(UTD, OS))
395       return;
396 
397     if (IdentifierInfo *II = UTD->getIdentifier();
398         Policy.CleanUglifiedParameters && II &&
399         isa<TemplateTemplateParmDecl>(UTD))
400       OS << II->deuglifiedName();
401     else
402       OS << *UTD;
403   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
404     if (NestedNameSpecifier *NNS = DTN->getQualifier())
405       NNS->print(OS, Policy);
406     OS << "template ";
407 
408     if (DTN->isIdentifier())
409       OS << DTN->getIdentifier()->getName();
410     else
411       OS << "operator " << getOperatorSpelling(DTN->getOperator());
412   } else if (SubstTemplateTemplateParmStorage *subst =
413                  getAsSubstTemplateTemplateParm()) {
414     subst->getReplacement().print(OS, Policy, Qual);
415   } else if (SubstTemplateTemplateParmPackStorage *SubstPack =
416                  getAsSubstTemplateTemplateParmPack())
417     OS << *SubstPack->getParameterPack();
418   else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
419     Assumed->getDeclName().print(OS, Policy);
420   } else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) {
421     Deduced->getUnderlying().print(OS, Policy);
422     DefaultArguments DefArgs = Deduced->getDefaultArguments();
423     OS << ":" << DefArgs.StartPos;
424     printTemplateArgumentList(OS, DefArgs.Args, Policy);
425   } else {
426     assert(getKind() == TemplateName::OverloadedTemplate);
427     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
428     (*OTS->begin())->printName(OS, Policy);
429   }
430 }
431 
432 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
433                                              TemplateName N) {
434   std::string NameStr;
435   llvm::raw_string_ostream OS(NameStr);
436   LangOptions LO;
437   LO.CPlusPlus = true;
438   LO.Bool = true;
439   OS << '\'';
440   N.print(OS, PrintingPolicy(LO));
441   OS << '\'';
442   return DB << NameStr;
443 }
444