1 //===- TemplateName.cpp - C++ Template Name Representation ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the TemplateName interface and subclasses.
11 //===----------------------------------------------------------------------===//
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/Casting.h"
29 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/raw_ostream.h"
35 using namespace clang
;
38 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
39 return TemplateArgument(llvm::ArrayRef(Arguments
, Bits
.Data
));
42 TemplateTemplateParmDecl
*
43 SubstTemplateTemplateParmPackStorage::getParameterPack() const {
44 return cast
<TemplateTemplateParmDecl
>(
45 getReplacedTemplateParameterList(getAssociatedDecl())
46 ->asArray()[Bits
.Index
]);
49 TemplateTemplateParmDecl
*
50 SubstTemplateTemplateParmStorage::getParameter() const {
51 return cast
<TemplateTemplateParmDecl
>(
52 getReplacedTemplateParameterList(getAssociatedDecl())
53 ->asArray()[Bits
.Index
]);
56 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID
&ID
) {
57 Profile(ID
, Replacement
, getAssociatedDecl(), getIndex(), getPackIndex());
60 void SubstTemplateTemplateParmStorage::Profile(
61 llvm::FoldingSetNodeID
&ID
, TemplateName Replacement
, Decl
*AssociatedDecl
,
62 unsigned Index
, std::optional
<unsigned> PackIndex
) {
63 Replacement
.Profile(ID
);
64 ID
.AddPointer(AssociatedDecl
);
66 ID
.AddInteger(PackIndex
? *PackIndex
+ 1 : 0);
69 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
70 ArrayRef
<TemplateArgument
> ArgPack
, Decl
*AssociatedDecl
, unsigned Index
,
72 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack
, Index
,
74 Arguments(ArgPack
.data()), AssociatedDeclAndFinal(AssociatedDecl
, Final
) {
75 assert(AssociatedDecl
!= nullptr);
78 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID
&ID
,
79 ASTContext
&Context
) {
80 Profile(ID
, Context
, getArgumentPack(), getAssociatedDecl(), getIndex(),
84 Decl
*SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
85 return AssociatedDeclAndFinal
.getPointer();
88 bool SubstTemplateTemplateParmPackStorage::getFinal() const {
89 return AssociatedDeclAndFinal
.getInt();
92 void SubstTemplateTemplateParmPackStorage::Profile(
93 llvm::FoldingSetNodeID
&ID
, ASTContext
&Context
,
94 const TemplateArgument
&ArgPack
, Decl
*AssociatedDecl
, unsigned Index
,
96 ArgPack
.Profile(ID
, Context
);
97 ID
.AddPointer(AssociatedDecl
);
102 TemplateName::TemplateName(void *Ptr
) {
103 Storage
= StorageType::getFromOpaqueValue(Ptr
);
106 TemplateName::TemplateName(TemplateDecl
*Template
) : Storage(Template
) {}
107 TemplateName::TemplateName(OverloadedTemplateStorage
*Storage
)
108 : Storage(Storage
) {}
109 TemplateName::TemplateName(AssumedTemplateStorage
*Storage
)
110 : Storage(Storage
) {}
111 TemplateName::TemplateName(SubstTemplateTemplateParmStorage
*Storage
)
112 : Storage(Storage
) {}
113 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage
*Storage
)
114 : Storage(Storage
) {}
115 TemplateName::TemplateName(QualifiedTemplateName
*Qual
) : Storage(Qual
) {}
116 TemplateName::TemplateName(DependentTemplateName
*Dep
) : Storage(Dep
) {}
117 TemplateName::TemplateName(UsingShadowDecl
*Using
) : Storage(Using
) {}
119 bool TemplateName::isNull() const { return Storage
.isNull(); }
121 TemplateName::NameKind
TemplateName::getKind() const {
122 if (auto *ND
= Storage
.dyn_cast
<Decl
*>()) {
123 if (isa
<UsingShadowDecl
>(ND
))
124 return UsingTemplate
;
125 assert(isa
<TemplateDecl
>(ND
));
129 if (Storage
.is
<DependentTemplateName
*>())
130 return DependentTemplate
;
131 if (Storage
.is
<QualifiedTemplateName
*>())
132 return QualifiedTemplate
;
134 UncommonTemplateNameStorage
*uncommon
135 = Storage
.get
<UncommonTemplateNameStorage
*>();
136 if (uncommon
->getAsOverloadedStorage())
137 return OverloadedTemplate
;
138 if (uncommon
->getAsAssumedTemplateName())
139 return AssumedTemplate
;
140 if (uncommon
->getAsSubstTemplateTemplateParm())
141 return SubstTemplateTemplateParm
;
142 return SubstTemplateTemplateParmPack
;
145 TemplateDecl
*TemplateName::getAsTemplateDecl() const {
146 if (Decl
*TemplateOrUsing
= Storage
.dyn_cast
<Decl
*>()) {
147 if (UsingShadowDecl
*USD
= dyn_cast
<UsingShadowDecl
>(TemplateOrUsing
))
148 return cast
<TemplateDecl
>(USD
->getTargetDecl());
150 assert(isa
<TemplateDecl
>(TemplateOrUsing
));
151 return cast
<TemplateDecl
>(TemplateOrUsing
);
154 if (QualifiedTemplateName
*QTN
= getAsQualifiedTemplateName())
155 return QTN
->getUnderlyingTemplate().getAsTemplateDecl();
157 if (SubstTemplateTemplateParmStorage
*sub
= getAsSubstTemplateTemplateParm())
158 return sub
->getReplacement().getAsTemplateDecl();
160 if (UsingShadowDecl
*USD
= getAsUsingShadowDecl())
161 return cast
<TemplateDecl
>(USD
->getTargetDecl());
166 OverloadedTemplateStorage
*TemplateName::getAsOverloadedTemplate() const {
167 if (UncommonTemplateNameStorage
*Uncommon
=
168 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
169 return Uncommon
->getAsOverloadedStorage();
174 AssumedTemplateStorage
*TemplateName::getAsAssumedTemplateName() const {
175 if (UncommonTemplateNameStorage
*Uncommon
=
176 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
177 return Uncommon
->getAsAssumedTemplateName();
182 SubstTemplateTemplateParmStorage
*
183 TemplateName::getAsSubstTemplateTemplateParm() const {
184 if (UncommonTemplateNameStorage
*uncommon
=
185 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
186 return uncommon
->getAsSubstTemplateTemplateParm();
191 SubstTemplateTemplateParmPackStorage
*
192 TemplateName::getAsSubstTemplateTemplateParmPack() const {
193 if (UncommonTemplateNameStorage
*Uncommon
=
194 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
195 return Uncommon
->getAsSubstTemplateTemplateParmPack();
200 QualifiedTemplateName
*TemplateName::getAsQualifiedTemplateName() const {
201 return Storage
.dyn_cast
<QualifiedTemplateName
*>();
204 DependentTemplateName
*TemplateName::getAsDependentTemplateName() const {
205 return Storage
.dyn_cast
<DependentTemplateName
*>();
208 UsingShadowDecl
*TemplateName::getAsUsingShadowDecl() const {
209 if (Decl
*D
= Storage
.dyn_cast
<Decl
*>())
210 if (UsingShadowDecl
*USD
= dyn_cast
<UsingShadowDecl
>(D
))
212 if (QualifiedTemplateName
*QTN
= getAsQualifiedTemplateName())
213 return QTN
->getUnderlyingTemplate().getAsUsingShadowDecl();
217 TemplateName
TemplateName::getNameToSubstitute() const {
218 TemplateDecl
*Decl
= getAsTemplateDecl();
220 // Substituting a dependent template name: preserve it as written.
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");
231 return TemplateName(Decl
);
234 TemplateNameDependence
TemplateName::getDependence() const {
235 auto D
= TemplateNameDependence::None
;
237 case TemplateName::NameKind::QualifiedTemplate
:
238 D
|= toTemplateNameDependence(
239 getAsQualifiedTemplateName()->getQualifier()->getDependence());
241 case TemplateName::NameKind::DependentTemplate
:
242 D
|= toTemplateNameDependence(
243 getAsDependentTemplateName()->getQualifier()->getDependence());
245 case TemplateName::NameKind::SubstTemplateTemplateParmPack
:
246 D
|= TemplateNameDependence::UnexpandedPack
;
248 case TemplateName::NameKind::OverloadedTemplate
:
249 llvm_unreachable("overloaded templates shouldn't survive to here.");
253 if (TemplateDecl
*Template
= getAsTemplateDecl()) {
254 if (auto *TTP
= dyn_cast
<TemplateTemplateParmDecl
>(Template
)) {
255 D
|= TemplateNameDependence::DependentInstantiation
;
256 if (TTP
->isParameterPack())
257 D
|= TemplateNameDependence::UnexpandedPack
;
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
;
267 D
|= TemplateNameDependence::DependentInstantiation
;
272 bool TemplateName::isDependent() const {
273 return getDependence() & TemplateNameDependence::Dependent
;
276 bool TemplateName::isInstantiationDependent() const {
277 return getDependence() & TemplateNameDependence::Instantiation
;
280 bool TemplateName::containsUnexpandedParameterPack() const {
281 return getDependence() & TemplateNameDependence::UnexpandedPack
;
284 void 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());
290 ID
.AddPointer(Storage
.getOpaqueValue());
293 void TemplateName::print(raw_ostream
&OS
, const PrintingPolicy
&Policy
,
294 Qualified Qual
) const {
295 auto Kind
= getKind();
296 TemplateDecl
*Template
= nullptr;
297 if (Kind
== TemplateName::Template
|| Kind
== TemplateName::UsingTemplate
) {
298 // After `namespace ns { using std::vector }`, what is the fully-qualified
299 // name of the UsingTemplateName `vector` within ns?
301 // - ns::vector (the qualified name of the using-shadow decl)
302 // - std::vector (the qualified name of the underlying template decl)
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.
307 Template
= getAsTemplateDecl();
311 if (Policy
.CleanUglifiedParameters
&&
312 isa
<TemplateTemplateParmDecl
>(Template
) && Template
->getIdentifier())
313 OS
<< Template
->getIdentifier()->deuglifiedName();
314 else if (Qual
== Qualified::Fully
&&
316 TemplateNameDependenceScope::DependentInstantiation
)
317 Template
->printQualifiedName(OS
, Policy
);
320 else if (QualifiedTemplateName
*QTN
= getAsQualifiedTemplateName()) {
321 if (Qual
== Qualified::Fully
&&
323 TemplateNameDependenceScope::DependentInstantiation
) {
324 QTN
->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
328 if (Qual
== Qualified::AsWritten
)
329 QTN
->getQualifier()->print(OS
, Policy
);
330 if (QTN
->hasTemplateKeyword())
332 OS
<< *QTN
->getUnderlyingTemplate().getAsTemplateDecl();
333 } else if (DependentTemplateName
*DTN
= getAsDependentTemplateName()) {
334 if (Qual
== Qualified::AsWritten
&& DTN
->getQualifier())
335 DTN
->getQualifier()->print(OS
, Policy
);
338 if (DTN
->isIdentifier())
339 OS
<< DTN
->getIdentifier()->getName();
341 OS
<< "operator " << getOperatorSpelling(DTN
->getOperator());
342 } else if (SubstTemplateTemplateParmStorage
*subst
343 = getAsSubstTemplateTemplateParm()) {
344 subst
->getReplacement().print(OS
, Policy
, Qual
);
345 } else if (SubstTemplateTemplateParmPackStorage
*SubstPack
346 = getAsSubstTemplateTemplateParmPack())
347 OS
<< *SubstPack
->getParameterPack();
348 else if (AssumedTemplateStorage
*Assumed
= getAsAssumedTemplateName()) {
349 Assumed
->getDeclName().print(OS
, Policy
);
351 assert(getKind() == TemplateName::OverloadedTemplate
);
352 OverloadedTemplateStorage
*OTS
= getAsOverloadedTemplate();
353 (*OTS
->begin())->printName(OS
, Policy
);
357 const StreamingDiagnostic
&clang::operator<<(const StreamingDiagnostic
&DB
,
360 llvm::raw_string_ostream
OS(NameStr
);
365 N
.print(OS
, PrintingPolicy(LO
));
368 return DB
<< NameStr
;
371 void TemplateName::dump(raw_ostream
&OS
) const {
372 LangOptions LO
; // FIXME!
375 print(OS
, PrintingPolicy(LO
));
378 LLVM_DUMP_METHOD
void TemplateName::dump() const {