clang 19.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/Casting.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/raw_ostream.h"
31#include <cassert>
32#include <optional>
33#include <string>
34
35using namespace clang;
36
39 return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
40}
41
44 return cast<TemplateTemplateParmDecl>(
46 ->asArray()[Bits.Index]);
47}
48
51 return cast<TemplateTemplateParmDecl>(
53 ->asArray()[Bits.Index]);
54}
55
56void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
57 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
58}
59
61 llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
62 unsigned Index, std::optional<unsigned> PackIndex) {
63 Replacement.Profile(ID);
64 ID.AddPointer(AssociatedDecl);
65 ID.AddInteger(Index);
66 ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
67}
68
70 ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
71 bool Final)
72 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
73 ArgPack.size()),
74 Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
75 assert(AssociatedDecl != nullptr);
76}
77
78void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
79 ASTContext &Context) {
81 getFinal());
82}
83
85 return AssociatedDeclAndFinal.getPointer();
86}
87
89 return AssociatedDeclAndFinal.getInt();
90}
91
93 llvm::FoldingSetNodeID &ID, ASTContext &Context,
94 const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
95 bool Final) {
96 ArgPack.Profile(ID, Context);
97 ID.AddPointer(AssociatedDecl);
98 ID.AddInteger(Index);
99 ID.AddBoolean(Final);
100}
101
103 Storage = StorageType::getFromOpaqueValue(Ptr);
104}
105
106TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
108 : Storage(Storage) {}
110 : Storage(Storage) {}
112 : Storage(Storage) {}
114 : Storage(Storage) {}
118
119bool TemplateName::isNull() const { return Storage.isNull(); }
120
122 if (auto *ND = Storage.dyn_cast<Decl *>()) {
123 if (isa<UsingShadowDecl>(ND))
124 return UsingTemplate;
125 assert(isa<TemplateDecl>(ND));
126 return Template;
127 }
128
129 if (Storage.is<DependentTemplateName *>())
130 return DependentTemplate;
131 if (Storage.is<QualifiedTemplateName *>())
132 return QualifiedTemplate;
133
135 = Storage.get<UncommonTemplateNameStorage*>();
136 if (uncommon->getAsOverloadedStorage())
137 return OverloadedTemplate;
138 if (uncommon->getAsAssumedTemplateName())
139 return AssumedTemplate;
140 if (uncommon->getAsSubstTemplateTemplateParm())
143}
144
146 if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) {
147 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing))
148 return cast<TemplateDecl>(USD->getTargetDecl());
149
150 assert(isa<TemplateDecl>(TemplateOrUsing));
151 return cast<TemplateDecl>(TemplateOrUsing);
152 }
153
155 return QTN->getUnderlyingTemplate().getAsTemplateDecl();
156
158 return sub->getReplacement().getAsTemplateDecl();
159
161 return cast<TemplateDecl>(USD->getTargetDecl());
162
163 return nullptr;
164}
165
167 if (UncommonTemplateNameStorage *Uncommon =
168 Storage.dyn_cast<UncommonTemplateNameStorage *>())
169 return Uncommon->getAsOverloadedStorage();
170
171 return nullptr;
172}
173
175 if (UncommonTemplateNameStorage *Uncommon =
176 Storage.dyn_cast<UncommonTemplateNameStorage *>())
177 return Uncommon->getAsAssumedTemplateName();
178
179 return nullptr;
180}
181
184 if (UncommonTemplateNameStorage *uncommon =
185 Storage.dyn_cast<UncommonTemplateNameStorage *>())
186 return uncommon->getAsSubstTemplateTemplateParm();
187
188 return nullptr;
189}
190
193 if (UncommonTemplateNameStorage *Uncommon =
194 Storage.dyn_cast<UncommonTemplateNameStorage *>())
195 return Uncommon->getAsSubstTemplateTemplateParmPack();
196
197 return nullptr;
198}
199
201 return Storage.dyn_cast<QualifiedTemplateName *>();
202}
203
205 return Storage.dyn_cast<DependentTemplateName *>();
206}
207
209 if (Decl *D = Storage.dyn_cast<Decl *>())
210 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
211 return USD;
213 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
214 return nullptr;
215}
216
219
220 // Substituting a dependent template name: preserve it as written.
221 if (!Decl)
222 return *this;
223
224 // If we have a template declaration, use the most recent non-friend
225 // declaration of that template.
226 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
227 while (Decl->getFriendObjectKind()) {
228 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
229 assert(Decl && "all declarations of template are friends");
230 }
231 return TemplateName(Decl);
232}
233
234TemplateNameDependence TemplateName::getDependence() const {
235 auto D = TemplateNameDependence::None;
236 switch (getKind()) {
239 getAsQualifiedTemplateName()->getQualifier()->getDependence());
240 break;
243 getAsDependentTemplateName()->getQualifier()->getDependence());
244 break;
246 D |= TemplateNameDependence::UnexpandedPack;
247 break;
249 llvm_unreachable("overloaded templates shouldn't survive to here.");
250 default:
251 break;
252 }
254 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
255 D |= TemplateNameDependence::DependentInstantiation;
256 if (TTP->isParameterPack())
257 D |= TemplateNameDependence::UnexpandedPack;
258 }
259 // FIXME: Hack, getDeclContext() can be null if Template is still
260 // initializing due to PCH reading, so we check it before using it.
261 // Should probably modify TemplateSpecializationType to allow constructing
262 // it without the isDependent() checking.
263 if (Template->getDeclContext() &&
264 Template->getDeclContext()->isDependentContext())
265 D |= TemplateNameDependence::DependentInstantiation;
266 } else {
267 D |= TemplateNameDependence::DependentInstantiation;
268 }
269 return D;
270}
271
273 return getDependence() & TemplateNameDependence::Dependent;
274}
275
277 return getDependence() & TemplateNameDependence::Instantiation;
278}
279
281 return getDependence() & TemplateNameDependence::UnexpandedPack;
282}
283
284void TemplateName::Profile(llvm::FoldingSetNodeID &ID) {
285 if (const auto* USD = getAsUsingShadowDecl())
286 ID.AddPointer(USD->getCanonicalDecl());
287 else if (const auto *TD = getAsTemplateDecl())
288 ID.AddPointer(TD->getCanonicalDecl());
289 else
290 ID.AddPointer(Storage.getOpaqueValue());
291}
292
293void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
294 Qualified Qual) const {
295 auto Kind = getKind();
296 TemplateDecl *Template = nullptr;
298 // After `namespace ns { using std::vector }`, what is the fully-qualified
299 // name of the UsingTemplateName `vector` within ns?
300 //
301 // - ns::vector (the qualified name of the using-shadow decl)
302 // - std::vector (the qualified name of the underlying template decl)
303 //
304 // Similar to the UsingType behavior, using declarations are used to import
305 // names more often than to export them, thus using the original name is
306 // most useful in this case.
308 }
309
310 if (Template)
311 if (Policy.CleanUglifiedParameters &&
312 isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
313 OS << Template->getIdentifier()->deuglifiedName();
314 else if (Qual == Qualified::Fully &&
315 getDependence() !=
316 TemplateNameDependenceScope::DependentInstantiation)
317 Template->printQualifiedName(OS, Policy);
318 else
319 OS << *Template;
321 if (Qual == Qualified::Fully &&
322 getDependence() !=
323 TemplateNameDependenceScope::DependentInstantiation) {
324 QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
325 OS, Policy);
326 return;
327 }
328 if (Qual == Qualified::AsWritten)
329 QTN->getQualifier()->print(OS, Policy);
330 if (QTN->hasTemplateKeyword())
331 OS << "template ";
332 OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
334 if (Qual == Qualified::AsWritten && DTN->getQualifier())
335 DTN->getQualifier()->print(OS, Policy);
336 OS << "template ";
337
338 if (DTN->isIdentifier())
339 OS << DTN->getIdentifier()->getName();
340 else
341 OS << "operator " << getOperatorSpelling(DTN->getOperator());
342 } else if (SubstTemplateTemplateParmStorage *subst
344 subst->getReplacement().print(OS, Policy, Qual);
345 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
347 OS << *SubstPack->getParameterPack();
348 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
349 Assumed->getDeclName().print(OS, Policy);
350 } else {
353 (*OTS->begin())->printName(OS, Policy);
354 }
355}
356
358 TemplateName N) {
359 std::string NameStr;
360 llvm::raw_string_ostream OS(NameStr);
361 LangOptions LO;
362 LO.CPlusPlus = true;
363 LO.Bool = true;
364 OS << '\'';
365 N.print(OS, PrintingPolicy(LO));
366 OS << '\'';
367 OS.flush();
368 return DB << NameStr;
369}
370
371void TemplateName::dump(raw_ostream &OS) const {
372 LangOptions LO; // FIXME!
373 LO.CPlusPlus = true;
374 LO.Bool = true;
375 print(OS, PrintingPolicy(LO));
376}
377
378LLVM_DUMP_METHOD void TemplateName::dump() const {
379 dump(llvm::errs());
380}
Defines the Diagnostic-related interfaces.
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:182
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:85
Decl * getPreviousDecl()
Retrieve the previous declaration that declares the same entity as this declaration,...
Definition: DeclBase.h:1061
Decl * getMostRecentDecl()
Retrieve the most recent declaration that declares the same entity as this declaration (which may be ...
Definition: DeclBase.h:1076
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
Definition: DeclBase.h:1226
Represents a dependent template name that cannot be resolved prior to template instantiation.
Definition: TemplateName.h:488
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:418
A structure for storing the information associated with an overloaded template name.
Definition: TemplateName.h:108
Represents a template name that was expressed as a qualified name.
Definition: TemplateName.h:431
The streaming interface shared between DiagnosticBuilder and PartialDiagnostic.
Definition: Diagnostic.h:1115
A structure for storing an already-substituted template template parameter pack.
Definition: TemplateName.h:141
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:156
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:373
std::optional< unsigned > getPackIndex() const
Definition: TemplateName.h:397
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:395
Decl * getAssociatedDecl() const
A template-like entity which owns the whole pattern being substituted.
Definition: TemplateName.h:391
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:394
Represents a C++ template name within the type system.
Definition: TemplateName.h:202
TemplateNameDependence getDependence() const
bool isNull() const
Determine whether this template name is NULL.
TemplateName()=default
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known.
DependentTemplateName * getAsDependentTemplateName() const
Retrieve the underlying dependent template name structure, if any.
QualifiedTemplateName * getAsQualifiedTemplateName() const
Retrieve the underlying qualified template name structure, if any.
void dump() const
Debugging aid that dumps the template name to standard error.
void Profile(llvm::FoldingSetNodeID &ID)
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:247
@ OverloadedTemplate
A set of overloaded template declarations.
Definition: TemplateName.h:222
@ Template
A single template declaration.
Definition: TemplateName.h:219
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
Definition: TemplateName.h:234
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
Definition: TemplateName.h:238
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
Definition: TemplateName.h:243
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
Definition: TemplateName.h:230
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
Definition: TemplateName.h:226
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.
bool isDependent() const
Determines whether this is a dependent template name.
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.
TemplateName getNameToSubstitute() const
Get the template name to substitute when this template name is used as a template template argument.
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:48
SubstTemplateTemplateParmPackStorage * getAsSubstTemplateTemplateParmPack()
Definition: TemplateName.h:99
SubstTemplateTemplateParmStorage * getAsSubstTemplateTemplateParm()
Definition: TemplateName.h:93
AssumedTemplateStorage * getAsAssumedTemplateName()
Definition: TemplateName.h:87
OverloadedTemplateStorage * getAsOverloadedStorage()
Definition: TemplateName.h:81
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Definition: DeclCXX.h:3313
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.
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
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:66