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