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/PrettyPrinter.h"
20#include "clang/AST/TemplateBase.h"
21#include "clang/Basic/Diagnostic.h"
22#include "clang/Basic/LLVM.h"
23#include "clang/Basic/LangOptions.h"
24#include "clang/Basic/OperatorKinds.h"
25#include "llvm/ADT/ArrayRef.h"
26#include "llvm/ADT/FoldingSet.h"
27#include "llvm/Support/raw_ostream.h"
28#include <cassert>
29#include <optional>
30#include <string>
31
32using namespace clang;
33
34DeducedTemplateStorage::DeducedTemplateStorage(TemplateName Underlying,
35 const DefaultArguments &DefArgs)
36 : UncommonTemplateNameStorage(Deduced, /*Index=*/DefArgs.StartPos,
37 DefArgs.Args.size()),
38 Underlying(Underlying) {
39 llvm::copy(Range: DefArgs.Args, Out: reinterpret_cast<TemplateArgument *>(this + 1));
40}
41
42void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
43 const ASTContext &Context) const {
44 Profile(ID, Context, Underlying, DefArgs: getDefaultArguments());
45}
46
47void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
48 const ASTContext &Context,
49 TemplateName Underlying,
50 const DefaultArguments &DefArgs) {
51 Underlying.Profile(ID);
52 ID.AddInteger(I: DefArgs.StartPos);
53 ID.AddInteger(I: DefArgs.Args.size());
54 for (const TemplateArgument &Arg : DefArgs.Args)
55 Arg.Profile(ID, Context);
56}
57
58TemplateArgument
59SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
60 return TemplateArgument(ArrayRef(Arguments, Bits.Data));
61}
62
63TemplateTemplateParmDecl *
64SubstTemplateTemplateParmPackStorage::getParameterPack() const {
65 return cast<TemplateTemplateParmDecl>(Val: std::get<0>(
66 t: getReplacedTemplateParameter(D: getAssociatedDecl(), Index: Bits.Index)));
67}
68
69TemplateTemplateParmDecl *
70SubstTemplateTemplateParmStorage::getParameter() const {
71 return cast<TemplateTemplateParmDecl>(Val: std::get<0>(
72 t: getReplacedTemplateParameter(D: getAssociatedDecl(), Index: Bits.Index)));
73}
74
75void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
76 Profile(ID, Replacement, AssociatedDecl: getAssociatedDecl(), Index: getIndex(), PackIndex: getPackIndex(),
77 Final: getFinal());
78}
79
80void SubstTemplateTemplateParmStorage::Profile(
81 llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
82 unsigned Index, UnsignedOrNone PackIndex, bool Final) {
83 Replacement.Profile(ID);
84 ID.AddPointer(Ptr: AssociatedDecl);
85 ID.AddInteger(I: Index);
86 ID.AddInteger(I: PackIndex.toInternalRepresentation());
87 ID.AddBoolean(B: Final);
88}
89
90SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
91 ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
92 bool Final)
93 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
94 ArgPack.size()),
95 Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
96 assert(AssociatedDecl != nullptr);
97}
98
99void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
100 ASTContext &Context) {
101 Profile(ID, Context, ArgPack: getArgumentPack(), AssociatedDecl: getAssociatedDecl(), Index: getIndex(),
102 Final: getFinal());
103}
104
105Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
106 return AssociatedDeclAndFinal.getPointer();
107}
108
109bool SubstTemplateTemplateParmPackStorage::getFinal() const {
110 return AssociatedDeclAndFinal.getInt();
111}
112
113void SubstTemplateTemplateParmPackStorage::Profile(
114 llvm::FoldingSetNodeID &ID, ASTContext &Context,
115 const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
116 bool Final) {
117 ArgPack.Profile(ID, Context);
118 ID.AddPointer(Ptr: AssociatedDecl);
119 ID.AddInteger(I: Index);
120 ID.AddBoolean(B: Final);
121}
122
123PackIndexingTemplateStorage::PackIndexingTemplateStorage(
124 TemplateName Pattern, Expr *IndexExpr, bool FullySubstituted,
125 ArrayRef<TemplateName> Expansions)
126 : UncommonTemplateNameStorage(PackIndexing, /*Index=*/0,
127 /*Data=*/Expansions.size()),
128 Pattern(Pattern),
129 IndexAndIsFullySubstituted(IndexExpr, FullySubstituted) {
130 llvm::uninitialized_copy(Src&: Expansions, Dst: getTrailingObjects());
131}
132
133TemplateTemplateParmDecl *
134PackIndexingTemplateStorage::getParameterPack() const {
135 if (SubstTemplateTemplateParmPackStorage *S =
136 Pattern.getAsSubstTemplateTemplateParmPack())
137 return S->getParameterPack();
138 return dyn_cast_if_present<TemplateTemplateParmDecl>(
139 Val: Pattern.getAsTemplateDecl());
140}
141
142UnsignedOrNone PackIndexingTemplateStorage::getSelectedIndex() const {
143 if (getIndexExpr()->isInstantiationDependent())
144 return std::nullopt;
145 auto *CE = dyn_cast<ConstantExpr>(Val: getIndexExpr());
146 if (!CE)
147 return std::nullopt;
148 llvm::APSInt Index = CE->getResultAsAPSInt();
149 assert(Index.isNonNegative() && "Invalid index");
150 return static_cast<unsigned>(Index.getExtValue());
151}
152
153TemplateName PackIndexingTemplateStorage::getSelectedTemplate() const {
154 if (!isFullySubstituted() || getIndexExpr()->isInstantiationDependent())
155 return TemplateName();
156 UnsignedOrNone Index = getSelectedIndex();
157 ArrayRef<TemplateName> Expansions = getExpansions();
158 assert(Index && *Index < Expansions.size());
159 return Expansions[*Index];
160}
161
162TemplateNameDependence PackIndexingTemplateStorage::getDependence() const {
163 TemplateNameDependence IndexD =
164 toTemplateNameDependence(D: getIndexExpr()->getDependence());
165
166 TemplateNameDependence D =
167 IndexD | (getIndexExpr()->isInstantiationDependent()
168 ? TemplateNameDependence::DependentInstantiation
169 : TemplateNameDependence::None);
170 if (ArrayRef<TemplateName> Expansions = getExpansions(); Expansions.empty())
171 D |= Pattern.getDependence() &
172 TemplateNameDependence::DependentInstantiation;
173 else
174 for (TemplateName T : Expansions)
175 D |= T.getDependence();
176
177 // C++29 [temp.names]p5:
178 // A pack-index-template-name is a pack expansion.
179 if (!(IndexD & TemplateNameDependence::UnexpandedPack))
180 D &= ~TemplateNameDependence::UnexpandedPack;
181
182 // C++29 [temp.names]p3:
183 // The simple-template-name P in a pack-index-template-name shall
184 // denote a pack.
185 if (!Pattern.containsUnexpandedParameterPack())
186 D |= TemplateNameDependence::Error |
187 TemplateNameDependence::DependentInstantiation;
188
189 return D;
190}
191
192void PackIndexingTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
193 const ASTContext &Context) const {
194 Profile(ID, Context, Pattern, IndexExpr: getIndexExpr(), FullySubstituted: isFullySubstituted(),
195 Expansions: getExpansions());
196}
197
198void PackIndexingTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
199 const ASTContext &Context,
200 TemplateName Pattern, Expr *IndexExpr,
201 bool FullySubstituted,
202 ArrayRef<TemplateName> Expansions) {
203 Pattern.Profile(ID);
204 IndexExpr->Profile(ID, Context, /*Canonical=*/true);
205 ID.AddBoolean(B: FullySubstituted);
206 ID.AddInteger(I: Expansions.size());
207 for (TemplateName T : Expansions)
208 T.Profile(ID);
209}
210
211IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
212 const IdentifierInfo *II)
213 : PtrOrOp(reinterpret_cast<uintptr_t>(II)) {
214 static_assert(NUM_OVERLOADED_OPERATORS <= 4096,
215 "NUM_OVERLOADED_OPERATORS is too large");
216 assert(II);
217 assert(getIdentifier() == II);
218}
219IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
220 OverloadedOperatorKind OOK)
221 : PtrOrOp(-uintptr_t(OOK)) {
222 assert(OOK != OO_None);
223 assert(getOperator() == OOK);
224}
225
226void IdentifierOrOverloadedOperator::Profile(llvm::FoldingSetNodeID &ID) const {
227 if (auto *Identifier = getIdentifier()) {
228 ID.AddBoolean(B: false);
229 ID.AddPointer(Ptr: Identifier);
230 } else {
231 ID.AddBoolean(B: true);
232 ID.AddInteger(I: getOperator());
233 }
234}
235
236TemplateName::TemplateName(void *Ptr) {
237 Storage = StorageType::getFromOpaqueValue(VP: Ptr);
238}
239
240TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
241TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
242 : Storage(Storage) {}
243TemplateName::TemplateName(AssumedTemplateStorage *Storage)
244 : Storage(Storage) {}
245TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
246 : Storage(Storage) {}
247TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
248 : Storage(Storage) {}
249TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
250TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
251TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
252TemplateName::TemplateName(DeducedTemplateStorage *Deduced)
253 : Storage(Deduced) {}
254TemplateName::TemplateName(PackIndexingTemplateStorage *PackIndexing)
255 : Storage(PackIndexing) {}
256
257bool TemplateName::isNull() const { return Storage.isNull(); }
258
259TemplateName::NameKind TemplateName::getKind() const {
260 if (auto *ND = dyn_cast<Decl *>(Val: Storage)) {
261 if (isa<UsingShadowDecl>(Val: ND))
262 return UsingTemplate;
263 assert(isa<TemplateDecl>(ND));
264 return Template;
265 }
266
267 if (isa<DependentTemplateName *>(Val: Storage))
268 return DependentTemplate;
269 if (isa<QualifiedTemplateName *>(Val: Storage))
270 return QualifiedTemplate;
271
272 UncommonTemplateNameStorage *uncommon =
273 cast<UncommonTemplateNameStorage *>(Val: Storage);
274 if (uncommon->getAsOverloadedStorage())
275 return OverloadedTemplate;
276 if (uncommon->getAsAssumedTemplateName())
277 return AssumedTemplate;
278 if (uncommon->getAsSubstTemplateTemplateParm())
279 return SubstTemplateTemplateParm;
280 if (uncommon->getAsDeducedTemplateName())
281 return DeducedTemplate;
282 if (uncommon->getAsPackIndexingTemplate())
283 return PackIndexingTemplate;
284
285 assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr);
286 return SubstTemplateTemplateParmPack;
287}
288
289TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const {
290 TemplateName Name = *this;
291 while (std::optional<TemplateName> UnderlyingOrNone =
292 Name.desugar(IgnoreDeduced))
293 Name = *UnderlyingOrNone;
294
295 if (!IgnoreDeduced)
296 assert(Name.getAsDeducedTemplateName() == nullptr &&
297 "Unexpected canonical DeducedTemplateName; Did you mean to use "
298 "getTemplateDeclAndDefaultArgs instead?");
299
300 return cast_if_present<TemplateDecl>(
301 Val: dyn_cast_if_present<Decl *>(Val&: Name.Storage));
302}
303
304TemplateTemplateParmDecl *TemplateName::getAsTemplateTemplateParmDecl() const {
305 if (TemplateDecl *TD = getAsTemplateDecl())
306 return dyn_cast<TemplateTemplateParmDecl>(Val: TD);
307 if (PackIndexingTemplateStorage *PI = getAsPackIndexingTemplate())
308 return PI->getParameterPack();
309 return nullptr;
310}
311
312std::pair<TemplateName, DefaultArguments>
313TemplateName::getTemplateDeclAndDefaultArgs() const {
314 DefaultArguments DefArgs;
315 for (TemplateName Name = *this; /**/; /**/) {
316 if (DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName()) {
317 assert(!DefArgs && "multiple default args?");
318 DefArgs = DTS->getDefaultArguments();
319 if (TemplateDecl *TD = DTS->getUnderlying().getAsTemplateDecl();
320 TD && DefArgs)
321 assert(DefArgs.StartPos + DefArgs.Args.size() <=
322 TD->getTemplateParameters()->size());
323 Name = DTS->getUnderlying();
324 }
325 if (std::optional<TemplateName> UnderlyingOrNone =
326 Name.desugar(/*IgnoreDeduced=*/false)) {
327 Name = *UnderlyingOrNone;
328 continue;
329 }
330 return {Name, DefArgs};
331 }
332}
333
334std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const {
335 if (Decl *D = dyn_cast_if_present<Decl *>(Val: Storage)) {
336 if (auto *USD = dyn_cast<UsingShadowDecl>(Val: D))
337 return TemplateName(USD->getTargetDecl());
338 return std::nullopt;
339 }
340 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
341 return QTN->getUnderlyingTemplate();
342 if (SubstTemplateTemplateParmStorage *S = getAsSubstTemplateTemplateParm())
343 return S->getReplacement();
344 if (PackIndexingTemplateStorage *S = getAsPackIndexingTemplate()) {
345 if (TemplateName Selected = S->getSelectedTemplate(); !Selected.isNull())
346 return Selected;
347 return std::nullopt;
348 }
349 if (IgnoreDeduced)
350 if (DeducedTemplateStorage *S = getAsDeducedTemplateName())
351 return S->getUnderlying();
352 return std::nullopt;
353}
354
355OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
356 if (UncommonTemplateNameStorage *Uncommon =
357 Storage.dyn_cast<UncommonTemplateNameStorage *>())
358 return Uncommon->getAsOverloadedStorage();
359
360 return nullptr;
361}
362
363AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
364 if (UncommonTemplateNameStorage *Uncommon =
365 Storage.dyn_cast<UncommonTemplateNameStorage *>())
366 return Uncommon->getAsAssumedTemplateName();
367
368 return nullptr;
369}
370
371SubstTemplateTemplateParmStorage *
372TemplateName::getAsSubstTemplateTemplateParm() const {
373 if (UncommonTemplateNameStorage *uncommon =
374 dyn_cast_if_present<UncommonTemplateNameStorage *>(Val: Storage))
375 return uncommon->getAsSubstTemplateTemplateParm();
376
377 return nullptr;
378}
379
380SubstTemplateTemplateParmPackStorage *
381TemplateName::getAsSubstTemplateTemplateParmPack() const {
382 if (UncommonTemplateNameStorage *Uncommon =
383 Storage.dyn_cast<UncommonTemplateNameStorage *>())
384 return Uncommon->getAsSubstTemplateTemplateParmPack();
385
386 return nullptr;
387}
388
389QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
390 return dyn_cast_if_present<QualifiedTemplateName *>(Val: Storage);
391}
392
393DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
394 return Storage.dyn_cast<DependentTemplateName *>();
395}
396
397std::tuple<NestedNameSpecifier, bool>
398TemplateName::getQualifierAndTemplateKeyword() const {
399 for (std::optional<TemplateName> Cur = *this; Cur;
400 Cur = Cur->desugar(/*IgnoreDeduced=*/true)) {
401 if (DependentTemplateName *N = Cur->getAsDependentTemplateName())
402 return {N->getQualifier(), N->hasTemplateKeyword()};
403 if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
404 return {N->getQualifier(), N->hasTemplateKeyword()};
405 if (Cur->getAsSubstTemplateTemplateParm() ||
406 Cur->getAsSubstTemplateTemplateParmPack() ||
407 Cur->getAsPackIndexingTemplate())
408 break;
409 }
410 return {std::nullopt, false};
411}
412
413UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
414 if (Decl *D = Storage.dyn_cast<Decl *>())
415 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(Val: D))
416 return USD;
417 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
418 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
419 return nullptr;
420}
421
422DependentTemplateStorage::DependentTemplateStorage(
423 NestedNameSpecifier Qualifier, IdentifierOrOverloadedOperator Name,
424 bool HasTemplateKeyword)
425 : Qualifier(Qualifier, HasTemplateKeyword), Name(Name) {
426 assert((!Qualifier || Qualifier.isDependent()) &&
427 "Qualifier must be dependent");
428}
429
430TemplateNameDependence DependentTemplateStorage::getDependence() const {
431 return toTemplateNameDependence(D: getQualifier().getDependence()) |
432 TemplateNameDependence::DependentInstantiation;
433}
434
435void DependentTemplateStorage::print(raw_ostream &OS,
436 const PrintingPolicy &Policy) const {
437 getQualifier().print(OS, Policy);
438
439 if (hasTemplateKeyword())
440 OS << "template ";
441
442 IdentifierOrOverloadedOperator Name = getName();
443 if (const IdentifierInfo *II = Name.getIdentifier())
444 OS << II->getName();
445 else
446 OS << "operator " << getOperatorSpelling(Operator: Name.getOperator());
447}
448
449DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const {
450 if (UncommonTemplateNameStorage *Uncommon =
451 dyn_cast_if_present<UncommonTemplateNameStorage *>(Val: Storage))
452 return Uncommon->getAsDeducedTemplateName();
453
454 return nullptr;
455}
456
457PackIndexingTemplateStorage *TemplateName::getAsPackIndexingTemplate() const {
458 if (UncommonTemplateNameStorage *Uncommon =
459 dyn_cast_if_present<UncommonTemplateNameStorage *>(Val: Storage))
460 return Uncommon->getAsPackIndexingTemplate();
461
462 return nullptr;
463}
464
465TemplateNameDependence TemplateName::getDependence() const {
466 switch (getKind()) {
467 case NameKind::Template:
468 case NameKind::UsingTemplate: {
469 TemplateDecl *Template = getAsTemplateDecl();
470 auto D = TemplateNameDependence::None;
471 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: Template)) {
472 D |= TemplateNameDependence::DependentInstantiation;
473 if (TTP->isParameterPack())
474 D |= TemplateNameDependence::UnexpandedPack;
475 }
476 // FIXME: Hack, getDeclContext() can be null if Template is still
477 // initializing due to PCH reading, so we check it before using it.
478 // Should probably modify TemplateSpecializationType to allow constructing
479 // it without the isDependent() checking.
480 if (Template->getDeclContext() &&
481 Template->getDeclContext()->isDependentContext())
482 D |= TemplateNameDependence::DependentInstantiation;
483 return D;
484 }
485 case NameKind::QualifiedTemplate: {
486 QualifiedTemplateName *S = getAsQualifiedTemplateName();
487 TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
488 D |= toTemplateNameDependence(D: S->getQualifier().getDependence());
489 return D;
490 }
491 case NameKind::DependentTemplate: {
492 DependentTemplateName *S = getAsDependentTemplateName();
493 return toTemplateNameDependence(D: S->getQualifier().getDependence()) |
494 TemplateNameDependence::DependentInstantiation;
495 }
496 case NameKind::SubstTemplateTemplateParm: {
497 auto *S = getAsSubstTemplateTemplateParm();
498 return S->getReplacement().getDependence();
499 }
500 case NameKind::SubstTemplateTemplateParmPack:
501 return TemplateNameDependence::UnexpandedPack |
502 TemplateNameDependence::DependentInstantiation;
503 case NameKind::DeducedTemplate: {
504 DeducedTemplateStorage *DTS = getAsDeducedTemplateName();
505 TemplateNameDependence D = DTS->getUnderlying().getDependence();
506 for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args)
507 D |= toTemplateNameDependence(D: Arg.getDependence());
508 return D;
509 }
510 case NameKind::PackIndexingTemplate:
511 return getAsPackIndexingTemplate()->getDependence();
512 case NameKind::AssumedTemplate:
513 return TemplateNameDependence::DependentInstantiation;
514 case NameKind::OverloadedTemplate:
515 llvm_unreachable("overloaded templates shouldn't survive to here.");
516 }
517 llvm_unreachable("Unknown TemplateName kind");
518}
519
520bool TemplateName::isDependent() const {
521 return getDependence() & TemplateNameDependence::Dependent;
522}
523
524bool TemplateName::isInstantiationDependent() const {
525 return getDependence() & TemplateNameDependence::Instantiation;
526}
527
528bool TemplateName::containsUnexpandedParameterPack() const {
529 return getDependence() & TemplateNameDependence::UnexpandedPack;
530}
531
532bool TemplateName::isConceptName() const {
533 auto namesConcept = [](const TemplateTemplateParmDecl *TTP) {
534 return TTP->templateParameterKind() == TNK_Concept_template;
535 };
536 switch (getKind()) {
537 case NameKind::Template:
538 case NameKind::UsingTemplate: {
539 const TemplateDecl *TD = getAsTemplateDecl();
540 if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: TD))
541 return namesConcept(TTP);
542 return isa<ConceptDecl>(Val: TD);
543 }
544 case NameKind::PackIndexingTemplate:
545 return getAsPackIndexingTemplate()->getPattern().isConceptName();
546 case NameKind::SubstTemplateTemplateParmPack:
547 return namesConcept(
548 getAsSubstTemplateTemplateParmPack()->getParameterPack());
549 case NameKind::QualifiedTemplate:
550 case NameKind::SubstTemplateTemplateParm:
551 case NameKind::DeducedTemplate:
552 return desugar(/*IgnoreDeduced=*/true)->isConceptName();
553 case NameKind::OverloadedTemplate:
554 case NameKind::AssumedTemplate:
555 case NameKind::DependentTemplate:
556 return false;
557 }
558 llvm_unreachable("Unknown TemplateName kind");
559}
560
561void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
562 Qualified Qual) const {
563 auto handleAnonymousTTP = [&](TemplateDecl *TD, raw_ostream &OS) {
564 if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: TD);
565 TTP && (Policy.PrintAsCanonical || TTP->getIdentifier() == nullptr)) {
566 OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
567 return true;
568 }
569 return false;
570 };
571 if (NameKind Kind = getKind();
572 Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
573 // After `namespace ns { using std::vector }`, what is the fully-qualified
574 // name of the UsingTemplateName `vector` within ns?
575 //
576 // - ns::vector (the qualified name of the using-shadow decl)
577 // - std::vector (the qualified name of the underlying template decl)
578 //
579 // Similar to the UsingType behavior, using declarations are used to import
580 // names more often than to export them, thus using the original name is
581 // most useful in this case.
582 TemplateDecl *Template = getAsTemplateDecl();
583 if (Policy.PrintAsCanonical)
584 Template = cast<TemplateDecl>(Val: Template->getCanonicalDecl());
585 if (handleAnonymousTTP(Template, OS))
586 return;
587 if (Qual == Qualified::None || isa<TemplateTemplateParmDecl>(Val: Template) ||
588 Policy.SuppressScope) {
589 if (IdentifierInfo *II = Template->getIdentifier();
590 Policy.CleanUglifiedParameters && II &&
591 isa<TemplateTemplateParmDecl>(Val: Template))
592 OS << II->deuglifiedName();
593 else
594 OS << *Template;
595 } else {
596 PrintingPolicy NestedNamePolicy = Policy;
597 NestedNamePolicy.SuppressUnwrittenScope = true;
598 Template->printQualifiedName(OS, Policy: NestedNamePolicy);
599 }
600 } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
601 if (Policy.PrintAsCanonical) {
602 QTN->getUnderlyingTemplate().print(OS, Policy, Qual);
603 return;
604 }
605 if (Qual != Qualified::None)
606 QTN->getQualifier().print(OS, Policy);
607 if (QTN->hasTemplateKeyword())
608 OS << "template ";
609
610 TemplateName Underlying = QTN->getUnderlyingTemplate();
611 assert(Underlying.getKind() == TemplateName::Template ||
612 Underlying.getKind() == TemplateName::UsingTemplate);
613
614 TemplateDecl *UTD = Underlying.getAsTemplateDecl();
615
616 if (handleAnonymousTTP(UTD, OS))
617 return;
618
619 OS << *UTD;
620 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
621 DTN->print(OS, Policy);
622 } else if (SubstTemplateTemplateParmStorage *subst =
623 getAsSubstTemplateTemplateParm()) {
624 subst->getReplacement().print(OS, Policy, Qual);
625 } else if (PackIndexingTemplateStorage *PI = getAsPackIndexingTemplate()) {
626 if (TemplateName Selected = PI->getSelectedTemplate();
627 !Selected.isNull() && Policy.PrintAsCanonical) {
628 Selected.print(OS, Policy, Qual);
629 return;
630 }
631 PI->getPattern().print(OS, Policy, Qual);
632 OS << "...[";
633 PI->getIndexExpr()->printPretty(OS, Helper: nullptr, Policy);
634 OS << "]";
635 } else if (SubstTemplateTemplateParmPackStorage *SubstPack =
636 getAsSubstTemplateTemplateParmPack())
637 OS << *SubstPack->getParameterPack();
638 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
639 Assumed->getDeclName().print(OS, Policy);
640 } else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) {
641 Deduced->getUnderlying().print(OS, Policy);
642 DefaultArguments DefArgs = Deduced->getDefaultArguments();
643 OS << ":" << DefArgs.StartPos;
644 printTemplateArgumentList(OS, Args: DefArgs.Args, Policy);
645 } else {
646 assert(getKind() == TemplateName::OverloadedTemplate);
647 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
648 (*OTS->begin())->printName(OS, Policy);
649 }
650}
651
652const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
653 TemplateName N) {
654 std::string NameStr;
655 llvm::raw_string_ostream OS(NameStr);
656 LangOptions LO;
657 LO.CPlusPlus = true;
658 LO.Bool = true;
659 OS << '\'';
660 N.print(OS, Policy: PrintingPolicy(LO));
661 OS << '\'';
662 return DB << NameStr;
663}
664