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->getTemplateDecl();
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   return nullptr;
176 }
177 
178 TemplateName TemplateName::getNameToSubstitute() const {
179   TemplateDecl *Decl = getAsTemplateDecl();
180 
181   // Substituting a dependent template name: preserve it as written.
182   if (!Decl)
183     return *this;
184 
185   // If we have a template declaration, use the most recent non-friend
186   // declaration of that template.
187   Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
188   while (Decl->getFriendObjectKind()) {
189     Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
190     assert(Decl && "all declarations of template are friends");
191   }
192   return TemplateName(Decl);
193 }
194 
195 TemplateNameDependence TemplateName::getDependence() const {
196   auto D = TemplateNameDependence::None;
197   switch (getKind()) {
198   case TemplateName::NameKind::QualifiedTemplate:
199     D |= toTemplateNameDependence(
200         getAsQualifiedTemplateName()->getQualifier()->getDependence());
201     break;
202   case TemplateName::NameKind::DependentTemplate:
203     D |= toTemplateNameDependence(
204         getAsDependentTemplateName()->getQualifier()->getDependence());
205     break;
206   case TemplateName::NameKind::SubstTemplateTemplateParmPack:
207     D |= TemplateNameDependence::UnexpandedPack;
208     break;
209   case TemplateName::NameKind::OverloadedTemplate:
210     llvm_unreachable("overloaded templates shouldn't survive to here.");
211   default:
212     break;
213   }
214   if (TemplateDecl *Template = getAsTemplateDecl()) {
215     if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
216       D |= TemplateNameDependence::DependentInstantiation;
217       if (TTP->isParameterPack())
218         D |= TemplateNameDependence::UnexpandedPack;
219     }
220     // FIXME: Hack, getDeclContext() can be null if Template is still
221     // initializing due to PCH reading, so we check it before using it.
222     // Should probably modify TemplateSpecializationType to allow constructing
223     // it without the isDependent() checking.
224     if (Template->getDeclContext() &&
225         Template->getDeclContext()->isDependentContext())
226       D |= TemplateNameDependence::DependentInstantiation;
227   } else {
228     D |= TemplateNameDependence::DependentInstantiation;
229   }
230   return D;
231 }
232 
233 bool TemplateName::isDependent() const {
234   return getDependence() & TemplateNameDependence::Dependent;
235 }
236 
237 bool TemplateName::isInstantiationDependent() const {
238   return getDependence() & TemplateNameDependence::Instantiation;
239 }
240 
241 bool TemplateName::containsUnexpandedParameterPack() const {
242   return getDependence() & TemplateNameDependence::UnexpandedPack;
243 }
244 
245 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
246                          Qualified Qual) const {
247   auto Kind = getKind();
248   TemplateDecl *Template = nullptr;
249   if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
250     // After `namespace ns { using std::vector }`, what is the fully-qualified
251     // name of the UsingTemplateName `vector` within ns?
252     //
253     // - ns::vector (the qualified name of the using-shadow decl)
254     // - std::vector (the qualified name of the underlying template decl)
255     //
256     // Similar to the UsingType behavior, using declarations are used to import
257     // names more often than to export them, thus using the original name is
258     // most useful in this case.
259     Template = getAsTemplateDecl();
260   }
261 
262   if (Template)
263     if (Policy.CleanUglifiedParameters &&
264         isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
265       OS << Template->getIdentifier()->deuglifiedName();
266     else if (Qual == Qualified::Fully &&
267              getDependence() !=
268                  TemplateNameDependenceScope::DependentInstantiation)
269       Template->printQualifiedName(OS, Policy);
270     else
271       OS << *Template;
272   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
273     if (Qual == Qualified::Fully &&
274         getDependence() !=
275             TemplateNameDependenceScope::DependentInstantiation) {
276       QTN->getTemplateDecl()->printQualifiedName(OS, Policy);
277       return;
278     }
279     if (Qual == Qualified::AsWritten)
280       QTN->getQualifier()->print(OS, Policy);
281     if (QTN->hasTemplateKeyword())
282       OS << "template ";
283     OS << *QTN->getTemplateDecl();
284   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
285     if (Qual == Qualified::AsWritten && DTN->getQualifier())
286       DTN->getQualifier()->print(OS, Policy);
287     OS << "template ";
288 
289     if (DTN->isIdentifier())
290       OS << DTN->getIdentifier()->getName();
291     else
292       OS << "operator " << getOperatorSpelling(DTN->getOperator());
293   } else if (SubstTemplateTemplateParmStorage *subst
294                = getAsSubstTemplateTemplateParm()) {
295     subst->getReplacement().print(OS, Policy, Qual);
296   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
297                                         = getAsSubstTemplateTemplateParmPack())
298     OS << *SubstPack->getParameterPack();
299   else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
300     Assumed->getDeclName().print(OS, Policy);
301   } else {
302     assert(getKind() == TemplateName::OverloadedTemplate);
303     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
304     (*OTS->begin())->printName(OS);
305   }
306 }
307 
308 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
309                                              TemplateName N) {
310   std::string NameStr;
311   llvm::raw_string_ostream OS(NameStr);
312   LangOptions LO;
313   LO.CPlusPlus = true;
314   LO.Bool = true;
315   OS << '\'';
316   N.print(OS, PrintingPolicy(LO));
317   OS << '\'';
318   OS.flush();
319   return DB << NameStr;
320 }
321 
322 void TemplateName::dump(raw_ostream &OS) const {
323   LangOptions LO;  // FIXME!
324   LO.CPlusPlus = true;
325   LO.Bool = true;
326   print(OS, PrintingPolicy(LO));
327 }
328 
329 LLVM_DUMP_METHOD void TemplateName::dump() const {
330   dump(llvm::errs());
331 }
332