clang 20.0.0git
TemplateName.cpp
Go to the documentation of this file.
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
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclBase.h"
16#include "clang/AST/DeclCXX.h"
23#include "clang/Basic/LLVM.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(DefArgs.Args, reinterpret_cast<TemplateArgument *>(this + 1));
42}
43
44void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
45 const ASTContext &Context) const {
46 Profile(ID, Context, Underlying, 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(DefArgs.StartPos);
55 ID.AddInteger(DefArgs.Args.size());
56 for (const TemplateArgument &Arg : DefArgs.Args)
57 Arg.Profile(ID, Context);
58}
59
62 return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
63}
64
67 return cast<TemplateTemplateParmDecl>(
69 ->asArray()[Bits.Index]);
70}
71
74 return cast<TemplateTemplateParmDecl>(
76 ->asArray()[Bits.Index]);
77}
78
79void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
80 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
81}
82
84 llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
85 unsigned Index, std::optional<unsigned> PackIndex) {
86 Replacement.Profile(ID);
87 ID.AddPointer(AssociatedDecl);
88 ID.AddInteger(Index);
89 ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
90}
91
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) {
104 getFinal());
105}
106
108 return AssociatedDeclAndFinal.getPointer();
109}
110
112 return AssociatedDeclAndFinal.getInt();
113}
114
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(AssociatedDecl);
121 ID.AddInteger(Index);
122 ID.AddBoolean(Final);
123}
124
126 Storage = StorageType::getFromOpaqueValue(Ptr);
127}
128
129TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
131 : Storage(Storage) {}
133 : Storage(Storage) {}
135 : Storage(Storage) {}
137 : Storage(Storage) {}
142 : Storage(Deduced) {}
143
144bool TemplateName::isNull() const { return Storage.isNull(); }
145
147 if (auto *ND = Storage.dyn_cast<Decl *>()) {
148 if (isa<UsingShadowDecl>(ND))
149 return UsingTemplate;
150 assert(isa<TemplateDecl>(ND));
151 return Template;
152 }
153
154 if (isa<DependentTemplateName *>(Storage))
155 return DependentTemplate;
156 if (isa<QualifiedTemplateName *>(Storage))
157 return QualifiedTemplate;
158
160 cast<UncommonTemplateNameStorage *>(Storage);
161 if (uncommon->getAsOverloadedStorage())
162 return OverloadedTemplate;
163 if (uncommon->getAsAssumedTemplateName())
164 return AssumedTemplate;
165 if (uncommon->getAsSubstTemplateTemplateParm())
167 if (uncommon->getAsDeducedTemplateName())
168 return DeducedTemplate;
169
170 assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr);
172}
173
175 TemplateName Name = *this;
176 while (std::optional<TemplateName> UnderlyingOrNone =
177 Name.desugar(IgnoreDeduced))
178 Name = *UnderlyingOrNone;
179
180 if (!IgnoreDeduced)
181 assert(Name.getAsDeducedTemplateName() == nullptr &&
182 "Unexpected canonical DeducedTemplateName; Did you mean to use "
183 "getTemplateDeclAndDefaultArgs instead?");
184
185 return cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>());
186}
187
188std::pair<TemplateDecl *, DefaultArguments>
190 for (TemplateName Name = *this; /**/; /**/) {
191 if (Name.getKind() == TemplateName::DeducedTemplate) {
192 DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName();
193 TemplateDecl *TD =
194 DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true);
195 DefaultArguments DefArgs = DTS->getDefaultArguments();
196 if (TD && DefArgs)
197 assert(DefArgs.StartPos + DefArgs.Args.size() <=
198 TD->getTemplateParameters()->size());
199 return {TD, DTS->getDefaultArguments()};
200 }
201 if (std::optional<TemplateName> UnderlyingOrNone =
202 Name.desugar(/*IgnoreDeduced=*/false)) {
203 Name = *UnderlyingOrNone;
204 continue;
205 }
206 return {cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()), {}};
207 }
208}
209
210std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const {
211 if (Decl *D = Storage.dyn_cast<Decl *>()) {
212 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
213 return TemplateName(USD->getTargetDecl());
214 return std::nullopt;
215 }
217 return QTN->getUnderlyingTemplate();
219 return S->getReplacement();
220 if (IgnoreDeduced)
222 return S->getUnderlying();
223 return std::nullopt;
224}
225
227 if (UncommonTemplateNameStorage *Uncommon =
228 Storage.dyn_cast<UncommonTemplateNameStorage *>())
229 return Uncommon->getAsOverloadedStorage();
230
231 return nullptr;
232}
233
235 if (UncommonTemplateNameStorage *Uncommon =
236 Storage.dyn_cast<UncommonTemplateNameStorage *>())
237 return Uncommon->getAsAssumedTemplateName();
238
239 return nullptr;
240}
241
244 if (UncommonTemplateNameStorage *uncommon =
245 Storage.dyn_cast<UncommonTemplateNameStorage *>())
246 return uncommon->getAsSubstTemplateTemplateParm();
247
248 return nullptr;
249}
250
253 if (UncommonTemplateNameStorage *Uncommon =
254 Storage.dyn_cast<UncommonTemplateNameStorage *>())
255 return Uncommon->getAsSubstTemplateTemplateParmPack();
256
257 return nullptr;
258}
259
261 return Storage.dyn_cast<QualifiedTemplateName *>();
262}
263
265 return Storage.dyn_cast<DependentTemplateName *>();
266}
267
269 if (Decl *D = Storage.dyn_cast<Decl *>())
270 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
271 return USD;
273 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
274 return nullptr;
275}
276
278 if (UncommonTemplateNameStorage *Uncommon =
279 Storage.dyn_cast<UncommonTemplateNameStorage *>())
280 return Uncommon->getAsDeducedTemplateName();
281
282 return nullptr;
283}
284
285TemplateNameDependence TemplateName::getDependence() const {
286 switch (getKind()) {
290 auto D = TemplateNameDependence::None;
291 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
292 D |= TemplateNameDependence::DependentInstantiation;
293 if (TTP->isParameterPack())
294 D |= TemplateNameDependence::UnexpandedPack;
295 }
296 // FIXME: Hack, getDeclContext() can be null if Template is still
297 // initializing due to PCH reading, so we check it before using it.
298 // Should probably modify TemplateSpecializationType to allow constructing
299 // it without the isDependent() checking.
300 if (Template->getDeclContext() &&
301 Template->getDeclContext()->isDependentContext())
302 D |= TemplateNameDependence::DependentInstantiation;
303 return D;
304 }
307 TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
308 if (NestedNameSpecifier *NNS = S->getQualifier())
309 D |= toTemplateNameDependence(NNS->getDependence());
310 return D;
311 }
314 auto D = TemplateNameDependence::DependentInstantiation;
315 D |= toTemplateNameDependence(S->getQualifier()->getDependence());
316 return D;
317 }
320 return S->getReplacement().getDependence();
321 }
323 return TemplateNameDependence::UnexpandedPack |
324 TemplateNameDependence::DependentInstantiation;
327 TemplateNameDependence D = DTS->getUnderlying().getDependence();
328 for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args)
329 D |= toTemplateNameDependence(Arg.getDependence());
330 return D;
331 }
333 return TemplateNameDependence::DependentInstantiation;
335 llvm_unreachable("overloaded templates shouldn't survive to here.");
336 }
337 llvm_unreachable("Unknown TemplateName kind");
338}
339
341 return getDependence() & TemplateNameDependence::Dependent;
342}
343
345 return getDependence() & TemplateNameDependence::Instantiation;
346}
347
349 return getDependence() & TemplateNameDependence::UnexpandedPack;
350}
351
352void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
353 Qualified Qual) const {
354 auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
355 if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
356 TTP && TTP->getIdentifier() == nullptr) {
357 OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
358 return true;
359 }
360 return false;
361 };
362 if (NameKind Kind = getKind();
364 // After `namespace ns { using std::vector }`, what is the fully-qualified
365 // name of the UsingTemplateName `vector` within ns?
366 //
367 // - ns::vector (the qualified name of the using-shadow decl)
368 // - std::vector (the qualified name of the underlying template decl)
369 //
370 // Similar to the UsingType behavior, using declarations are used to import
371 // names more often than to export them, thus using the original name is
372 // most useful in this case.
374 if (handleAnonymousTTP(Template, OS))
375 return;
376 if (Qual == Qualified::None)
377 OS << *Template;
378 else
379 Template->printQualifiedName(OS, Policy);
381 if (NestedNameSpecifier *NNS = QTN->getQualifier();
382 Qual != Qualified::None && NNS)
383 NNS->print(OS, Policy);
384 if (QTN->hasTemplateKeyword())
385 OS << "template ";
386
387 TemplateName Underlying = QTN->getUnderlyingTemplate();
388 assert(Underlying.getKind() == TemplateName::Template ||
389 Underlying.getKind() == TemplateName::UsingTemplate);
390
391 TemplateDecl *UTD = Underlying.getAsTemplateDecl();
392
393 if (handleAnonymousTTP(UTD, OS))
394 return;
395
396 if (IdentifierInfo *II = UTD->getIdentifier();
397 Policy.CleanUglifiedParameters && II &&
398 isa<TemplateTemplateParmDecl>(UTD))
399 OS << II->deuglifiedName();
400 else
401 OS << *UTD;
403 if (NestedNameSpecifier *NNS = DTN->getQualifier())
404 NNS->print(OS, Policy);
405 OS << "template ";
406
407 if (DTN->isIdentifier())
408 OS << DTN->getIdentifier()->getName();
409 else
410 OS << "operator " << getOperatorSpelling(DTN->getOperator());
411 } else if (SubstTemplateTemplateParmStorage *subst =
413 subst->getReplacement().print(OS, Policy, Qual);
414 } else if (SubstTemplateTemplateParmPackStorage *SubstPack =
416 OS << *SubstPack->getParameterPack();
417 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
418 Assumed->getDeclName().print(OS, Policy);
419 } else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) {
420 Deduced->getUnderlying().print(OS, Policy);
421 DefaultArguments DefArgs = Deduced->getDefaultArguments();
422 OS << ":" << DefArgs.StartPos;
423 printTemplateArgumentList(OS, DefArgs.Args, Policy);
424 } else {
427 (*OTS->begin())->printName(OS, Policy);
428 }
429}
430
432 TemplateName N) {
433 std::string NameStr;
434 llvm::raw_string_ostream OS(NameStr);
435 LangOptions LO;
436 LO.CPlusPlus = true;
437 LO.Bool = true;
438 OS << '\'';
439 N.print(OS, PrintingPolicy(LO));
440 OS << '\'';
441 return DB << NameStr;
442}
Defines the Diagnostic-related interfaces.
const Decl * D
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
Defines an enumeration for C++ overloaded operators.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
A structure for storing the information associated with a name that has been assumed to be a template...
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
TemplateName getUnderlying() const
Definition: TemplateName.h:458
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
DefaultArguments getDefaultArguments() const
Definition: TemplateName.h:460
Represents a dependent template name that cannot be resolved prior to template instantiation.
Definition: TemplateName.h:548
One of these records is kept for each identifier that is lexed.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:499
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:274
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
A structure for storing the information associated with an overloaded template name.
Definition: TemplateName.h:116
Represents a template name as written in source code.
Definition: TemplateName.h:491
The streaming interface shared between DiagnosticBuilder and PartialDiagnostic.
Definition: Diagnostic.h:1102
A structure for storing an already-substituted template template parameter pack.
Definition: TemplateName.h:149
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context)
TemplateTemplateParmDecl * getParameterPack() const
Retrieve the template template parameter pack being substituted.
TemplateArgument getArgumentPack() const
Retrieve the template template argument pack with which this parameter was substituted.
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Definition: TemplateName.h:164
SubstTemplateTemplateParmPackStorage(ArrayRef< TemplateArgument > ArgPack, Decl *AssociatedDecl, unsigned Index, bool Final)
A structure for storing the information associated with a substituted template template parameter.
Definition: TemplateName.h:408
std::optional< unsigned > getPackIndex() const
Definition: TemplateName.h:432
void Profile(llvm::FoldingSetNodeID &ID)
TemplateTemplateParmDecl * getParameter() const
unsigned getIndex() const
Returns the index of the replaced parameter in the associated declaration.
Definition: TemplateName.h:430
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
Definition: TemplateName.h:426
Represents a template argument.
Definition: TemplateBase.h:61
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:399
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:418
Represents a C++ template name within the type system.
Definition: TemplateName.h:220
TemplateNameDependence getDependence() const
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
DeducedTemplateStorage * getAsDeducedTemplateName() const
Retrieve the deduced template info, if any.
bool isNull() const
Determine whether this template name is NULL.
TemplateName()=default
DependentTemplateName * getAsDependentTemplateName() const
Retrieve the underlying dependent template name structure, if any.
QualifiedTemplateName * getAsQualifiedTemplateName() const
Retrieve the underlying qualified template name structure, if any.
std::optional< TemplateName > desugar(bool IgnoreDeduced) const
void print(raw_ostream &OS, const PrintingPolicy &Policy, Qualified Qual=Qualified::AsWritten) const
Print the template name.
OverloadedTemplateStorage * getAsOverloadedTemplate() const
Retrieve the underlying, overloaded function template declarations that this template name refers to,...
bool containsUnexpandedParameterPack() const
Determines whether this template name contains an unexpanded parameter pack (for C++0x variadic templ...
AssumedTemplateStorage * getAsAssumedTemplateName() const
Retrieve information on a name that has been assumed to be a template-name in order to permit a call ...
NameKind getKind() const
@ UsingTemplate
A template name that refers to a template declaration found through a specific using shadow declarati...
Definition: TemplateName.h:265
@ OverloadedTemplate
A set of overloaded template declarations.
Definition: TemplateName.h:240
@ Template
A single template declaration.
Definition: TemplateName.h:237
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
Definition: TemplateName.h:252
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
Definition: TemplateName.h:256
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
Definition: TemplateName.h:261
@ DeducedTemplate
A template name that refers to another TemplateName with deduced default arguments.
Definition: TemplateName.h:269
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
Definition: TemplateName.h:248
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
Definition: TemplateName.h:244
UsingShadowDecl * getAsUsingShadowDecl() const
Retrieve the using shadow declaration through which the underlying template declaration is introduced...
SubstTemplateTemplateParmPackStorage * getAsSubstTemplateTemplateParmPack() const
Retrieve the substituted template template parameter pack, if known.
void Profile(llvm::FoldingSetNodeID &ID)
Definition: TemplateName.h:383
bool isDependent() const
Determines whether this is a dependent template name.
std::pair< TemplateDecl *, DefaultArguments > getTemplateDeclAndDefaultArgs() const
Retrieves the underlying template declaration that this template name refers to, along with the deduc...
SubstTemplateTemplateParmStorage * getAsSubstTemplateTemplateParm() const
Retrieve the substituted template template parameter, if known.
bool isInstantiationDependent() const
Determines whether this is a template name that somehow depends on a template parameter.
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
Implementation class used to describe either a set of overloaded template names or an already-substit...
Definition: TemplateName.h:49
SubstTemplateTemplateParmPackStorage * getAsSubstTemplateTemplateParmPack()
Definition: TemplateName.h:107
SubstTemplateTemplateParmStorage * getAsSubstTemplateTemplateParm()
Definition: TemplateName.h:101
AssumedTemplateStorage * getAsAssumedTemplateName()
Definition: TemplateName.h:89
DeducedTemplateStorage * getAsDeducedTemplateName()
Definition: TemplateName.h:95
OverloadedTemplateStorage * getAsOverloadedStorage()
Definition: TemplateName.h:83
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Definition: DeclCXX.h:3338
The JSON file list parser is used to communicate input to InstallAPI.
TemplateNameDependence toTemplateNameDependence(NestedNameSpecifierDependence D)
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
TemplateParameterList * getReplacedTemplateParameterList(Decl *D)
Internal helper used by Subst* nodes to retrieve the parameter list for their AssociatedDecl.
void printTemplateArgumentList(raw_ostream &OS, ArrayRef< TemplateArgument > Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL=nullptr)
Print a template argument list, including the '<' and '>' enclosing the template arguments.
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
ArrayRef< TemplateArgument > Args
Definition: TemplateName.h:187
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
unsigned CleanUglifiedParameters
Whether to strip underscores when printing reserved parameter names.
unsigned Data
The pack index, or the number of stored templates or template arguments, depending on which subclass ...
Definition: TemplateName.h:68