xref: /freebsd/contrib/llvm-project/clang/lib/AST/TemplateName.cpp (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
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/Casting.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include <cassert>
32 #include <optional>
33 #include <string>
34 
35 using namespace clang;
36 
37 TemplateArgument
38 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
39   return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
40 }
41 
42 TemplateTemplateParmDecl *
43 SubstTemplateTemplateParmPackStorage::getParameterPack() const {
44   return cast<TemplateTemplateParmDecl>(
45       getReplacedTemplateParameterList(getAssociatedDecl())
46           ->asArray()[Bits.Index]);
47 }
48 
49 TemplateTemplateParmDecl *
50 SubstTemplateTemplateParmStorage::getParameter() const {
51   return cast<TemplateTemplateParmDecl>(
52       getReplacedTemplateParameterList(getAssociatedDecl())
53           ->asArray()[Bits.Index]);
54 }
55 
56 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
57   Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
58 }
59 
60 void SubstTemplateTemplateParmStorage::Profile(
61     llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
62     unsigned Index, std::optional<unsigned> PackIndex) {
63   Replacement.Profile(ID);
64   ID.AddPointer(AssociatedDecl);
65   ID.AddInteger(Index);
66   ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
67 }
68 
69 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
70     ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
71     bool Final)
72     : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
73                                   ArgPack.size()),
74       Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
75   assert(AssociatedDecl != nullptr);
76 }
77 
78 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
79                                                    ASTContext &Context) {
80   Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
81           getFinal());
82 }
83 
84 Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
85   return AssociatedDeclAndFinal.getPointer();
86 }
87 
88 bool SubstTemplateTemplateParmPackStorage::getFinal() const {
89   return AssociatedDeclAndFinal.getInt();
90 }
91 
92 void SubstTemplateTemplateParmPackStorage::Profile(
93     llvm::FoldingSetNodeID &ID, ASTContext &Context,
94     const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
95     bool Final) {
96   ArgPack.Profile(ID, Context);
97   ID.AddPointer(AssociatedDecl);
98   ID.AddInteger(Index);
99   ID.AddBoolean(Final);
100 }
101 
102 TemplateName::TemplateName(void *Ptr) {
103   Storage = StorageType::getFromOpaqueValue(Ptr);
104 }
105 
106 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
107 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
108     : Storage(Storage) {}
109 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
110     : Storage(Storage) {}
111 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
112     : Storage(Storage) {}
113 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
114     : Storage(Storage) {}
115 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
116 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
117 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
118 
119 bool TemplateName::isNull() const { return Storage.isNull(); }
120 
121 TemplateName::NameKind TemplateName::getKind() const {
122   if (auto *ND = Storage.dyn_cast<Decl *>()) {
123     if (isa<UsingShadowDecl>(ND))
124       return UsingTemplate;
125     assert(isa<TemplateDecl>(ND));
126     return Template;
127   }
128 
129   if (Storage.is<DependentTemplateName *>())
130     return DependentTemplate;
131   if (Storage.is<QualifiedTemplateName *>())
132     return QualifiedTemplate;
133 
134   UncommonTemplateNameStorage *uncommon
135     = Storage.get<UncommonTemplateNameStorage*>();
136   if (uncommon->getAsOverloadedStorage())
137     return OverloadedTemplate;
138   if (uncommon->getAsAssumedTemplateName())
139     return AssumedTemplate;
140   if (uncommon->getAsSubstTemplateTemplateParm())
141     return SubstTemplateTemplateParm;
142   return SubstTemplateTemplateParmPack;
143 }
144 
145 TemplateDecl *TemplateName::getAsTemplateDecl() const {
146   if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) {
147     if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing))
148       return cast<TemplateDecl>(USD->getTargetDecl());
149 
150     assert(isa<TemplateDecl>(TemplateOrUsing));
151     return cast<TemplateDecl>(TemplateOrUsing);
152   }
153 
154   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
155     return QTN->getUnderlyingTemplate().getAsTemplateDecl();
156 
157   if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
158     return sub->getReplacement().getAsTemplateDecl();
159 
160   if (UsingShadowDecl *USD = getAsUsingShadowDecl())
161     return cast<TemplateDecl>(USD->getTargetDecl());
162 
163   return nullptr;
164 }
165 
166 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
167   if (UncommonTemplateNameStorage *Uncommon =
168           Storage.dyn_cast<UncommonTemplateNameStorage *>())
169     return Uncommon->getAsOverloadedStorage();
170 
171   return nullptr;
172 }
173 
174 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
175   if (UncommonTemplateNameStorage *Uncommon =
176           Storage.dyn_cast<UncommonTemplateNameStorage *>())
177     return Uncommon->getAsAssumedTemplateName();
178 
179   return nullptr;
180 }
181 
182 SubstTemplateTemplateParmStorage *
183 TemplateName::getAsSubstTemplateTemplateParm() const {
184   if (UncommonTemplateNameStorage *uncommon =
185           Storage.dyn_cast<UncommonTemplateNameStorage *>())
186     return uncommon->getAsSubstTemplateTemplateParm();
187 
188   return nullptr;
189 }
190 
191 SubstTemplateTemplateParmPackStorage *
192 TemplateName::getAsSubstTemplateTemplateParmPack() const {
193   if (UncommonTemplateNameStorage *Uncommon =
194           Storage.dyn_cast<UncommonTemplateNameStorage *>())
195     return Uncommon->getAsSubstTemplateTemplateParmPack();
196 
197   return nullptr;
198 }
199 
200 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
201   return Storage.dyn_cast<QualifiedTemplateName *>();
202 }
203 
204 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
205   return Storage.dyn_cast<DependentTemplateName *>();
206 }
207 
208 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
209   if (Decl *D = Storage.dyn_cast<Decl *>())
210     if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
211       return USD;
212   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
213     return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
214   return nullptr;
215 }
216 
217 TemplateName TemplateName::getNameToSubstitute() const {
218   TemplateDecl *Decl = getAsTemplateDecl();
219 
220   // Substituting a dependent template name: preserve it as written.
221   if (!Decl)
222     return *this;
223 
224   // If we have a template declaration, use the most recent non-friend
225   // declaration of that template.
226   Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
227   while (Decl->getFriendObjectKind()) {
228     Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
229     assert(Decl && "all declarations of template are friends");
230   }
231   return TemplateName(Decl);
232 }
233 
234 TemplateNameDependence TemplateName::getDependence() const {
235   auto D = TemplateNameDependence::None;
236   switch (getKind()) {
237   case TemplateName::NameKind::QualifiedTemplate:
238     D |= toTemplateNameDependence(
239         getAsQualifiedTemplateName()->getQualifier()->getDependence());
240     break;
241   case TemplateName::NameKind::DependentTemplate:
242     D |= toTemplateNameDependence(
243         getAsDependentTemplateName()->getQualifier()->getDependence());
244     break;
245   case TemplateName::NameKind::SubstTemplateTemplateParmPack:
246     D |= TemplateNameDependence::UnexpandedPack;
247     break;
248   case TemplateName::NameKind::OverloadedTemplate:
249     llvm_unreachable("overloaded templates shouldn't survive to here.");
250   default:
251     break;
252   }
253   if (TemplateDecl *Template = getAsTemplateDecl()) {
254     if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
255       D |= TemplateNameDependence::DependentInstantiation;
256       if (TTP->isParameterPack())
257         D |= TemplateNameDependence::UnexpandedPack;
258     }
259     // FIXME: Hack, getDeclContext() can be null if Template is still
260     // initializing due to PCH reading, so we check it before using it.
261     // Should probably modify TemplateSpecializationType to allow constructing
262     // it without the isDependent() checking.
263     if (Template->getDeclContext() &&
264         Template->getDeclContext()->isDependentContext())
265       D |= TemplateNameDependence::DependentInstantiation;
266   } else {
267     D |= TemplateNameDependence::DependentInstantiation;
268   }
269   return D;
270 }
271 
272 bool TemplateName::isDependent() const {
273   return getDependence() & TemplateNameDependence::Dependent;
274 }
275 
276 bool TemplateName::isInstantiationDependent() const {
277   return getDependence() & TemplateNameDependence::Instantiation;
278 }
279 
280 bool TemplateName::containsUnexpandedParameterPack() const {
281   return getDependence() & TemplateNameDependence::UnexpandedPack;
282 }
283 
284 void TemplateName::Profile(llvm::FoldingSetNodeID &ID) {
285   if (const auto* USD = getAsUsingShadowDecl())
286     ID.AddPointer(USD->getCanonicalDecl());
287   else if (const auto *TD = getAsTemplateDecl())
288     ID.AddPointer(TD->getCanonicalDecl());
289   else
290     ID.AddPointer(Storage.getOpaqueValue());
291 }
292 
293 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
294                          Qualified Qual) const {
295   auto Kind = getKind();
296   TemplateDecl *Template = nullptr;
297   if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
298     // After `namespace ns { using std::vector }`, what is the fully-qualified
299     // name of the UsingTemplateName `vector` within ns?
300     //
301     // - ns::vector (the qualified name of the using-shadow decl)
302     // - std::vector (the qualified name of the underlying template decl)
303     //
304     // Similar to the UsingType behavior, using declarations are used to import
305     // names more often than to export them, thus using the original name is
306     // most useful in this case.
307     Template = getAsTemplateDecl();
308   }
309 
310   if (Template)
311     if (Policy.CleanUglifiedParameters &&
312         isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
313       OS << Template->getIdentifier()->deuglifiedName();
314     else if (Qual == Qualified::Fully &&
315              getDependence() !=
316                  TemplateNameDependenceScope::DependentInstantiation)
317       Template->printQualifiedName(OS, Policy);
318     else
319       OS << *Template;
320   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
321     if (Qual == Qualified::Fully &&
322         getDependence() !=
323             TemplateNameDependenceScope::DependentInstantiation) {
324       QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
325           OS, Policy);
326       return;
327     }
328     if (Qual == Qualified::AsWritten)
329       QTN->getQualifier()->print(OS, Policy);
330     if (QTN->hasTemplateKeyword())
331       OS << "template ";
332     OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
333   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
334     if (Qual == Qualified::AsWritten && DTN->getQualifier())
335       DTN->getQualifier()->print(OS, Policy);
336     OS << "template ";
337 
338     if (DTN->isIdentifier())
339       OS << DTN->getIdentifier()->getName();
340     else
341       OS << "operator " << getOperatorSpelling(DTN->getOperator());
342   } else if (SubstTemplateTemplateParmStorage *subst
343                = getAsSubstTemplateTemplateParm()) {
344     subst->getReplacement().print(OS, Policy, Qual);
345   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
346                                         = getAsSubstTemplateTemplateParmPack())
347     OS << *SubstPack->getParameterPack();
348   else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
349     Assumed->getDeclName().print(OS, Policy);
350   } else {
351     assert(getKind() == TemplateName::OverloadedTemplate);
352     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
353     (*OTS->begin())->printName(OS, Policy);
354   }
355 }
356 
357 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
358                                              TemplateName N) {
359   std::string NameStr;
360   llvm::raw_string_ostream OS(NameStr);
361   LangOptions LO;
362   LO.CPlusPlus = true;
363   LO.Bool = true;
364   OS << '\'';
365   N.print(OS, PrintingPolicy(LO));
366   OS << '\'';
367   OS.flush();
368   return DB << NameStr;
369 }
370 
371 void TemplateName::dump(raw_ostream &OS) const {
372   LangOptions LO;  // FIXME!
373   LO.CPlusPlus = true;
374   LO.Bool = true;
375   print(OS, PrintingPolicy(LO));
376 }
377 
378 LLVM_DUMP_METHOD void TemplateName::dump() const {
379   dump(llvm::errs());
380 }
381