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
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"
31 #include <cassert>
32 #include <string>
33
34 using namespace clang;
35
36 TemplateArgument
getArgumentPack() const37 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
38 return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
39 }
40
Profile(llvm::FoldingSetNodeID & ID)41 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
42 Profile(ID, Parameter, Replacement);
43 }
44
Profile(llvm::FoldingSetNodeID & ID,TemplateTemplateParmDecl * parameter,TemplateName replacement)45 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
46 TemplateTemplateParmDecl *parameter,
47 TemplateName replacement) {
48 ID.AddPointer(parameter);
49 ID.AddPointer(replacement.getAsVoidPointer());
50 }
51
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context)52 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
53 ASTContext &Context) {
54 Profile(ID, Context, Parameter, getArgumentPack());
55 }
56
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context,TemplateTemplateParmDecl * Parameter,const TemplateArgument & ArgPack)57 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
58 ASTContext &Context,
59 TemplateTemplateParmDecl *Parameter,
60 const TemplateArgument &ArgPack) {
61 ID.AddPointer(Parameter);
62 ArgPack.Profile(ID, Context);
63 }
64
TemplateName(void * Ptr)65 TemplateName::TemplateName(void *Ptr) {
66 Storage = StorageType::getFromOpaqueValue(Ptr);
67 }
68
TemplateName(TemplateDecl * Template)69 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
TemplateName(OverloadedTemplateStorage * Storage)70 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
71 : Storage(Storage) {}
TemplateName(AssumedTemplateStorage * Storage)72 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
73 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmStorage * Storage)74 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
75 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmPackStorage * Storage)76 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
77 : Storage(Storage) {}
TemplateName(QualifiedTemplateName * Qual)78 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
TemplateName(DependentTemplateName * Dep)79 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
TemplateName(UsingShadowDecl * Using)80 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
81
isNull() const82 bool TemplateName::isNull() const { return Storage.isNull(); }
83
getKind() const84 TemplateName::NameKind TemplateName::getKind() const {
85 if (auto *ND = Storage.dyn_cast<Decl *>()) {
86 if (isa<UsingShadowDecl>(ND))
87 return UsingTemplate;
88 assert(isa<TemplateDecl>(ND));
89 return Template;
90 }
91
92 if (Storage.is<DependentTemplateName *>())
93 return DependentTemplate;
94 if (Storage.is<QualifiedTemplateName *>())
95 return QualifiedTemplate;
96
97 UncommonTemplateNameStorage *uncommon
98 = Storage.get<UncommonTemplateNameStorage*>();
99 if (uncommon->getAsOverloadedStorage())
100 return OverloadedTemplate;
101 if (uncommon->getAsAssumedTemplateName())
102 return AssumedTemplate;
103 if (uncommon->getAsSubstTemplateTemplateParm())
104 return SubstTemplateTemplateParm;
105 return SubstTemplateTemplateParmPack;
106 }
107
getAsTemplateDecl() const108 TemplateDecl *TemplateName::getAsTemplateDecl() const {
109 if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) {
110 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing))
111 return cast<TemplateDecl>(USD->getTargetDecl());
112
113 assert(isa<TemplateDecl>(TemplateOrUsing));
114 return cast<TemplateDecl>(TemplateOrUsing);
115 }
116
117 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
118 return QTN->getUnderlyingTemplate().getAsTemplateDecl();
119
120 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
121 return sub->getReplacement().getAsTemplateDecl();
122
123 if (UsingShadowDecl *USD = getAsUsingShadowDecl())
124 return cast<TemplateDecl>(USD->getTargetDecl());
125
126 return nullptr;
127 }
128
getAsOverloadedTemplate() const129 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
130 if (UncommonTemplateNameStorage *Uncommon =
131 Storage.dyn_cast<UncommonTemplateNameStorage *>())
132 return Uncommon->getAsOverloadedStorage();
133
134 return nullptr;
135 }
136
getAsAssumedTemplateName() const137 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
138 if (UncommonTemplateNameStorage *Uncommon =
139 Storage.dyn_cast<UncommonTemplateNameStorage *>())
140 return Uncommon->getAsAssumedTemplateName();
141
142 return nullptr;
143 }
144
145 SubstTemplateTemplateParmStorage *
getAsSubstTemplateTemplateParm() const146 TemplateName::getAsSubstTemplateTemplateParm() const {
147 if (UncommonTemplateNameStorage *uncommon =
148 Storage.dyn_cast<UncommonTemplateNameStorage *>())
149 return uncommon->getAsSubstTemplateTemplateParm();
150
151 return nullptr;
152 }
153
154 SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const155 TemplateName::getAsSubstTemplateTemplateParmPack() const {
156 if (UncommonTemplateNameStorage *Uncommon =
157 Storage.dyn_cast<UncommonTemplateNameStorage *>())
158 return Uncommon->getAsSubstTemplateTemplateParmPack();
159
160 return nullptr;
161 }
162
getAsQualifiedTemplateName() const163 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
164 return Storage.dyn_cast<QualifiedTemplateName *>();
165 }
166
getAsDependentTemplateName() const167 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
168 return Storage.dyn_cast<DependentTemplateName *>();
169 }
170
getAsUsingShadowDecl() const171 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
172 if (Decl *D = Storage.dyn_cast<Decl *>())
173 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
174 return USD;
175 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
176 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
177 return nullptr;
178 }
179
getNameToSubstitute() const180 TemplateName TemplateName::getNameToSubstitute() const {
181 TemplateDecl *Decl = getAsTemplateDecl();
182
183 // Substituting a dependent template name: preserve it as written.
184 if (!Decl)
185 return *this;
186
187 // If we have a template declaration, use the most recent non-friend
188 // declaration of that template.
189 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
190 while (Decl->getFriendObjectKind()) {
191 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
192 assert(Decl && "all declarations of template are friends");
193 }
194 return TemplateName(Decl);
195 }
196
getDependence() const197 TemplateNameDependence TemplateName::getDependence() const {
198 auto D = TemplateNameDependence::None;
199 switch (getKind()) {
200 case TemplateName::NameKind::QualifiedTemplate:
201 D |= toTemplateNameDependence(
202 getAsQualifiedTemplateName()->getQualifier()->getDependence());
203 break;
204 case TemplateName::NameKind::DependentTemplate:
205 D |= toTemplateNameDependence(
206 getAsDependentTemplateName()->getQualifier()->getDependence());
207 break;
208 case TemplateName::NameKind::SubstTemplateTemplateParmPack:
209 D |= TemplateNameDependence::UnexpandedPack;
210 break;
211 case TemplateName::NameKind::OverloadedTemplate:
212 llvm_unreachable("overloaded templates shouldn't survive to here.");
213 default:
214 break;
215 }
216 if (TemplateDecl *Template = getAsTemplateDecl()) {
217 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
218 D |= TemplateNameDependence::DependentInstantiation;
219 if (TTP->isParameterPack())
220 D |= TemplateNameDependence::UnexpandedPack;
221 }
222 // FIXME: Hack, getDeclContext() can be null if Template is still
223 // initializing due to PCH reading, so we check it before using it.
224 // Should probably modify TemplateSpecializationType to allow constructing
225 // it without the isDependent() checking.
226 if (Template->getDeclContext() &&
227 Template->getDeclContext()->isDependentContext())
228 D |= TemplateNameDependence::DependentInstantiation;
229 } else {
230 D |= TemplateNameDependence::DependentInstantiation;
231 }
232 return D;
233 }
234
isDependent() const235 bool TemplateName::isDependent() const {
236 return getDependence() & TemplateNameDependence::Dependent;
237 }
238
isInstantiationDependent() const239 bool TemplateName::isInstantiationDependent() const {
240 return getDependence() & TemplateNameDependence::Instantiation;
241 }
242
containsUnexpandedParameterPack() const243 bool TemplateName::containsUnexpandedParameterPack() const {
244 return getDependence() & TemplateNameDependence::UnexpandedPack;
245 }
246
print(raw_ostream & OS,const PrintingPolicy & Policy,Qualified Qual) const247 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
248 Qualified Qual) const {
249 auto Kind = getKind();
250 TemplateDecl *Template = nullptr;
251 if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
252 // After `namespace ns { using std::vector }`, what is the fully-qualified
253 // name of the UsingTemplateName `vector` within ns?
254 //
255 // - ns::vector (the qualified name of the using-shadow decl)
256 // - std::vector (the qualified name of the underlying template decl)
257 //
258 // Similar to the UsingType behavior, using declarations are used to import
259 // names more often than to export them, thus using the original name is
260 // most useful in this case.
261 Template = getAsTemplateDecl();
262 }
263
264 if (Template)
265 if (Policy.CleanUglifiedParameters &&
266 isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
267 OS << Template->getIdentifier()->deuglifiedName();
268 else if (Qual == Qualified::Fully &&
269 getDependence() !=
270 TemplateNameDependenceScope::DependentInstantiation)
271 Template->printQualifiedName(OS, Policy);
272 else
273 OS << *Template;
274 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
275 if (Qual == Qualified::Fully &&
276 getDependence() !=
277 TemplateNameDependenceScope::DependentInstantiation) {
278 QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
279 OS, Policy);
280 return;
281 }
282 if (Qual == Qualified::AsWritten)
283 QTN->getQualifier()->print(OS, Policy);
284 if (QTN->hasTemplateKeyword())
285 OS << "template ";
286 OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
287 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
288 if (Qual == Qualified::AsWritten && DTN->getQualifier())
289 DTN->getQualifier()->print(OS, Policy);
290 OS << "template ";
291
292 if (DTN->isIdentifier())
293 OS << DTN->getIdentifier()->getName();
294 else
295 OS << "operator " << getOperatorSpelling(DTN->getOperator());
296 } else if (SubstTemplateTemplateParmStorage *subst
297 = getAsSubstTemplateTemplateParm()) {
298 subst->getReplacement().print(OS, Policy, Qual);
299 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
300 = getAsSubstTemplateTemplateParmPack())
301 OS << *SubstPack->getParameterPack();
302 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
303 Assumed->getDeclName().print(OS, Policy);
304 } else {
305 assert(getKind() == TemplateName::OverloadedTemplate);
306 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
307 (*OTS->begin())->printName(OS);
308 }
309 }
310
operator <<(const StreamingDiagnostic & DB,TemplateName N)311 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
312 TemplateName N) {
313 std::string NameStr;
314 llvm::raw_string_ostream OS(NameStr);
315 LangOptions LO;
316 LO.CPlusPlus = true;
317 LO.Bool = true;
318 OS << '\'';
319 N.print(OS, PrintingPolicy(LO));
320 OS << '\'';
321 OS.flush();
322 return DB << NameStr;
323 }
324
dump(raw_ostream & OS) const325 void TemplateName::dump(raw_ostream &OS) const {
326 LangOptions LO; // FIXME!
327 LO.CPlusPlus = true;
328 LO.Bool = true;
329 print(OS, PrintingPolicy(LO));
330 }
331
dump() const332 LLVM_DUMP_METHOD void TemplateName::dump() const {
333 dump(llvm::errs());
334 }
335