/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/TemplateName.cpp
Line | Count | Source (jump to first uncovered line) |
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 |
37 | 9 | SubstTemplateTemplateParmPackStorage::getArgumentPack() const { |
38 | 9 | return TemplateArgument(llvm::makeArrayRef(Arguments, size())); |
39 | 9 | } |
40 | | |
41 | 27.4k | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { |
42 | 27.4k | Profile(ID, Parameter, Replacement); |
43 | 27.4k | } |
44 | | |
45 | | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, |
46 | | TemplateTemplateParmDecl *parameter, |
47 | 56.5k | TemplateName replacement) { |
48 | 56.5k | ID.AddPointer(parameter); |
49 | 56.5k | ID.AddPointer(replacement.getAsVoidPointer()); |
50 | 56.5k | } |
51 | | |
52 | | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, |
53 | 0 | ASTContext &Context) { |
54 | 0 | Profile(ID, Context, Parameter, getArgumentPack()); |
55 | 0 | } |
56 | | |
57 | | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, |
58 | | ASTContext &Context, |
59 | | TemplateTemplateParmDecl *Parameter, |
60 | 8 | const TemplateArgument &ArgPack) { |
61 | 8 | ID.AddPointer(Parameter); |
62 | 8 | ArgPack.Profile(ID, Context); |
63 | 8 | } |
64 | | |
65 | 4.17M | TemplateName::TemplateName(void *Ptr) { |
66 | 4.17M | Storage = StorageType::getFromOpaqueValue(Ptr); |
67 | 4.17M | } |
68 | | |
69 | 17.2M | TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} |
70 | | TemplateName::TemplateName(OverloadedTemplateStorage *Storage) |
71 | 140k | : Storage(Storage) {} |
72 | | TemplateName::TemplateName(AssumedTemplateStorage *Storage) |
73 | 828 | : Storage(Storage) {} |
74 | | TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) |
75 | 29.0k | : Storage(Storage) {} |
76 | | TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) |
77 | 8 | : Storage(Storage) {} |
78 | 296k | TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} |
79 | 82.5k | TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} |
80 | 219 | TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {} |
81 | | |
82 | 5.23M | bool TemplateName::isNull() const { return Storage.isNull(); } |
83 | | |
84 | 49.7M | TemplateName::NameKind TemplateName::getKind() const { |
85 | 49.7M | if (auto *ND = Storage.dyn_cast<Decl *>()) { |
86 | 49.2M | if (isa<UsingShadowDecl>(ND)) |
87 | 1.25k | return UsingTemplate; |
88 | 49.2M | assert(isa<TemplateDecl>(ND)); |
89 | 0 | return Template; |
90 | 49.2M | } |
91 | | |
92 | 572k | if (Storage.is<DependentTemplateName *>()) |
93 | 12.4k | return DependentTemplate; |
94 | 560k | if (Storage.is<QualifiedTemplateName *>()) |
95 | 321k | return QualifiedTemplate; |
96 | | |
97 | 238k | UncommonTemplateNameStorage *uncommon |
98 | 238k | = Storage.get<UncommonTemplateNameStorage*>(); |
99 | 238k | if (uncommon->getAsOverloadedStorage()) |
100 | 143k | return OverloadedTemplate; |
101 | 94.8k | if (uncommon->getAsAssumedTemplateName()) |
102 | 67 | return AssumedTemplate; |
103 | 94.8k | if (uncommon->getAsSubstTemplateTemplateParm()) |
104 | 94.8k | return SubstTemplateTemplateParm; |
105 | 22 | return SubstTemplateTemplateParmPack; |
106 | 94.8k | } |
107 | | |
108 | 73.5M | TemplateDecl *TemplateName::getAsTemplateDecl() const { |
109 | 73.5M | if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) { |
110 | 72.6M | if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing)) |
111 | 1.38k | return cast<TemplateDecl>(USD->getTargetDecl()); |
112 | | |
113 | 72.6M | assert(isa<TemplateDecl>(TemplateOrUsing)); |
114 | 0 | return cast<TemplateDecl>(TemplateOrUsing); |
115 | 72.6M | } |
116 | | |
117 | 891k | if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) |
118 | 739k | return QTN->getUnderlyingTemplate().getAsTemplateDecl(); |
119 | | |
120 | 151k | if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) |
121 | 93.9k | return sub->getReplacement().getAsTemplateDecl(); |
122 | | |
123 | 57.4k | if (UsingShadowDecl *USD = getAsUsingShadowDecl()) |
124 | 0 | return cast<TemplateDecl>(USD->getTargetDecl()); |
125 | | |
126 | 57.4k | return nullptr; |
127 | 57.4k | } |
128 | | |
129 | 1.60M | OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { |
130 | 1.60M | if (UncommonTemplateNameStorage *Uncommon = |
131 | 1.60M | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
132 | 143k | return Uncommon->getAsOverloadedStorage(); |
133 | | |
134 | 1.46M | return nullptr; |
135 | 1.60M | } |
136 | | |
137 | 11.1M | AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const { |
138 | 11.1M | if (UncommonTemplateNameStorage *Uncommon = |
139 | 11.1M | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
140 | 24.3k | return Uncommon->getAsAssumedTemplateName(); |
141 | | |
142 | 11.1M | return nullptr; |
143 | 11.1M | } |
144 | | |
145 | | SubstTemplateTemplateParmStorage * |
146 | 8.31M | TemplateName::getAsSubstTemplateTemplateParm() const { |
147 | 8.31M | if (UncommonTemplateNameStorage *uncommon = |
148 | 8.31M | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
149 | 128k | return uncommon->getAsSubstTemplateTemplateParm(); |
150 | | |
151 | 8.18M | return nullptr; |
152 | 8.31M | } |
153 | | |
154 | | SubstTemplateTemplateParmPackStorage * |
155 | 4.59M | TemplateName::getAsSubstTemplateTemplateParmPack() const { |
156 | 4.59M | if (UncommonTemplateNameStorage *Uncommon = |
157 | 4.59M | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
158 | 250 | return Uncommon->getAsSubstTemplateTemplateParmPack(); |
159 | | |
160 | 4.59M | return nullptr; |
161 | 4.59M | } |
162 | | |
163 | 24.5M | QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { |
164 | 24.5M | return Storage.dyn_cast<QualifiedTemplateName *>(); |
165 | 24.5M | } |
166 | | |
167 | 57.2M | DependentTemplateName *TemplateName::getAsDependentTemplateName() const { |
168 | 57.2M | return Storage.dyn_cast<DependentTemplateName *>(); |
169 | 57.2M | } |
170 | | |
171 | 57.5k | UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { |
172 | 57.5k | if (Decl *D = Storage.dyn_cast<Decl *>()) |
173 | 60 | if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) |
174 | 60 | return USD; |
175 | 57.4k | if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) |
176 | 1 | return QTN->getUnderlyingTemplate().getAsUsingShadowDecl(); |
177 | 57.4k | return nullptr; |
178 | 57.4k | } |
179 | | |
180 | 28.9k | TemplateName TemplateName::getNameToSubstitute() const { |
181 | 28.9k | TemplateDecl *Decl = getAsTemplateDecl(); |
182 | | |
183 | | // Substituting a dependent template name: preserve it as written. |
184 | 28.9k | if (!Decl) |
185 | 483 | return *this; |
186 | | |
187 | | // If we have a template declaration, use the most recent non-friend |
188 | | // declaration of that template. |
189 | 28.4k | Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); |
190 | 28.4k | while (Decl->getFriendObjectKind()) { |
191 | 0 | Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); |
192 | 0 | assert(Decl && "all declarations of template are friends"); |
193 | 0 | } |
194 | 28.4k | return TemplateName(Decl); |
195 | 28.9k | } |
196 | | |
197 | 21.5M | TemplateNameDependence TemplateName::getDependence() const { |
198 | 21.5M | auto D = TemplateNameDependence::None; |
199 | 21.5M | switch (getKind()) { |
200 | 221k | case TemplateName::NameKind::QualifiedTemplate: |
201 | 221k | D |= toTemplateNameDependence( |
202 | 221k | getAsQualifiedTemplateName()->getQualifier()->getDependence()); |
203 | 221k | break; |
204 | 1.13k | case TemplateName::NameKind::DependentTemplate: |
205 | 1.13k | D |= toTemplateNameDependence( |
206 | 1.13k | getAsDependentTemplateName()->getQualifier()->getDependence()); |
207 | 1.13k | break; |
208 | 8 | case TemplateName::NameKind::SubstTemplateTemplateParmPack: |
209 | 8 | D |= TemplateNameDependence::UnexpandedPack; |
210 | 8 | break; |
211 | 0 | case TemplateName::NameKind::OverloadedTemplate: |
212 | 0 | llvm_unreachable("overloaded templates shouldn't survive to here."); |
213 | 21.3M | default: |
214 | 21.3M | break; |
215 | 21.5M | } |
216 | 21.5M | if (TemplateDecl *Template = getAsTemplateDecl()) { |
217 | 21.5M | if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { |
218 | 135k | D |= TemplateNameDependence::DependentInstantiation; |
219 | 135k | if (TTP->isParameterPack()) |
220 | 186 | D |= TemplateNameDependence::UnexpandedPack; |
221 | 135k | } |
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 | 21.5M | if (Template->getDeclContext() && |
227 | 21.5M | Template->getDeclContext()->isDependentContext()) |
228 | 234k | D |= TemplateNameDependence::DependentInstantiation; |
229 | 21.5M | } else { |
230 | 2.08k | D |= TemplateNameDependence::DependentInstantiation; |
231 | 2.08k | } |
232 | 21.5M | return D; |
233 | 21.5M | } |
234 | | |
235 | 7.21M | bool TemplateName::isDependent() const { |
236 | 7.21M | return getDependence() & TemplateNameDependence::Dependent; |
237 | 7.21M | } |
238 | | |
239 | 0 | bool TemplateName::isInstantiationDependent() const { |
240 | 0 | return getDependence() & TemplateNameDependence::Instantiation; |
241 | 0 | } |
242 | | |
243 | 9.39k | bool TemplateName::containsUnexpandedParameterPack() const { |
244 | 9.39k | return getDependence() & TemplateNameDependence::UnexpandedPack; |
245 | 9.39k | } |
246 | | |
247 | | void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, |
248 | 209k | Qualified Qual) const { |
249 | 209k | auto Kind = getKind(); |
250 | 209k | TemplateDecl *Template = nullptr; |
251 | 209k | if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate324 ) { |
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 | 209k | Template = getAsTemplateDecl(); |
262 | 209k | } |
263 | | |
264 | 209k | if (Template) |
265 | 209k | if (Policy.CleanUglifiedParameters && |
266 | 209k | isa<TemplateTemplateParmDecl>(Template)129 && Template->getIdentifier()2 ) |
267 | 2 | OS << Template->getIdentifier()->deuglifiedName(); |
268 | 209k | else if (Qual == Qualified::Fully && |
269 | 209k | getDependence() != |
270 | 1.69k | TemplateNameDependenceScope::DependentInstantiation) |
271 | 1.63k | Template->printQualifiedName(OS, Policy); |
272 | 207k | else |
273 | 207k | OS << *Template; |
274 | 287 | else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { |
275 | 50 | if (Qual == Qualified::Fully && |
276 | 50 | getDependence() != |
277 | 1 | TemplateNameDependenceScope::DependentInstantiation) { |
278 | 1 | QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName( |
279 | 1 | OS, Policy); |
280 | 1 | return; |
281 | 1 | } |
282 | 49 | if (Qual == Qualified::AsWritten) |
283 | 49 | QTN->getQualifier()->print(OS, Policy); |
284 | 49 | if (QTN->hasTemplateKeyword()) |
285 | 19 | OS << "template "; |
286 | 49 | OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl(); |
287 | 237 | } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { |
288 | 12 | if (Qual == Qualified::AsWritten && DTN->getQualifier()) |
289 | 12 | DTN->getQualifier()->print(OS, Policy); |
290 | 12 | OS << "template "; |
291 | | |
292 | 12 | if (DTN->isIdentifier()) |
293 | 0 | OS << DTN->getIdentifier()->getName(); |
294 | 12 | else |
295 | 12 | OS << "operator " << getOperatorSpelling(DTN->getOperator()); |
296 | 225 | } else if (SubstTemplateTemplateParmStorage *subst |
297 | 225 | = getAsSubstTemplateTemplateParm()) { |
298 | 222 | subst->getReplacement().print(OS, Policy, Qual); |
299 | 222 | } else if (SubstTemplateTemplateParmPackStorage *3 SubstPack3 |
300 | 3 | = getAsSubstTemplateTemplateParmPack()) |
301 | 0 | OS << *SubstPack->getParameterPack(); |
302 | 3 | else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { |
303 | 0 | Assumed->getDeclName().print(OS, Policy); |
304 | 3 | } else { |
305 | 3 | assert(getKind() == TemplateName::OverloadedTemplate); |
306 | 0 | OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); |
307 | 3 | (*OTS->begin())->printName(OS); |
308 | 3 | } |
309 | 209k | } |
310 | | |
311 | | const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, |
312 | 563 | TemplateName N) { |
313 | 563 | std::string NameStr; |
314 | 563 | llvm::raw_string_ostream OS(NameStr); |
315 | 563 | LangOptions LO; |
316 | 563 | LO.CPlusPlus = true; |
317 | 563 | LO.Bool = true; |
318 | 563 | OS << '\''; |
319 | 563 | N.print(OS, PrintingPolicy(LO)); |
320 | 563 | OS << '\''; |
321 | 563 | OS.flush(); |
322 | 563 | return DB << NameStr; |
323 | 563 | } |
324 | | |
325 | 102 | void TemplateName::dump(raw_ostream &OS) const { |
326 | 102 | LangOptions LO; // FIXME! |
327 | 102 | LO.CPlusPlus = true; |
328 | 102 | LO.Bool = true; |
329 | 102 | print(OS, PrintingPolicy(LO)); |
330 | 102 | } |
331 | | |
332 | 0 | LLVM_DUMP_METHOD void TemplateName::dump() const { |
333 | 0 | dump(llvm::errs()); |
334 | 0 | } |