/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/DeclTemplate.h" |
17 | | #include "clang/AST/DependenceFlags.h" |
18 | | #include "clang/AST/NestedNameSpecifier.h" |
19 | | #include "clang/AST/PrettyPrinter.h" |
20 | | #include "clang/AST/TemplateBase.h" |
21 | | #include "clang/Basic/Diagnostic.h" |
22 | | #include "clang/Basic/LLVM.h" |
23 | | #include "clang/Basic/LangOptions.h" |
24 | | #include "clang/Basic/OperatorKinds.h" |
25 | | #include "llvm/ADT/ArrayRef.h" |
26 | | #include "llvm/ADT/FoldingSet.h" |
27 | | #include "llvm/Support/Casting.h" |
28 | | #include "llvm/Support/Compiler.h" |
29 | | #include "llvm/Support/raw_ostream.h" |
30 | | #include <cassert> |
31 | | #include <string> |
32 | | |
33 | | using namespace clang; |
34 | | |
35 | | TemplateArgument |
36 | 9 | SubstTemplateTemplateParmPackStorage::getArgumentPack() const { |
37 | 9 | return TemplateArgument(llvm::makeArrayRef(Arguments, size())); |
38 | 9 | } |
39 | | |
40 | 27.7k | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { |
41 | 27.7k | Profile(ID, Parameter, Replacement); |
42 | 27.7k | } |
43 | | |
44 | | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, |
45 | | TemplateTemplateParmDecl *parameter, |
46 | 58.5k | TemplateName replacement) { |
47 | 58.5k | ID.AddPointer(parameter); |
48 | 58.5k | ID.AddPointer(replacement.getAsVoidPointer()); |
49 | 58.5k | } |
50 | | |
51 | | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, |
52 | 0 | ASTContext &Context) { |
53 | 0 | Profile(ID, Context, Parameter, getArgumentPack()); |
54 | 0 | } |
55 | | |
56 | | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, |
57 | | ASTContext &Context, |
58 | | TemplateTemplateParmDecl *Parameter, |
59 | 8 | const TemplateArgument &ArgPack) { |
60 | 8 | ID.AddPointer(Parameter); |
61 | 8 | ArgPack.Profile(ID, Context); |
62 | 8 | } |
63 | | |
64 | 3.09M | TemplateName::TemplateName(void *Ptr) { |
65 | 3.09M | Storage = StorageType::getFromOpaqueValue(Ptr); |
66 | 3.09M | } |
67 | | |
68 | 12.6M | TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} |
69 | | TemplateName::TemplateName(OverloadedTemplateStorage *Storage) |
70 | 120k | : Storage(Storage) {} |
71 | | TemplateName::TemplateName(AssumedTemplateStorage *Storage) |
72 | 673 | : Storage(Storage) {} |
73 | | TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) |
74 | 30.8k | : Storage(Storage) {} |
75 | | TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) |
76 | 8 | : Storage(Storage) {} |
77 | 153k | TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} |
78 | 306k | TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} |
79 | | |
80 | 3.96M | bool TemplateName::isNull() const { return Storage.isNull(); } |
81 | | |
82 | 35.6M | TemplateName::NameKind TemplateName::getKind() const { |
83 | 35.6M | if (Storage.is<TemplateDecl *>()) |
84 | 35.1M | return Template; |
85 | 426k | if (Storage.is<DependentTemplateName *>()) |
86 | 16.4k | return DependentTemplate; |
87 | 409k | if (Storage.is<QualifiedTemplateName *>()) |
88 | 189k | return QualifiedTemplate; |
89 | | |
90 | 220k | UncommonTemplateNameStorage *uncommon |
91 | 220k | = Storage.get<UncommonTemplateNameStorage*>(); |
92 | 220k | if (uncommon->getAsOverloadedStorage()) |
93 | 123k | return OverloadedTemplate; |
94 | 97.3k | if (uncommon->getAsAssumedTemplateName()) |
95 | 52 | return AssumedTemplate; |
96 | 97.2k | if (uncommon->getAsSubstTemplateTemplateParm()) |
97 | 97.2k | return SubstTemplateTemplateParm; |
98 | 22 | return SubstTemplateTemplateParmPack; |
99 | 22 | } |
100 | | |
101 | 61.1M | TemplateDecl *TemplateName::getAsTemplateDecl() const { |
102 | 61.1M | if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) |
103 | 60.5M | return Template; |
104 | | |
105 | 553k | if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) |
106 | 366k | return QTN->getTemplateDecl(); |
107 | | |
108 | 186k | if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) |
109 | 121k | return sub->getReplacement().getAsTemplateDecl(); |
110 | | |
111 | 65.3k | return nullptr; |
112 | 65.3k | } |
113 | | |
114 | 1.21M | OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { |
115 | 1.21M | if (UncommonTemplateNameStorage *Uncommon = |
116 | 123k | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
117 | 123k | return Uncommon->getAsOverloadedStorage(); |
118 | | |
119 | 1.09M | return nullptr; |
120 | 1.09M | } |
121 | | |
122 | 8.10M | AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const { |
123 | 8.10M | if (UncommonTemplateNameStorage *Uncommon = |
124 | 24.8k | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
125 | 24.8k | return Uncommon->getAsAssumedTemplateName(); |
126 | | |
127 | 8.08M | return nullptr; |
128 | 8.08M | } |
129 | | |
130 | | SubstTemplateTemplateParmStorage * |
131 | 6.16M | TemplateName::getAsSubstTemplateTemplateParm() const { |
132 | 6.16M | if (UncommonTemplateNameStorage *uncommon = |
133 | 154k | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
134 | 154k | return uncommon->getAsSubstTemplateTemplateParm(); |
135 | | |
136 | 6.00M | return nullptr; |
137 | 6.00M | } |
138 | | |
139 | | SubstTemplateTemplateParmPackStorage * |
140 | 3.43M | TemplateName::getAsSubstTemplateTemplateParmPack() const { |
141 | 3.43M | if (UncommonTemplateNameStorage *Uncommon = |
142 | 250 | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
143 | 250 | return Uncommon->getAsSubstTemplateTemplateParmPack(); |
144 | | |
145 | 3.43M | return nullptr; |
146 | 3.43M | } |
147 | | |
148 | 17.2M | QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { |
149 | 17.2M | return Storage.dyn_cast<QualifiedTemplateName *>(); |
150 | 17.2M | } |
151 | | |
152 | 41.2M | DependentTemplateName *TemplateName::getAsDependentTemplateName() const { |
153 | 41.2M | return Storage.dyn_cast<DependentTemplateName *>(); |
154 | 41.2M | } |
155 | | |
156 | 29.4k | TemplateName TemplateName::getNameToSubstitute() const { |
157 | 29.4k | TemplateDecl *Decl = getAsTemplateDecl(); |
158 | | |
159 | | // Substituting a dependent template name: preserve it as written. |
160 | 29.4k | if (!Decl) |
161 | 836 | return *this; |
162 | | |
163 | | // If we have a template declaration, use the most recent non-friend |
164 | | // declaration of that template. |
165 | 28.5k | Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); |
166 | 28.5k | while (Decl->getFriendObjectKind()) { |
167 | 0 | Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); |
168 | 0 | assert(Decl && "all declarations of template are friends"); |
169 | 0 | } |
170 | 28.5k | return TemplateName(Decl); |
171 | 28.5k | } |
172 | | |
173 | 15.5M | TemplateNameDependence TemplateName::getDependence() const { |
174 | 15.5M | auto D = TemplateNameDependence::None; |
175 | 15.5M | switch (getKind()) { |
176 | 105k | case TemplateName::NameKind::QualifiedTemplate: |
177 | 105k | D |= toTemplateNameDependence( |
178 | 105k | getAsQualifiedTemplateName()->getQualifier()->getDependence()); |
179 | 105k | break; |
180 | 2.04k | case TemplateName::NameKind::DependentTemplate: |
181 | 2.04k | D |= toTemplateNameDependence( |
182 | 2.04k | getAsDependentTemplateName()->getQualifier()->getDependence()); |
183 | 2.04k | break; |
184 | 8 | case TemplateName::NameKind::SubstTemplateTemplateParmPack: |
185 | 8 | D |= TemplateNameDependence::UnexpandedPack; |
186 | 8 | break; |
187 | 0 | case TemplateName::NameKind::OverloadedTemplate: |
188 | 0 | llvm_unreachable("overloaded templates shouldn't survive to here."); |
189 | 15.4M | default: |
190 | 15.4M | break; |
191 | 15.5M | } |
192 | 15.5M | if (TemplateDecl *Template = getAsTemplateDecl()) { |
193 | 15.5M | if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) { |
194 | 28.3k | D |= TemplateNameDependence::DependentInstantiation; |
195 | 28.3k | if (TTP->isParameterPack()) |
196 | 185 | D |= TemplateNameDependence::UnexpandedPack; |
197 | 28.3k | } |
198 | | // FIXME: Hack, getDeclContext() can be null if Template is still |
199 | | // initializing due to PCH reading, so we check it before using it. |
200 | | // Should probably modify TemplateSpecializationType to allow constructing |
201 | | // it without the isDependent() checking. |
202 | 15.5M | if (Template->getDeclContext() && |
203 | 15.5M | Template->getDeclContext()->isDependentContext()) |
204 | 189k | D |= TemplateNameDependence::DependentInstantiation; |
205 | 3.82k | } else { |
206 | 3.82k | D |= TemplateNameDependence::DependentInstantiation; |
207 | 3.82k | } |
208 | 15.5M | return D; |
209 | 15.5M | } |
210 | | |
211 | 5.40M | bool TemplateName::isDependent() const { |
212 | 5.40M | return getDependence() & TemplateNameDependence::Dependent; |
213 | 5.40M | } |
214 | | |
215 | 0 | bool TemplateName::isInstantiationDependent() const { |
216 | 0 | return getDependence() & TemplateNameDependence::Instantiation; |
217 | 0 | } |
218 | | |
219 | 226 | bool TemplateName::containsUnexpandedParameterPack() const { |
220 | 226 | return getDependence() & TemplateNameDependence::UnexpandedPack; |
221 | 226 | } |
222 | | |
223 | | void |
224 | | TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, |
225 | 113k | bool SuppressNNS) const { |
226 | 113k | if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) |
227 | 113k | OS << *Template; |
228 | 138 | else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { |
229 | 49 | if (!SuppressNNS) |
230 | 49 | QTN->getQualifier()->print(OS, Policy); |
231 | 49 | if (QTN->hasTemplateKeyword()) |
232 | 19 | OS << "template "; |
233 | 49 | OS << *QTN->getDecl(); |
234 | 89 | } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { |
235 | 8 | if (!SuppressNNS && DTN->getQualifier()) |
236 | 8 | DTN->getQualifier()->print(OS, Policy); |
237 | 8 | OS << "template "; |
238 | | |
239 | 8 | if (DTN->isIdentifier()) |
240 | 0 | OS << DTN->getIdentifier()->getName(); |
241 | 8 | else |
242 | 8 | OS << "operator " << getOperatorSpelling(DTN->getOperator()); |
243 | 81 | } else if (SubstTemplateTemplateParmStorage *subst |
244 | 78 | = getAsSubstTemplateTemplateParm()) { |
245 | 78 | subst->getReplacement().print(OS, Policy, SuppressNNS); |
246 | 3 | } else if (SubstTemplateTemplateParmPackStorage *SubstPack |
247 | 0 | = getAsSubstTemplateTemplateParmPack()) |
248 | 0 | OS << *SubstPack->getParameterPack(); |
249 | 3 | else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { |
250 | 0 | Assumed->getDeclName().print(OS, Policy); |
251 | 3 | } else { |
252 | 3 | OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); |
253 | 3 | (*OTS->begin())->printName(OS); |
254 | 3 | } |
255 | 113k | } |
256 | | |
257 | | const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, |
258 | 398 | TemplateName N) { |
259 | 398 | std::string NameStr; |
260 | 398 | llvm::raw_string_ostream OS(NameStr); |
261 | 398 | LangOptions LO; |
262 | 398 | LO.CPlusPlus = true; |
263 | 398 | LO.Bool = true; |
264 | 398 | OS << '\''; |
265 | 398 | N.print(OS, PrintingPolicy(LO)); |
266 | 398 | OS << '\''; |
267 | 398 | OS.flush(); |
268 | 398 | return DB << NameStr; |
269 | 398 | } |
270 | | |
271 | 77 | void TemplateName::dump(raw_ostream &OS) const { |
272 | 77 | LangOptions LO; // FIXME! |
273 | 77 | LO.CPlusPlus = true; |
274 | 77 | LO.Bool = true; |
275 | 77 | print(OS, PrintingPolicy(LO)); |
276 | 77 | } |
277 | | |
278 | 0 | LLVM_DUMP_METHOD void TemplateName::dump() const { |
279 | 0 | dump(llvm::errs()); |
280 | 0 | } |