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"
34 using namespace clang
;
37 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
38 return TemplateArgument(llvm::makeArrayRef(Arguments
, Bits
.Data
));
41 TemplateTemplateParmDecl
*
42 SubstTemplateTemplateParmPackStorage::getParameterPack() const {
43 return cast
<TemplateTemplateParmDecl
>(
44 getReplacedTemplateParameterList(getAssociatedDecl())
45 ->asArray()[Bits
.Index
]);
48 TemplateTemplateParmDecl
*
49 SubstTemplateTemplateParmStorage::getParameter() const {
50 return cast
<TemplateTemplateParmDecl
>(
51 getReplacedTemplateParameterList(getAssociatedDecl())
52 ->asArray()[Bits
.Index
]);
55 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID
&ID
) {
56 Profile(ID
, Replacement
, getAssociatedDecl(), getIndex(), getPackIndex());
59 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID
&ID
,
60 TemplateName Replacement
,
63 Optional
<unsigned> PackIndex
) {
64 Replacement
.Profile(ID
);
65 ID
.AddPointer(AssociatedDecl
);
67 ID
.AddInteger(PackIndex
? *PackIndex
+ 1 : 0);
70 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
71 ArrayRef
<TemplateArgument
> ArgPack
, Decl
*AssociatedDecl
, unsigned Index
,
73 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack
, Index
,
75 Arguments(ArgPack
.data()), AssociatedDeclAndFinal(AssociatedDecl
, Final
) {
76 assert(AssociatedDecl
!= nullptr);
79 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID
&ID
,
80 ASTContext
&Context
) {
81 Profile(ID
, Context
, getArgumentPack(), getAssociatedDecl(), getIndex(),
85 Decl
*SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
86 return AssociatedDeclAndFinal
.getPointer();
89 bool SubstTemplateTemplateParmPackStorage::getFinal() const {
90 return AssociatedDeclAndFinal
.getInt();
93 void SubstTemplateTemplateParmPackStorage::Profile(
94 llvm::FoldingSetNodeID
&ID
, ASTContext
&Context
,
95 const TemplateArgument
&ArgPack
, Decl
*AssociatedDecl
, unsigned Index
,
97 ArgPack
.Profile(ID
, Context
);
98 ID
.AddPointer(AssociatedDecl
);
100 ID
.AddBoolean(Final
);
103 TemplateName::TemplateName(void *Ptr
) {
104 Storage
= StorageType::getFromOpaqueValue(Ptr
);
107 TemplateName::TemplateName(TemplateDecl
*Template
) : Storage(Template
) {}
108 TemplateName::TemplateName(OverloadedTemplateStorage
*Storage
)
109 : Storage(Storage
) {}
110 TemplateName::TemplateName(AssumedTemplateStorage
*Storage
)
111 : Storage(Storage
) {}
112 TemplateName::TemplateName(SubstTemplateTemplateParmStorage
*Storage
)
113 : Storage(Storage
) {}
114 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage
*Storage
)
115 : Storage(Storage
) {}
116 TemplateName::TemplateName(QualifiedTemplateName
*Qual
) : Storage(Qual
) {}
117 TemplateName::TemplateName(DependentTemplateName
*Dep
) : Storage(Dep
) {}
118 TemplateName::TemplateName(UsingShadowDecl
*Using
) : Storage(Using
) {}
120 bool TemplateName::isNull() const { return Storage
.isNull(); }
122 TemplateName::NameKind
TemplateName::getKind() const {
123 if (auto *ND
= Storage
.dyn_cast
<Decl
*>()) {
124 if (isa
<UsingShadowDecl
>(ND
))
125 return UsingTemplate
;
126 assert(isa
<TemplateDecl
>(ND
));
130 if (Storage
.is
<DependentTemplateName
*>())
131 return DependentTemplate
;
132 if (Storage
.is
<QualifiedTemplateName
*>())
133 return QualifiedTemplate
;
135 UncommonTemplateNameStorage
*uncommon
136 = Storage
.get
<UncommonTemplateNameStorage
*>();
137 if (uncommon
->getAsOverloadedStorage())
138 return OverloadedTemplate
;
139 if (uncommon
->getAsAssumedTemplateName())
140 return AssumedTemplate
;
141 if (uncommon
->getAsSubstTemplateTemplateParm())
142 return SubstTemplateTemplateParm
;
143 return SubstTemplateTemplateParmPack
;
146 TemplateDecl
*TemplateName::getAsTemplateDecl() const {
147 if (Decl
*TemplateOrUsing
= Storage
.dyn_cast
<Decl
*>()) {
148 if (UsingShadowDecl
*USD
= dyn_cast
<UsingShadowDecl
>(TemplateOrUsing
))
149 return cast
<TemplateDecl
>(USD
->getTargetDecl());
151 assert(isa
<TemplateDecl
>(TemplateOrUsing
));
152 return cast
<TemplateDecl
>(TemplateOrUsing
);
155 if (QualifiedTemplateName
*QTN
= getAsQualifiedTemplateName())
156 return QTN
->getUnderlyingTemplate().getAsTemplateDecl();
158 if (SubstTemplateTemplateParmStorage
*sub
= getAsSubstTemplateTemplateParm())
159 return sub
->getReplacement().getAsTemplateDecl();
161 if (UsingShadowDecl
*USD
= getAsUsingShadowDecl())
162 return cast
<TemplateDecl
>(USD
->getTargetDecl());
167 OverloadedTemplateStorage
*TemplateName::getAsOverloadedTemplate() const {
168 if (UncommonTemplateNameStorage
*Uncommon
=
169 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
170 return Uncommon
->getAsOverloadedStorage();
175 AssumedTemplateStorage
*TemplateName::getAsAssumedTemplateName() const {
176 if (UncommonTemplateNameStorage
*Uncommon
=
177 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
178 return Uncommon
->getAsAssumedTemplateName();
183 SubstTemplateTemplateParmStorage
*
184 TemplateName::getAsSubstTemplateTemplateParm() const {
185 if (UncommonTemplateNameStorage
*uncommon
=
186 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
187 return uncommon
->getAsSubstTemplateTemplateParm();
192 SubstTemplateTemplateParmPackStorage
*
193 TemplateName::getAsSubstTemplateTemplateParmPack() const {
194 if (UncommonTemplateNameStorage
*Uncommon
=
195 Storage
.dyn_cast
<UncommonTemplateNameStorage
*>())
196 return Uncommon
->getAsSubstTemplateTemplateParmPack();
201 QualifiedTemplateName
*TemplateName::getAsQualifiedTemplateName() const {
202 return Storage
.dyn_cast
<QualifiedTemplateName
*>();
205 DependentTemplateName
*TemplateName::getAsDependentTemplateName() const {
206 return Storage
.dyn_cast
<DependentTemplateName
*>();
209 UsingShadowDecl
*TemplateName::getAsUsingShadowDecl() const {
210 if (Decl
*D
= Storage
.dyn_cast
<Decl
*>())
211 if (UsingShadowDecl
*USD
= dyn_cast
<UsingShadowDecl
>(D
))
213 if (QualifiedTemplateName
*QTN
= getAsQualifiedTemplateName())
214 return QTN
->getUnderlyingTemplate().getAsUsingShadowDecl();
218 TemplateName
TemplateName::getNameToSubstitute() const {
219 TemplateDecl
*Decl
= getAsTemplateDecl();
221 // Substituting a dependent template name: preserve it as written.
225 // If we have a template declaration, use the most recent non-friend
226 // declaration of that template.
227 Decl
= cast
<TemplateDecl
>(Decl
->getMostRecentDecl());
228 while (Decl
->getFriendObjectKind()) {
229 Decl
= cast
<TemplateDecl
>(Decl
->getPreviousDecl());
230 assert(Decl
&& "all declarations of template are friends");
232 return TemplateName(Decl
);
235 TemplateNameDependence
TemplateName::getDependence() const {
236 auto D
= TemplateNameDependence::None
;
238 case TemplateName::NameKind::QualifiedTemplate
:
239 D
|= toTemplateNameDependence(
240 getAsQualifiedTemplateName()->getQualifier()->getDependence());
242 case TemplateName::NameKind::DependentTemplate
:
243 D
|= toTemplateNameDependence(
244 getAsDependentTemplateName()->getQualifier()->getDependence());
246 case TemplateName::NameKind::SubstTemplateTemplateParmPack
:
247 D
|= TemplateNameDependence::UnexpandedPack
;
249 case TemplateName::NameKind::OverloadedTemplate
:
250 llvm_unreachable("overloaded templates shouldn't survive to here.");
254 if (TemplateDecl
*Template
= getAsTemplateDecl()) {
255 if (auto *TTP
= dyn_cast
<TemplateTemplateParmDecl
>(Template
)) {
256 D
|= TemplateNameDependence::DependentInstantiation
;
257 if (TTP
->isParameterPack())
258 D
|= TemplateNameDependence::UnexpandedPack
;
260 // FIXME: Hack, getDeclContext() can be null if Template is still
261 // initializing due to PCH reading, so we check it before using it.
262 // Should probably modify TemplateSpecializationType to allow constructing
263 // it without the isDependent() checking.
264 if (Template
->getDeclContext() &&
265 Template
->getDeclContext()->isDependentContext())
266 D
|= TemplateNameDependence::DependentInstantiation
;
268 D
|= TemplateNameDependence::DependentInstantiation
;
273 bool TemplateName::isDependent() const {
274 return getDependence() & TemplateNameDependence::Dependent
;
277 bool TemplateName::isInstantiationDependent() const {
278 return getDependence() & TemplateNameDependence::Instantiation
;
281 bool TemplateName::containsUnexpandedParameterPack() const {
282 return getDependence() & TemplateNameDependence::UnexpandedPack
;
285 void TemplateName::print(raw_ostream
&OS
, const PrintingPolicy
&Policy
,
286 Qualified Qual
) const {
287 auto Kind
= getKind();
288 TemplateDecl
*Template
= nullptr;
289 if (Kind
== TemplateName::Template
|| Kind
== TemplateName::UsingTemplate
) {
290 // After `namespace ns { using std::vector }`, what is the fully-qualified
291 // name of the UsingTemplateName `vector` within ns?
293 // - ns::vector (the qualified name of the using-shadow decl)
294 // - std::vector (the qualified name of the underlying template decl)
296 // Similar to the UsingType behavior, using declarations are used to import
297 // names more often than to export them, thus using the original name is
298 // most useful in this case.
299 Template
= getAsTemplateDecl();
303 if (Policy
.CleanUglifiedParameters
&&
304 isa
<TemplateTemplateParmDecl
>(Template
) && Template
->getIdentifier())
305 OS
<< Template
->getIdentifier()->deuglifiedName();
306 else if (Qual
== Qualified::Fully
&&
308 TemplateNameDependenceScope::DependentInstantiation
)
309 Template
->printQualifiedName(OS
, Policy
);
312 else if (QualifiedTemplateName
*QTN
= getAsQualifiedTemplateName()) {
313 if (Qual
== Qualified::Fully
&&
315 TemplateNameDependenceScope::DependentInstantiation
) {
316 QTN
->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
320 if (Qual
== Qualified::AsWritten
)
321 QTN
->getQualifier()->print(OS
, Policy
);
322 if (QTN
->hasTemplateKeyword())
324 OS
<< *QTN
->getUnderlyingTemplate().getAsTemplateDecl();
325 } else if (DependentTemplateName
*DTN
= getAsDependentTemplateName()) {
326 if (Qual
== Qualified::AsWritten
&& DTN
->getQualifier())
327 DTN
->getQualifier()->print(OS
, Policy
);
330 if (DTN
->isIdentifier())
331 OS
<< DTN
->getIdentifier()->getName();
333 OS
<< "operator " << getOperatorSpelling(DTN
->getOperator());
334 } else if (SubstTemplateTemplateParmStorage
*subst
335 = getAsSubstTemplateTemplateParm()) {
336 subst
->getReplacement().print(OS
, Policy
, Qual
);
337 } else if (SubstTemplateTemplateParmPackStorage
*SubstPack
338 = getAsSubstTemplateTemplateParmPack())
339 OS
<< *SubstPack
->getParameterPack();
340 else if (AssumedTemplateStorage
*Assumed
= getAsAssumedTemplateName()) {
341 Assumed
->getDeclName().print(OS
, Policy
);
343 assert(getKind() == TemplateName::OverloadedTemplate
);
344 OverloadedTemplateStorage
*OTS
= getAsOverloadedTemplate();
345 (*OTS
->begin())->printName(OS
, Policy
);
349 const StreamingDiagnostic
&clang::operator<<(const StreamingDiagnostic
&DB
,
352 llvm::raw_string_ostream
OS(NameStr
);
357 N
.print(OS
, PrintingPolicy(LO
));
360 return DB
<< NameStr
;
363 void TemplateName::dump(raw_ostream
&OS
) const {
364 LangOptions LO
; // FIXME!
367 print(OS
, PrintingPolicy(LO
));
370 LLVM_DUMP_METHOD
void TemplateName::dump() const {