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
getArgumentPack() const38 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
39 return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
40 }
41
42 TemplateTemplateParmDecl *
getParameterPack() const43 SubstTemplateTemplateParmPackStorage::getParameterPack() const {
44 return cast<TemplateTemplateParmDecl>(
45 getReplacedTemplateParameterList(getAssociatedDecl())
46 ->asArray()[Bits.Index]);
47 }
48
49 TemplateTemplateParmDecl *
getParameter() const50 SubstTemplateTemplateParmStorage::getParameter() const {
51 return cast<TemplateTemplateParmDecl>(
52 getReplacedTemplateParameterList(getAssociatedDecl())
53 ->asArray()[Bits.Index]);
54 }
55
Profile(llvm::FoldingSetNodeID & ID)56 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
57 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
58 }
59
Profile(llvm::FoldingSetNodeID & ID,TemplateName Replacement,Decl * AssociatedDecl,unsigned Index,std::optional<unsigned> PackIndex)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
SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,Decl * AssociatedDecl,unsigned Index,bool Final)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
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context)78 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
79 ASTContext &Context) {
80 Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
81 getFinal());
82 }
83
getAssociatedDecl() const84 Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
85 return AssociatedDeclAndFinal.getPointer();
86 }
87
getFinal() const88 bool SubstTemplateTemplateParmPackStorage::getFinal() const {
89 return AssociatedDeclAndFinal.getInt();
90 }
91
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context,const TemplateArgument & ArgPack,Decl * AssociatedDecl,unsigned Index,bool Final)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
TemplateName(void * Ptr)102 TemplateName::TemplateName(void *Ptr) {
103 Storage = StorageType::getFromOpaqueValue(Ptr);
104 }
105
TemplateName(TemplateDecl * Template)106 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
TemplateName(OverloadedTemplateStorage * Storage)107 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
108 : Storage(Storage) {}
TemplateName(AssumedTemplateStorage * Storage)109 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
110 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmStorage * Storage)111 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
112 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmPackStorage * Storage)113 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
114 : Storage(Storage) {}
TemplateName(QualifiedTemplateName * Qual)115 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
TemplateName(DependentTemplateName * Dep)116 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
TemplateName(UsingShadowDecl * Using)117 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
118
isNull() const119 bool TemplateName::isNull() const { return Storage.isNull(); }
120
getKind() const121 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
getAsTemplateDecl() const145 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
getAsOverloadedTemplate() const166 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
167 if (UncommonTemplateNameStorage *Uncommon =
168 Storage.dyn_cast<UncommonTemplateNameStorage *>())
169 return Uncommon->getAsOverloadedStorage();
170
171 return nullptr;
172 }
173
getAsAssumedTemplateName() const174 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 *
getAsSubstTemplateTemplateParm() const183 TemplateName::getAsSubstTemplateTemplateParm() const {
184 if (UncommonTemplateNameStorage *uncommon =
185 Storage.dyn_cast<UncommonTemplateNameStorage *>())
186 return uncommon->getAsSubstTemplateTemplateParm();
187
188 return nullptr;
189 }
190
191 SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const192 TemplateName::getAsSubstTemplateTemplateParmPack() const {
193 if (UncommonTemplateNameStorage *Uncommon =
194 Storage.dyn_cast<UncommonTemplateNameStorage *>())
195 return Uncommon->getAsSubstTemplateTemplateParmPack();
196
197 return nullptr;
198 }
199
getAsQualifiedTemplateName() const200 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
201 return Storage.dyn_cast<QualifiedTemplateName *>();
202 }
203
getAsDependentTemplateName() const204 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
205 return Storage.dyn_cast<DependentTemplateName *>();
206 }
207
getAsUsingShadowDecl() const208 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
getNameToSubstitute() const217 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
getDependence() const234 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
isDependent() const272 bool TemplateName::isDependent() const {
273 return getDependence() & TemplateNameDependence::Dependent;
274 }
275
isInstantiationDependent() const276 bool TemplateName::isInstantiationDependent() const {
277 return getDependence() & TemplateNameDependence::Instantiation;
278 }
279
containsUnexpandedParameterPack() const280 bool TemplateName::containsUnexpandedParameterPack() const {
281 return getDependence() & TemplateNameDependence::UnexpandedPack;
282 }
283
print(raw_ostream & OS,const PrintingPolicy & Policy,Qualified Qual) const284 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
285 Qualified Qual) const {
286 auto Kind = getKind();
287 TemplateDecl *Template = nullptr;
288 if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
289 // After `namespace ns { using std::vector }`, what is the fully-qualified
290 // name of the UsingTemplateName `vector` within ns?
291 //
292 // - ns::vector (the qualified name of the using-shadow decl)
293 // - std::vector (the qualified name of the underlying template decl)
294 //
295 // Similar to the UsingType behavior, using declarations are used to import
296 // names more often than to export them, thus using the original name is
297 // most useful in this case.
298 Template = getAsTemplateDecl();
299 }
300
301 if (Template)
302 if (Policy.CleanUglifiedParameters &&
303 isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
304 OS << Template->getIdentifier()->deuglifiedName();
305 else if (Qual == Qualified::Fully &&
306 getDependence() !=
307 TemplateNameDependenceScope::DependentInstantiation)
308 Template->printQualifiedName(OS, Policy);
309 else
310 OS << *Template;
311 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
312 if (Qual == Qualified::Fully &&
313 getDependence() !=
314 TemplateNameDependenceScope::DependentInstantiation) {
315 QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
316 OS, Policy);
317 return;
318 }
319 if (Qual == Qualified::AsWritten)
320 QTN->getQualifier()->print(OS, Policy);
321 if (QTN->hasTemplateKeyword())
322 OS << "template ";
323 OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
324 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
325 if (Qual == Qualified::AsWritten && DTN->getQualifier())
326 DTN->getQualifier()->print(OS, Policy);
327 OS << "template ";
328
329 if (DTN->isIdentifier())
330 OS << DTN->getIdentifier()->getName();
331 else
332 OS << "operator " << getOperatorSpelling(DTN->getOperator());
333 } else if (SubstTemplateTemplateParmStorage *subst
334 = getAsSubstTemplateTemplateParm()) {
335 subst->getReplacement().print(OS, Policy, Qual);
336 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
337 = getAsSubstTemplateTemplateParmPack())
338 OS << *SubstPack->getParameterPack();
339 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
340 Assumed->getDeclName().print(OS, Policy);
341 } else {
342 assert(getKind() == TemplateName::OverloadedTemplate);
343 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
344 (*OTS->begin())->printName(OS, Policy);
345 }
346 }
347
operator <<(const StreamingDiagnostic & DB,TemplateName N)348 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
349 TemplateName N) {
350 std::string NameStr;
351 llvm::raw_string_ostream OS(NameStr);
352 LangOptions LO;
353 LO.CPlusPlus = true;
354 LO.Bool = true;
355 OS << '\'';
356 N.print(OS, PrintingPolicy(LO));
357 OS << '\'';
358 OS.flush();
359 return DB << NameStr;
360 }
361
dump(raw_ostream & OS) const362 void TemplateName::dump(raw_ostream &OS) const {
363 LangOptions LO; // FIXME!
364 LO.CPlusPlus = true;
365 LO.Bool = true;
366 print(OS, PrintingPolicy(LO));
367 }
368
dump() const369 LLVM_DUMP_METHOD void TemplateName::dump() const {
370 dump(llvm::errs());
371 }
372