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