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 <optional> |
33 | #include <string> |
34 | |
35 | using namespace clang; |
36 | |
37 | TemplateArgument |
38 | SubstTemplateTemplateParmPackStorage::getArgumentPack() const { |
39 | return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data)); |
40 | } |
41 | |
42 | TemplateTemplateParmDecl * |
43 | SubstTemplateTemplateParmPackStorage::getParameterPack() const { |
44 | return cast<TemplateTemplateParmDecl>( |
45 | Val: getReplacedTemplateParameterList(D: getAssociatedDecl()) |
46 | ->asArray()[Bits.Index]); |
47 | } |
48 | |
49 | TemplateTemplateParmDecl * |
50 | SubstTemplateTemplateParmStorage::getParameter() const { |
51 | return cast<TemplateTemplateParmDecl>( |
52 | Val: getReplacedTemplateParameterList(D: getAssociatedDecl()) |
53 | ->asArray()[Bits.Index]); |
54 | } |
55 | |
56 | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { |
57 | Profile(ID, Replacement, AssociatedDecl: getAssociatedDecl(), Index: getIndex(), PackIndex: getPackIndex()); |
58 | } |
59 | |
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(Ptr: AssociatedDecl); |
65 | ID.AddInteger(I: Index); |
66 | ID.AddInteger(I: PackIndex ? *PackIndex + 1 : 0); |
67 | } |
68 | |
69 | SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage( |
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 | |
78 | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, |
79 | ASTContext &Context) { |
80 | Profile(ID, Context, ArgPack: getArgumentPack(), AssociatedDecl: getAssociatedDecl(), Index: getIndex(), |
81 | Final: getFinal()); |
82 | } |
83 | |
84 | Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const { |
85 | return AssociatedDeclAndFinal.getPointer(); |
86 | } |
87 | |
88 | bool SubstTemplateTemplateParmPackStorage::getFinal() const { |
89 | return AssociatedDeclAndFinal.getInt(); |
90 | } |
91 | |
92 | void SubstTemplateTemplateParmPackStorage::Profile( |
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(Ptr: AssociatedDecl); |
98 | ID.AddInteger(I: Index); |
99 | ID.AddBoolean(B: Final); |
100 | } |
101 | |
102 | TemplateName::TemplateName(void *Ptr) { |
103 | Storage = StorageType::getFromOpaqueValue(VP: Ptr); |
104 | } |
105 | |
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) {} |
118 | |
119 | bool TemplateName::isNull() const { return Storage.isNull(); } |
120 | |
121 | TemplateName::NameKind TemplateName::getKind() const { |
122 | if (auto *ND = Storage.dyn_cast<Decl *>()) { |
123 | if (isa<UsingShadowDecl>(Val: 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 | |
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; |
143 | } |
144 | |
145 | TemplateDecl *TemplateName::getAsTemplateDecl() const { |
146 | if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) { |
147 | if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(Val: TemplateOrUsing)) |
148 | return cast<TemplateDecl>(Val: USD->getTargetDecl()); |
149 | |
150 | assert(isa<TemplateDecl>(TemplateOrUsing)); |
151 | return cast<TemplateDecl>(Val: TemplateOrUsing); |
152 | } |
153 | |
154 | if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) |
155 | return QTN->getUnderlyingTemplate().getAsTemplateDecl(); |
156 | |
157 | if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) |
158 | return sub->getReplacement().getAsTemplateDecl(); |
159 | |
160 | if (UsingShadowDecl *USD = getAsUsingShadowDecl()) |
161 | return cast<TemplateDecl>(Val: USD->getTargetDecl()); |
162 | |
163 | return nullptr; |
164 | } |
165 | |
166 | OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { |
167 | if (UncommonTemplateNameStorage *Uncommon = |
168 | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
169 | return Uncommon->getAsOverloadedStorage(); |
170 | |
171 | return nullptr; |
172 | } |
173 | |
174 | AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const { |
175 | if (UncommonTemplateNameStorage *Uncommon = |
176 | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
177 | return Uncommon->getAsAssumedTemplateName(); |
178 | |
179 | return nullptr; |
180 | } |
181 | |
182 | SubstTemplateTemplateParmStorage * |
183 | TemplateName::getAsSubstTemplateTemplateParm() const { |
184 | if (UncommonTemplateNameStorage *uncommon = |
185 | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
186 | return uncommon->getAsSubstTemplateTemplateParm(); |
187 | |
188 | return nullptr; |
189 | } |
190 | |
191 | SubstTemplateTemplateParmPackStorage * |
192 | TemplateName::getAsSubstTemplateTemplateParmPack() const { |
193 | if (UncommonTemplateNameStorage *Uncommon = |
194 | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
195 | return Uncommon->getAsSubstTemplateTemplateParmPack(); |
196 | |
197 | return nullptr; |
198 | } |
199 | |
200 | QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { |
201 | return Storage.dyn_cast<QualifiedTemplateName *>(); |
202 | } |
203 | |
204 | DependentTemplateName *TemplateName::getAsDependentTemplateName() const { |
205 | return Storage.dyn_cast<DependentTemplateName *>(); |
206 | } |
207 | |
208 | UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { |
209 | if (Decl *D = Storage.dyn_cast<Decl *>()) |
210 | if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(Val: D)) |
211 | return USD; |
212 | if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) |
213 | return QTN->getUnderlyingTemplate().getAsUsingShadowDecl(); |
214 | return nullptr; |
215 | } |
216 | |
217 | TemplateName TemplateName::getNameToSubstitute() const { |
218 | TemplateDecl *Decl = getAsTemplateDecl(); |
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 | |
234 | TemplateNameDependence TemplateName::getDependence() const { |
235 | auto D = TemplateNameDependence::None; |
236 | switch (getKind()) { |
237 | case TemplateName::NameKind::QualifiedTemplate: |
238 | D |= toTemplateNameDependence( |
239 | D: getAsQualifiedTemplateName()->getQualifier()->getDependence()); |
240 | break; |
241 | case TemplateName::NameKind::DependentTemplate: |
242 | D |= toTemplateNameDependence( |
243 | D: getAsDependentTemplateName()->getQualifier()->getDependence()); |
244 | break; |
245 | case TemplateName::NameKind::SubstTemplateTemplateParmPack: |
246 | D |= TemplateNameDependence::UnexpandedPack; |
247 | break; |
248 | case TemplateName::NameKind::OverloadedTemplate: |
249 | llvm_unreachable("overloaded templates shouldn't survive to here." ); |
250 | default: |
251 | break; |
252 | } |
253 | if (TemplateDecl *Template = getAsTemplateDecl()) { |
254 | if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: 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 | |
272 | bool TemplateName::isDependent() const { |
273 | return getDependence() & TemplateNameDependence::Dependent; |
274 | } |
275 | |
276 | bool TemplateName::isInstantiationDependent() const { |
277 | return getDependence() & TemplateNameDependence::Instantiation; |
278 | } |
279 | |
280 | bool TemplateName::containsUnexpandedParameterPack() const { |
281 | return getDependence() & TemplateNameDependence::UnexpandedPack; |
282 | } |
283 | |
284 | void TemplateName::Profile(llvm::FoldingSetNodeID &ID) { |
285 | if (const auto* USD = getAsUsingShadowDecl()) |
286 | ID.AddPointer(Ptr: USD->getCanonicalDecl()); |
287 | else if (const auto *TD = getAsTemplateDecl()) |
288 | ID.AddPointer(Ptr: TD->getCanonicalDecl()); |
289 | else |
290 | ID.AddPointer(Ptr: Storage.getOpaqueValue()); |
291 | } |
292 | |
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? |
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. |
307 | Template = getAsTemplateDecl(); |
308 | } |
309 | |
310 | if (Template) |
311 | if (Policy.CleanUglifiedParameters && |
312 | isa<TemplateTemplateParmDecl>(Val: 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; |
320 | else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { |
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(); |
333 | } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { |
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(Operator: 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); |
350 | } else { |
351 | assert(getKind() == TemplateName::OverloadedTemplate); |
352 | OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); |
353 | (*OTS->begin())->printName(OS, Policy); |
354 | } |
355 | } |
356 | |
357 | const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, |
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, Policy: PrintingPolicy(LO)); |
366 | OS << '\''; |
367 | OS.flush(); |
368 | return DB << NameStr; |
369 | } |
370 | |
371 | void TemplateName::dump(raw_ostream &OS) const { |
372 | LangOptions LO; // FIXME! |
373 | LO.CPlusPlus = true; |
374 | LO.Bool = true; |
375 | print(OS, Policy: PrintingPolicy(LO)); |
376 | } |
377 | |
378 | LLVM_DUMP_METHOD void TemplateName::dump() const { |
379 | dump(OS&: llvm::errs()); |
380 | } |
381 | |