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 | TemplateNameDependence TemplateName::getDependence() const { |
218 | auto D = TemplateNameDependence::None; |
219 | switch (getKind()) { |
220 | case TemplateName::NameKind::QualifiedTemplate: |
221 | if (NestedNameSpecifier *NNS = getAsQualifiedTemplateName()->getQualifier()) |
222 | D |= toTemplateNameDependence(D: NNS->getDependence()); |
223 | break; |
224 | case TemplateName::NameKind::DependentTemplate: |
225 | D |= toTemplateNameDependence( |
226 | D: getAsDependentTemplateName()->getQualifier()->getDependence()); |
227 | break; |
228 | case TemplateName::NameKind::SubstTemplateTemplateParmPack: |
229 | D |= TemplateNameDependence::UnexpandedPack; |
230 | break; |
231 | case TemplateName::NameKind::OverloadedTemplate: |
232 | llvm_unreachable("overloaded templates shouldn't survive to here." ); |
233 | default: |
234 | break; |
235 | } |
236 | if (TemplateDecl *Template = getAsTemplateDecl()) { |
237 | if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: Template)) { |
238 | D |= TemplateNameDependence::DependentInstantiation; |
239 | if (TTP->isParameterPack()) |
240 | D |= TemplateNameDependence::UnexpandedPack; |
241 | } |
242 | // FIXME: Hack, getDeclContext() can be null if Template is still |
243 | // initializing due to PCH reading, so we check it before using it. |
244 | // Should probably modify TemplateSpecializationType to allow constructing |
245 | // it without the isDependent() checking. |
246 | if (Template->getDeclContext() && |
247 | Template->getDeclContext()->isDependentContext()) |
248 | D |= TemplateNameDependence::DependentInstantiation; |
249 | } else { |
250 | D |= TemplateNameDependence::DependentInstantiation; |
251 | } |
252 | return D; |
253 | } |
254 | |
255 | bool TemplateName::isDependent() const { |
256 | return getDependence() & TemplateNameDependence::Dependent; |
257 | } |
258 | |
259 | bool TemplateName::isInstantiationDependent() const { |
260 | return getDependence() & TemplateNameDependence::Instantiation; |
261 | } |
262 | |
263 | bool TemplateName::containsUnexpandedParameterPack() const { |
264 | return getDependence() & TemplateNameDependence::UnexpandedPack; |
265 | } |
266 | |
267 | void TemplateName::Profile(llvm::FoldingSetNodeID &ID) { |
268 | if (const auto* USD = getAsUsingShadowDecl()) |
269 | ID.AddPointer(Ptr: USD->getCanonicalDecl()); |
270 | else if (const auto *TD = getAsTemplateDecl()) |
271 | ID.AddPointer(Ptr: TD->getCanonicalDecl()); |
272 | else |
273 | ID.AddPointer(Ptr: Storage.getOpaqueValue()); |
274 | } |
275 | |
276 | void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, |
277 | Qualified Qual) const { |
278 | auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) { |
279 | if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: TD); |
280 | TTP && TTP->getIdentifier() == nullptr) { |
281 | OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex(); |
282 | return true; |
283 | } |
284 | return false; |
285 | }; |
286 | if (NameKind Kind = getKind(); |
287 | Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { |
288 | // After `namespace ns { using std::vector }`, what is the fully-qualified |
289 | // name of the UsingTemplateName `vector` within ns? |
290 | // |
291 | // - ns::vector (the qualified name of the using-shadow decl) |
292 | // - std::vector (the qualified name of the underlying template decl) |
293 | // |
294 | // Similar to the UsingType behavior, using declarations are used to import |
295 | // names more often than to export them, thus using the original name is |
296 | // most useful in this case. |
297 | TemplateDecl *Template = getAsTemplateDecl(); |
298 | if (handleAnonymousTTP(Template, OS)) |
299 | return; |
300 | if (Qual == Qualified::None) |
301 | OS << *Template; |
302 | else |
303 | Template->printQualifiedName(OS, Policy); |
304 | } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { |
305 | if (NestedNameSpecifier *NNS = QTN->getQualifier(); |
306 | Qual != Qualified::None && NNS) |
307 | NNS->print(OS, Policy); |
308 | if (QTN->hasTemplateKeyword()) |
309 | OS << "template " ; |
310 | |
311 | TemplateName Underlying = QTN->getUnderlyingTemplate(); |
312 | assert(Underlying.getKind() == TemplateName::Template || |
313 | Underlying.getKind() == TemplateName::UsingTemplate); |
314 | |
315 | TemplateDecl *UTD = Underlying.getAsTemplateDecl(); |
316 | |
317 | if (handleAnonymousTTP(UTD, OS)) |
318 | return; |
319 | |
320 | if (IdentifierInfo *II = UTD->getIdentifier(); |
321 | Policy.CleanUglifiedParameters && II && |
322 | isa<TemplateTemplateParmDecl>(Val: UTD)) |
323 | OS << II->deuglifiedName(); |
324 | else |
325 | OS << *UTD; |
326 | } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { |
327 | if (NestedNameSpecifier *NNS = DTN->getQualifier()) |
328 | NNS->print(OS, Policy); |
329 | OS << "template " ; |
330 | |
331 | if (DTN->isIdentifier()) |
332 | OS << DTN->getIdentifier()->getName(); |
333 | else |
334 | OS << "operator " << getOperatorSpelling(Operator: DTN->getOperator()); |
335 | } else if (SubstTemplateTemplateParmStorage *subst = |
336 | getAsSubstTemplateTemplateParm()) { |
337 | subst->getReplacement().print(OS, Policy, Qual); |
338 | } else if (SubstTemplateTemplateParmPackStorage *SubstPack = |
339 | getAsSubstTemplateTemplateParmPack()) |
340 | OS << *SubstPack->getParameterPack(); |
341 | else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { |
342 | Assumed->getDeclName().print(OS, Policy); |
343 | } else { |
344 | assert(getKind() == TemplateName::OverloadedTemplate); |
345 | OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); |
346 | (*OTS->begin())->printName(OS, Policy); |
347 | } |
348 | } |
349 | |
350 | const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, |
351 | TemplateName N) { |
352 | std::string NameStr; |
353 | llvm::raw_string_ostream OS(NameStr); |
354 | LangOptions LO; |
355 | LO.CPlusPlus = true; |
356 | LO.Bool = true; |
357 | OS << '\''; |
358 | N.print(OS, Policy: PrintingPolicy(LO)); |
359 | OS << '\''; |
360 | OS.flush(); |
361 | return DB << NameStr; |
362 | } |
363 | |