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>(
186 dyn_cast_if_present<Decl *>(Name.Storage));
187}
188
189std::pair<TemplateDecl *, DefaultArguments>
191 for (TemplateName Name = *this; /**/; /**/) {
192 if (Name.getKind() == TemplateName::DeducedTemplate) {
193 DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName();
194 TemplateDecl *TD =
195 DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true);
196 DefaultArguments DefArgs = DTS->getDefaultArguments();
197 if (TD && DefArgs)
198 assert(DefArgs.StartPos + DefArgs.Args.size() <=
199 TD->getTemplateParameters()->size());
200 return {TD, DTS->getDefaultArguments()};
201 }
202 if (std::optional<TemplateName> UnderlyingOrNone =
203 Name.desugar(/*IgnoreDeduced=*/false)) {
204 Name = *UnderlyingOrNone;
205 continue;
206 }
207 return {cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()), {}};
208 }
209}
210
211std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const {
212 if (Decl *D = dyn_cast_if_present<Decl *>(Storage)) {
213 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
214 return TemplateName(USD->getTargetDecl());
215 return std::nullopt;
216 }
218 return QTN->getUnderlyingTemplate();
220 return S->getReplacement();
221 if (IgnoreDeduced)
223 return S->getUnderlying();
224 return std::nullopt;
225}
226
228 if (UncommonTemplateNameStorage *Uncommon =
229 Storage.dyn_cast<UncommonTemplateNameStorage *>())
230 return Uncommon->getAsOverloadedStorage();
231
232 return nullptr;
233}
234
236 if (UncommonTemplateNameStorage *Uncommon =
237 Storage.dyn_cast<UncommonTemplateNameStorage *>())
238 return Uncommon->getAsAssumedTemplateName();
239
240 return nullptr;
241}
242
245 if (UncommonTemplateNameStorage *uncommon =
246 dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
247 return uncommon->getAsSubstTemplateTemplateParm();
248
249 return nullptr;
250}
251
254 if (UncommonTemplateNameStorage *Uncommon =
255 Storage.dyn_cast<UncommonTemplateNameStorage *>())
256 return Uncommon->getAsSubstTemplateTemplateParmPack();
257
258 return nullptr;
259}
260
262 return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
263}
264
266 return Storage.dyn_cast<DependentTemplateName *>();
267}
268
270 if (Decl *D = Storage.dyn_cast<Decl *>())
271 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
272 return USD;
274 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
275 return nullptr;
276}
277
279 if (UncommonTemplateNameStorage *Uncommon =
280 dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
281 return Uncommon->getAsDeducedTemplateName();
282
283 return nullptr;
284}
285
286TemplateNameDependence TemplateName::getDependence() const {
287 switch (getKind()) {
291 auto D = TemplateNameDependence::None;
292 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
293 D |= TemplateNameDependence::DependentInstantiation;
294 if (TTP->isParameterPack())
295 D |= TemplateNameDependence::UnexpandedPack;
296 }
297 // FIXME: Hack, getDeclContext() can be null if Template is still
298 // initializing due to PCH reading, so we check it before using it.
299 // Should probably modify TemplateSpecializationType to allow constructing
300 // it without the isDependent() checking.
301 if (Template->getDeclContext() &&
302 Template->getDeclContext()->isDependentContext())
303 D |= TemplateNameDependence::DependentInstantiation;
304 return D;
305 }
308 TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
309 if (NestedNameSpecifier *NNS = S->getQualifier())
310 D |= toTemplateNameDependence(NNS->getDependence());
311 return D;
312 }
315 auto D = TemplateNameDependence::DependentInstantiation;
316 D |= toTemplateNameDependence(S->getQualifier()->getDependence());
317 return D;
318 }
321 return S->getReplacement().getDependence();
322 }
324 return TemplateNameDependence::UnexpandedPack |
325 TemplateNameDependence::DependentInstantiation;
328 TemplateNameDependence D = DTS->getUnderlying().getDependence();
329 for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args)
330 D |= toTemplateNameDependence(Arg.getDependence());
331 return D;
332 }
334 return TemplateNameDependence::DependentInstantiation;
336 llvm_unreachable("overloaded templates shouldn't survive to here.");
337 }
338 llvm_unreachable("Unknown TemplateName kind");
339}
340
342 return getDependence() & TemplateNameDependence::Dependent;
343}
344
346 return getDependence() & TemplateNameDependence::Instantiation;
347}
348
350 return getDependence() & TemplateNameDependence::UnexpandedPack;
351}
352
353void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
354 Qualified Qual) const {
355 auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
356 if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
357 TTP && TTP->getIdentifier() == nullptr) {
358 OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
359 return true;
360 }
361 return false;
362 };
363 if (NameKind Kind = getKind();
365 // After `namespace ns { using std::vector }`, what is the fully-qualified
366 // name of the UsingTemplateName `vector` within ns?
367 //
368 // - ns::vector (the qualified name of the using-shadow decl)
369 // - std::vector (the qualified name of the underlying template decl)
370 //
371 // Similar to the UsingType behavior, using declarations are used to import
372 // names more often than to export them, thus using the original name is
373 // most useful in this case.
375 if (handleAnonymousTTP(Template, OS))
376 return;
377 if (Qual == Qualified::None)
378 OS << *Template;
379 else
380 Template->printQualifiedName(OS, Policy);
382 if (NestedNameSpecifier *NNS = QTN->getQualifier();
383 Qual != Qualified::None && NNS)
384 NNS->print(OS, Policy);
385 if (QTN->hasTemplateKeyword())
386 OS << "template ";
387
388 TemplateName Underlying = QTN->getUnderlyingTemplate();
389 assert(Underlying.getKind() == TemplateName::Template ||
390 Underlying.getKind() == TemplateName::UsingTemplate);
391
392 TemplateDecl *UTD = Underlying.getAsTemplateDecl();
393
394 if (handleAnonymousTTP(UTD, OS))
395 return;
396
397 if (IdentifierInfo *II = UTD->getIdentifier();
398 Policy.CleanUglifiedParameters && II &&
399 isa<TemplateTemplateParmDecl>(UTD))
400 OS << II->deuglifiedName();
401 else
402 OS << *UTD;
404 if (NestedNameSpecifier *NNS = DTN->getQualifier())
405 NNS->print(OS, Policy);
406 OS << "template ";
407
408 if (DTN->isIdentifier())
409 OS << DTN->getIdentifier()->getName();
410 else
411 OS << "operator " << getOperatorSpelling(DTN->getOperator());
412 } else if (SubstTemplateTemplateParmStorage *subst =
414 subst->getReplacement().print(OS, Policy, Qual);
415 } else if (SubstTemplateTemplateParmPackStorage *SubstPack =
417 OS << *SubstPack->getParameterPack();
418 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
419 Assumed->getDeclName().print(OS, Policy);
420 } else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) {
421 Deduced->getUnderlying().print(OS, Policy);
422 DefaultArguments DefArgs = Deduced->getDefaultArguments();
423 OS << ":" << DefArgs.StartPos;
424 printTemplateArgumentList(OS, DefArgs.Args, Policy);
425 } else {
428 (*OTS->begin())->printName(OS, Policy);
429 }
430}
431
433 TemplateName N) {
434 std::string NameStr;
435 llvm::raw_string_ostream OS(NameStr);
436 LangOptions LO;
437 LO.CPlusPlus = true;
438 LO.Bool = true;
439 OS << '\'';
440 N.print(OS, PrintingPolicy(LO));
441 OS << '\'';
442 return DB << NameStr;
443}
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:500
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:398
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:417
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:3382
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