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