File: | build/source/clang/lib/Sema/SemaTemplateVariadic.cpp |
Warning: | line 710, column 11 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/ | ||||||||||||
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 | // This file implements semantic analysis for C++0x variadic templates. | ||||||||||||
9 | //===----------------------------------------------------------------------===/ | ||||||||||||
10 | |||||||||||||
11 | #include "clang/Sema/Sema.h" | ||||||||||||
12 | #include "TypeLocBuilder.h" | ||||||||||||
13 | #include "clang/AST/Expr.h" | ||||||||||||
14 | #include "clang/AST/RecursiveASTVisitor.h" | ||||||||||||
15 | #include "clang/AST/TypeLoc.h" | ||||||||||||
16 | #include "clang/Sema/Lookup.h" | ||||||||||||
17 | #include "clang/Sema/ParsedTemplate.h" | ||||||||||||
18 | #include "clang/Sema/ScopeInfo.h" | ||||||||||||
19 | #include "clang/Sema/SemaInternal.h" | ||||||||||||
20 | #include "clang/Sema/Template.h" | ||||||||||||
21 | #include <optional> | ||||||||||||
22 | |||||||||||||
23 | using namespace clang; | ||||||||||||
24 | |||||||||||||
25 | //---------------------------------------------------------------------------- | ||||||||||||
26 | // Visitor that collects unexpanded parameter packs | ||||||||||||
27 | //---------------------------------------------------------------------------- | ||||||||||||
28 | |||||||||||||
29 | namespace { | ||||||||||||
30 | /// A class that collects unexpanded parameter packs. | ||||||||||||
31 | class CollectUnexpandedParameterPacksVisitor : | ||||||||||||
32 | public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> | ||||||||||||
33 | { | ||||||||||||
34 | typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> | ||||||||||||
35 | inherited; | ||||||||||||
36 | |||||||||||||
37 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded; | ||||||||||||
38 | |||||||||||||
39 | bool InLambda = false; | ||||||||||||
40 | unsigned DepthLimit = (unsigned)-1; | ||||||||||||
41 | |||||||||||||
42 | void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) { | ||||||||||||
43 | if (auto *VD = dyn_cast<VarDecl>(ND)) { | ||||||||||||
44 | // For now, the only problematic case is a generic lambda's templated | ||||||||||||
45 | // call operator, so we don't need to look for all the other ways we | ||||||||||||
46 | // could have reached a dependent parameter pack. | ||||||||||||
47 | auto *FD = dyn_cast<FunctionDecl>(VD->getDeclContext()); | ||||||||||||
48 | auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr; | ||||||||||||
49 | if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit) | ||||||||||||
50 | return; | ||||||||||||
51 | } else if (getDepthAndIndex(ND).first >= DepthLimit) | ||||||||||||
52 | return; | ||||||||||||
53 | |||||||||||||
54 | Unexpanded.push_back({ND, Loc}); | ||||||||||||
55 | } | ||||||||||||
56 | void addUnexpanded(const TemplateTypeParmType *T, | ||||||||||||
57 | SourceLocation Loc = SourceLocation()) { | ||||||||||||
58 | if (T->getDepth() < DepthLimit) | ||||||||||||
59 | Unexpanded.push_back({T, Loc}); | ||||||||||||
60 | } | ||||||||||||
61 | |||||||||||||
62 | public: | ||||||||||||
63 | explicit CollectUnexpandedParameterPacksVisitor( | ||||||||||||
64 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) | ||||||||||||
65 | : Unexpanded(Unexpanded) {} | ||||||||||||
66 | |||||||||||||
67 | bool shouldWalkTypesOfTypeLocs() const { return false; } | ||||||||||||
68 | |||||||||||||
69 | //------------------------------------------------------------------------ | ||||||||||||
70 | // Recording occurrences of (unexpanded) parameter packs. | ||||||||||||
71 | //------------------------------------------------------------------------ | ||||||||||||
72 | |||||||||||||
73 | /// Record occurrences of template type parameter packs. | ||||||||||||
74 | bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { | ||||||||||||
75 | if (TL.getTypePtr()->isParameterPack()) | ||||||||||||
76 | addUnexpanded(TL.getTypePtr(), TL.getNameLoc()); | ||||||||||||
77 | return true; | ||||||||||||
78 | } | ||||||||||||
79 | |||||||||||||
80 | /// Record occurrences of template type parameter packs | ||||||||||||
81 | /// when we don't have proper source-location information for | ||||||||||||
82 | /// them. | ||||||||||||
83 | /// | ||||||||||||
84 | /// Ideally, this routine would never be used. | ||||||||||||
85 | bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { | ||||||||||||
86 | if (T->isParameterPack()) | ||||||||||||
87 | addUnexpanded(T); | ||||||||||||
88 | |||||||||||||
89 | return true; | ||||||||||||
90 | } | ||||||||||||
91 | |||||||||||||
92 | /// Record occurrences of function and non-type template | ||||||||||||
93 | /// parameter packs in an expression. | ||||||||||||
94 | bool VisitDeclRefExpr(DeclRefExpr *E) { | ||||||||||||
95 | if (E->getDecl()->isParameterPack()) | ||||||||||||
96 | addUnexpanded(E->getDecl(), E->getLocation()); | ||||||||||||
97 | |||||||||||||
98 | return true; | ||||||||||||
99 | } | ||||||||||||
100 | |||||||||||||
101 | /// Record occurrences of template template parameter packs. | ||||||||||||
102 | bool TraverseTemplateName(TemplateName Template) { | ||||||||||||
103 | if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>( | ||||||||||||
104 | Template.getAsTemplateDecl())) { | ||||||||||||
105 | if (TTP->isParameterPack()) | ||||||||||||
106 | addUnexpanded(TTP); | ||||||||||||
107 | } | ||||||||||||
108 | |||||||||||||
109 | return inherited::TraverseTemplateName(Template); | ||||||||||||
110 | } | ||||||||||||
111 | |||||||||||||
112 | /// Suppress traversal into Objective-C container literal | ||||||||||||
113 | /// elements that are pack expansions. | ||||||||||||
114 | bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { | ||||||||||||
115 | if (!E->containsUnexpandedParameterPack()) | ||||||||||||
116 | return true; | ||||||||||||
117 | |||||||||||||
118 | for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { | ||||||||||||
119 | ObjCDictionaryElement Element = E->getKeyValueElement(I); | ||||||||||||
120 | if (Element.isPackExpansion()) | ||||||||||||
121 | continue; | ||||||||||||
122 | |||||||||||||
123 | TraverseStmt(Element.Key); | ||||||||||||
124 | TraverseStmt(Element.Value); | ||||||||||||
125 | } | ||||||||||||
126 | return true; | ||||||||||||
127 | } | ||||||||||||
128 | //------------------------------------------------------------------------ | ||||||||||||
129 | // Pruning the search for unexpanded parameter packs. | ||||||||||||
130 | //------------------------------------------------------------------------ | ||||||||||||
131 | |||||||||||||
132 | /// Suppress traversal into statements and expressions that | ||||||||||||
133 | /// do not contain unexpanded parameter packs. | ||||||||||||
134 | bool TraverseStmt(Stmt *S) { | ||||||||||||
135 | Expr *E = dyn_cast_or_null<Expr>(S); | ||||||||||||
136 | if ((E && E->containsUnexpandedParameterPack()) || InLambda) | ||||||||||||
137 | return inherited::TraverseStmt(S); | ||||||||||||
138 | |||||||||||||
139 | return true; | ||||||||||||
140 | } | ||||||||||||
141 | |||||||||||||
142 | /// Suppress traversal into types that do not contain | ||||||||||||
143 | /// unexpanded parameter packs. | ||||||||||||
144 | bool TraverseType(QualType T) { | ||||||||||||
145 | if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda) | ||||||||||||
146 | return inherited::TraverseType(T); | ||||||||||||
147 | |||||||||||||
148 | return true; | ||||||||||||
149 | } | ||||||||||||
150 | |||||||||||||
151 | /// Suppress traversal into types with location information | ||||||||||||
152 | /// that do not contain unexpanded parameter packs. | ||||||||||||
153 | bool TraverseTypeLoc(TypeLoc TL) { | ||||||||||||
154 | if ((!TL.getType().isNull() && | ||||||||||||
155 | TL.getType()->containsUnexpandedParameterPack()) || | ||||||||||||
156 | InLambda) | ||||||||||||
157 | return inherited::TraverseTypeLoc(TL); | ||||||||||||
158 | |||||||||||||
159 | return true; | ||||||||||||
160 | } | ||||||||||||
161 | |||||||||||||
162 | /// Suppress traversal of parameter packs. | ||||||||||||
163 | bool TraverseDecl(Decl *D) { | ||||||||||||
164 | // A function parameter pack is a pack expansion, so cannot contain | ||||||||||||
165 | // an unexpanded parameter pack. Likewise for a template parameter | ||||||||||||
166 | // pack that contains any references to other packs. | ||||||||||||
167 | if (D && D->isParameterPack()) | ||||||||||||
168 | return true; | ||||||||||||
169 | |||||||||||||
170 | return inherited::TraverseDecl(D); | ||||||||||||
171 | } | ||||||||||||
172 | |||||||||||||
173 | /// Suppress traversal of pack-expanded attributes. | ||||||||||||
174 | bool TraverseAttr(Attr *A) { | ||||||||||||
175 | if (A->isPackExpansion()) | ||||||||||||
176 | return true; | ||||||||||||
177 | |||||||||||||
178 | return inherited::TraverseAttr(A); | ||||||||||||
179 | } | ||||||||||||
180 | |||||||||||||
181 | /// Suppress traversal of pack expansion expressions and types. | ||||||||||||
182 | ///@{ | ||||||||||||
183 | bool TraversePackExpansionType(PackExpansionType *T) { return true; } | ||||||||||||
184 | bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; } | ||||||||||||
185 | bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; } | ||||||||||||
186 | bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; } | ||||||||||||
187 | |||||||||||||
188 | ///@} | ||||||||||||
189 | |||||||||||||
190 | /// Suppress traversal of using-declaration pack expansion. | ||||||||||||
191 | bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { | ||||||||||||
192 | if (D->isPackExpansion()) | ||||||||||||
193 | return true; | ||||||||||||
194 | |||||||||||||
195 | return inherited::TraverseUnresolvedUsingValueDecl(D); | ||||||||||||
196 | } | ||||||||||||
197 | |||||||||||||
198 | /// Suppress traversal of using-declaration pack expansion. | ||||||||||||
199 | bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { | ||||||||||||
200 | if (D->isPackExpansion()) | ||||||||||||
201 | return true; | ||||||||||||
202 | |||||||||||||
203 | return inherited::TraverseUnresolvedUsingTypenameDecl(D); | ||||||||||||
204 | } | ||||||||||||
205 | |||||||||||||
206 | /// Suppress traversal of template argument pack expansions. | ||||||||||||
207 | bool TraverseTemplateArgument(const TemplateArgument &Arg) { | ||||||||||||
208 | if (Arg.isPackExpansion()) | ||||||||||||
209 | return true; | ||||||||||||
210 | |||||||||||||
211 | return inherited::TraverseTemplateArgument(Arg); | ||||||||||||
212 | } | ||||||||||||
213 | |||||||||||||
214 | /// Suppress traversal of template argument pack expansions. | ||||||||||||
215 | bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { | ||||||||||||
216 | if (ArgLoc.getArgument().isPackExpansion()) | ||||||||||||
217 | return true; | ||||||||||||
218 | |||||||||||||
219 | return inherited::TraverseTemplateArgumentLoc(ArgLoc); | ||||||||||||
220 | } | ||||||||||||
221 | |||||||||||||
222 | /// Suppress traversal of base specifier pack expansions. | ||||||||||||
223 | bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) { | ||||||||||||
224 | if (Base.isPackExpansion()) | ||||||||||||
225 | return true; | ||||||||||||
226 | |||||||||||||
227 | return inherited::TraverseCXXBaseSpecifier(Base); | ||||||||||||
228 | } | ||||||||||||
229 | |||||||||||||
230 | /// Suppress traversal of mem-initializer pack expansions. | ||||||||||||
231 | bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { | ||||||||||||
232 | if (Init->isPackExpansion()) | ||||||||||||
233 | return true; | ||||||||||||
234 | |||||||||||||
235 | return inherited::TraverseConstructorInitializer(Init); | ||||||||||||
236 | } | ||||||||||||
237 | |||||||||||||
238 | /// Note whether we're traversing a lambda containing an unexpanded | ||||||||||||
239 | /// parameter pack. In this case, the unexpanded pack can occur anywhere, | ||||||||||||
240 | /// including all the places where we normally wouldn't look. Within a | ||||||||||||
241 | /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit | ||||||||||||
242 | /// outside an expression. | ||||||||||||
243 | bool TraverseLambdaExpr(LambdaExpr *Lambda) { | ||||||||||||
244 | // The ContainsUnexpandedParameterPack bit on a lambda is always correct, | ||||||||||||
245 | // even if it's contained within another lambda. | ||||||||||||
246 | if (!Lambda->containsUnexpandedParameterPack()) | ||||||||||||
247 | return true; | ||||||||||||
248 | |||||||||||||
249 | bool WasInLambda = InLambda; | ||||||||||||
250 | unsigned OldDepthLimit = DepthLimit; | ||||||||||||
251 | |||||||||||||
252 | InLambda = true; | ||||||||||||
253 | if (auto *TPL = Lambda->getTemplateParameterList()) | ||||||||||||
254 | DepthLimit = TPL->getDepth(); | ||||||||||||
255 | |||||||||||||
256 | inherited::TraverseLambdaExpr(Lambda); | ||||||||||||
257 | |||||||||||||
258 | InLambda = WasInLambda; | ||||||||||||
259 | DepthLimit = OldDepthLimit; | ||||||||||||
260 | return true; | ||||||||||||
261 | } | ||||||||||||
262 | |||||||||||||
263 | /// Suppress traversal within pack expansions in lambda captures. | ||||||||||||
264 | bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C, | ||||||||||||
265 | Expr *Init) { | ||||||||||||
266 | if (C->isPackExpansion()) | ||||||||||||
267 | return true; | ||||||||||||
268 | |||||||||||||
269 | return inherited::TraverseLambdaCapture(Lambda, C, Init); | ||||||||||||
270 | } | ||||||||||||
271 | }; | ||||||||||||
272 | } | ||||||||||||
273 | |||||||||||||
274 | /// Determine whether it's possible for an unexpanded parameter pack to | ||||||||||||
275 | /// be valid in this location. This only happens when we're in a declaration | ||||||||||||
276 | /// that is nested within an expression that could be expanded, such as a | ||||||||||||
277 | /// lambda-expression within a function call. | ||||||||||||
278 | /// | ||||||||||||
279 | /// This is conservatively correct, but may claim that some unexpanded packs are | ||||||||||||
280 | /// permitted when they are not. | ||||||||||||
281 | bool Sema::isUnexpandedParameterPackPermitted() { | ||||||||||||
282 | for (auto *SI : FunctionScopes) | ||||||||||||
283 | if (isa<sema::LambdaScopeInfo>(SI)) | ||||||||||||
284 | return true; | ||||||||||||
285 | return false; | ||||||||||||
286 | } | ||||||||||||
287 | |||||||||||||
288 | /// Diagnose all of the unexpanded parameter packs in the given | ||||||||||||
289 | /// vector. | ||||||||||||
290 | bool | ||||||||||||
291 | Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, | ||||||||||||
292 | UnexpandedParameterPackContext UPPC, | ||||||||||||
293 | ArrayRef<UnexpandedParameterPack> Unexpanded) { | ||||||||||||
294 | if (Unexpanded.empty()) | ||||||||||||
295 | return false; | ||||||||||||
296 | |||||||||||||
297 | // If we are within a lambda expression and referencing a pack that is not | ||||||||||||
298 | // declared within the lambda itself, that lambda contains an unexpanded | ||||||||||||
299 | // parameter pack, and we are done. | ||||||||||||
300 | // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it | ||||||||||||
301 | // later. | ||||||||||||
302 | SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences; | ||||||||||||
303 | if (auto *LSI = getEnclosingLambda()) { | ||||||||||||
304 | for (auto &Pack : Unexpanded) { | ||||||||||||
305 | auto DeclaresThisPack = [&](NamedDecl *LocalPack) { | ||||||||||||
306 | if (auto *TTPT = Pack.first.dyn_cast<const TemplateTypeParmType *>()) { | ||||||||||||
307 | auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack); | ||||||||||||
308 | return TTPD && TTPD->getTypeForDecl() == TTPT; | ||||||||||||
309 | } | ||||||||||||
310 | return declaresSameEntity(Pack.first.get<NamedDecl *>(), LocalPack); | ||||||||||||
311 | }; | ||||||||||||
312 | if (llvm::any_of(LSI->LocalPacks, DeclaresThisPack)) | ||||||||||||
313 | LambdaParamPackReferences.push_back(Pack); | ||||||||||||
314 | } | ||||||||||||
315 | |||||||||||||
316 | if (LambdaParamPackReferences.empty()) { | ||||||||||||
317 | // Construct in lambda only references packs declared outside the lambda. | ||||||||||||
318 | // That's OK for now, but the lambda itself is considered to contain an | ||||||||||||
319 | // unexpanded pack in this case, which will require expansion outside the | ||||||||||||
320 | // lambda. | ||||||||||||
321 | |||||||||||||
322 | // We do not permit pack expansion that would duplicate a statement | ||||||||||||
323 | // expression, not even within a lambda. | ||||||||||||
324 | // FIXME: We could probably support this for statement expressions that | ||||||||||||
325 | // do not contain labels. | ||||||||||||
326 | // FIXME: This is insufficient to detect this problem; consider | ||||||||||||
327 | // f( ({ bad: 0; }) + pack ... ); | ||||||||||||
328 | bool EnclosingStmtExpr = false; | ||||||||||||
329 | for (unsigned N = FunctionScopes.size(); N; --N) { | ||||||||||||
330 | sema::FunctionScopeInfo *Func = FunctionScopes[N-1]; | ||||||||||||
331 | if (llvm::any_of( | ||||||||||||
332 | Func->CompoundScopes, | ||||||||||||
333 | [](sema::CompoundScopeInfo &CSI) { return CSI.IsStmtExpr; })) { | ||||||||||||
334 | EnclosingStmtExpr = true; | ||||||||||||
335 | break; | ||||||||||||
336 | } | ||||||||||||
337 | // Coumpound-statements outside the lambda are OK for now; we'll check | ||||||||||||
338 | // for those when we finish handling the lambda. | ||||||||||||
339 | if (Func == LSI) | ||||||||||||
340 | break; | ||||||||||||
341 | } | ||||||||||||
342 | |||||||||||||
343 | if (!EnclosingStmtExpr) { | ||||||||||||
344 | LSI->ContainsUnexpandedParameterPack = true; | ||||||||||||
345 | return false; | ||||||||||||
346 | } | ||||||||||||
347 | } else { | ||||||||||||
348 | Unexpanded = LambdaParamPackReferences; | ||||||||||||
349 | } | ||||||||||||
350 | } | ||||||||||||
351 | |||||||||||||
352 | SmallVector<SourceLocation, 4> Locations; | ||||||||||||
353 | SmallVector<IdentifierInfo *, 4> Names; | ||||||||||||
354 | llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown; | ||||||||||||
355 | |||||||||||||
356 | for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { | ||||||||||||
357 | IdentifierInfo *Name = nullptr; | ||||||||||||
358 | if (const TemplateTypeParmType *TTP | ||||||||||||
359 | = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) | ||||||||||||
360 | Name = TTP->getIdentifier(); | ||||||||||||
361 | else | ||||||||||||
362 | Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier(); | ||||||||||||
363 | |||||||||||||
364 | if (Name && NamesKnown.insert(Name).second) | ||||||||||||
365 | Names.push_back(Name); | ||||||||||||
366 | |||||||||||||
367 | if (Unexpanded[I].second.isValid()) | ||||||||||||
368 | Locations.push_back(Unexpanded[I].second); | ||||||||||||
369 | } | ||||||||||||
370 | |||||||||||||
371 | auto DB = Diag(Loc, diag::err_unexpanded_parameter_pack) | ||||||||||||
372 | << (int)UPPC << (int)Names.size(); | ||||||||||||
373 | for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I) | ||||||||||||
374 | DB << Names[I]; | ||||||||||||
375 | |||||||||||||
376 | for (unsigned I = 0, N = Locations.size(); I != N; ++I) | ||||||||||||
377 | DB << SourceRange(Locations[I]); | ||||||||||||
378 | return true; | ||||||||||||
379 | } | ||||||||||||
380 | |||||||||||||
381 | bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, | ||||||||||||
382 | TypeSourceInfo *T, | ||||||||||||
383 | UnexpandedParameterPackContext UPPC) { | ||||||||||||
384 | // C++0x [temp.variadic]p5: | ||||||||||||
385 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||||||
386 | // ill-formed. | ||||||||||||
387 | if (!T->getType()->containsUnexpandedParameterPack()) | ||||||||||||
388 | return false; | ||||||||||||
389 | |||||||||||||
390 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
391 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc( | ||||||||||||
392 | T->getTypeLoc()); | ||||||||||||
393 | assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs")(static_cast <bool> (!Unexpanded.empty() && "Unable to find unexpanded parameter packs" ) ? void (0) : __assert_fail ("!Unexpanded.empty() && \"Unable to find unexpanded parameter packs\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 393, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
394 | return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); | ||||||||||||
395 | } | ||||||||||||
396 | |||||||||||||
397 | bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, | ||||||||||||
398 | UnexpandedParameterPackContext UPPC) { | ||||||||||||
399 | // C++0x [temp.variadic]p5: | ||||||||||||
400 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||||||
401 | // ill-formed. | ||||||||||||
402 | if (!E->containsUnexpandedParameterPack()) | ||||||||||||
403 | return false; | ||||||||||||
404 | |||||||||||||
405 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
406 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); | ||||||||||||
407 | assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs")(static_cast <bool> (!Unexpanded.empty() && "Unable to find unexpanded parameter packs" ) ? void (0) : __assert_fail ("!Unexpanded.empty() && \"Unable to find unexpanded parameter packs\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 407, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
408 | return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded); | ||||||||||||
409 | } | ||||||||||||
410 | |||||||||||||
411 | bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) { | ||||||||||||
412 | if (!RE->containsUnexpandedParameterPack()) | ||||||||||||
413 | return false; | ||||||||||||
414 | |||||||||||||
415 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
416 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(RE); | ||||||||||||
417 | assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs")(static_cast <bool> (!Unexpanded.empty() && "Unable to find unexpanded parameter packs" ) ? void (0) : __assert_fail ("!Unexpanded.empty() && \"Unable to find unexpanded parameter packs\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 417, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
418 | |||||||||||||
419 | // We only care about unexpanded references to the RequiresExpr's own | ||||||||||||
420 | // parameter packs. | ||||||||||||
421 | auto Parms = RE->getLocalParameters(); | ||||||||||||
422 | llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end()); | ||||||||||||
423 | SmallVector<UnexpandedParameterPack, 2> UnexpandedParms; | ||||||||||||
424 | for (auto Parm : Unexpanded) | ||||||||||||
425 | if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl *>())) | ||||||||||||
426 | UnexpandedParms.push_back(Parm); | ||||||||||||
427 | if (UnexpandedParms.empty()) | ||||||||||||
428 | return false; | ||||||||||||
429 | |||||||||||||
430 | return DiagnoseUnexpandedParameterPacks(RE->getBeginLoc(), UPPC_Requirement, | ||||||||||||
431 | UnexpandedParms); | ||||||||||||
432 | } | ||||||||||||
433 | |||||||||||||
434 | bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, | ||||||||||||
435 | UnexpandedParameterPackContext UPPC) { | ||||||||||||
436 | // C++0x [temp.variadic]p5: | ||||||||||||
437 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||||||
438 | // ill-formed. | ||||||||||||
439 | if (!SS.getScopeRep() || | ||||||||||||
440 | !SS.getScopeRep()->containsUnexpandedParameterPack()) | ||||||||||||
441 | return false; | ||||||||||||
442 | |||||||||||||
443 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
444 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
445 | .TraverseNestedNameSpecifier(SS.getScopeRep()); | ||||||||||||
446 | assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs")(static_cast <bool> (!Unexpanded.empty() && "Unable to find unexpanded parameter packs" ) ? void (0) : __assert_fail ("!Unexpanded.empty() && \"Unable to find unexpanded parameter packs\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 446, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
447 | return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), | ||||||||||||
448 | UPPC, Unexpanded); | ||||||||||||
449 | } | ||||||||||||
450 | |||||||||||||
451 | bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, | ||||||||||||
452 | UnexpandedParameterPackContext UPPC) { | ||||||||||||
453 | // C++0x [temp.variadic]p5: | ||||||||||||
454 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||||||
455 | // ill-formed. | ||||||||||||
456 | switch (NameInfo.getName().getNameKind()) { | ||||||||||||
457 | case DeclarationName::Identifier: | ||||||||||||
458 | case DeclarationName::ObjCZeroArgSelector: | ||||||||||||
459 | case DeclarationName::ObjCOneArgSelector: | ||||||||||||
460 | case DeclarationName::ObjCMultiArgSelector: | ||||||||||||
461 | case DeclarationName::CXXOperatorName: | ||||||||||||
462 | case DeclarationName::CXXLiteralOperatorName: | ||||||||||||
463 | case DeclarationName::CXXUsingDirective: | ||||||||||||
464 | case DeclarationName::CXXDeductionGuideName: | ||||||||||||
465 | return false; | ||||||||||||
466 | |||||||||||||
467 | case DeclarationName::CXXConstructorName: | ||||||||||||
468 | case DeclarationName::CXXDestructorName: | ||||||||||||
469 | case DeclarationName::CXXConversionFunctionName: | ||||||||||||
470 | // FIXME: We shouldn't need this null check! | ||||||||||||
471 | if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) | ||||||||||||
472 | return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC); | ||||||||||||
473 | |||||||||||||
474 | if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack()) | ||||||||||||
475 | return false; | ||||||||||||
476 | |||||||||||||
477 | break; | ||||||||||||
478 | } | ||||||||||||
479 | |||||||||||||
480 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
481 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
482 | .TraverseType(NameInfo.getName().getCXXNameType()); | ||||||||||||
483 | assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs")(static_cast <bool> (!Unexpanded.empty() && "Unable to find unexpanded parameter packs" ) ? void (0) : __assert_fail ("!Unexpanded.empty() && \"Unable to find unexpanded parameter packs\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 483, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
484 | return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded); | ||||||||||||
485 | } | ||||||||||||
486 | |||||||||||||
487 | bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, | ||||||||||||
488 | TemplateName Template, | ||||||||||||
489 | UnexpandedParameterPackContext UPPC) { | ||||||||||||
490 | |||||||||||||
491 | if (Template.isNull() || !Template.containsUnexpandedParameterPack()) | ||||||||||||
492 | return false; | ||||||||||||
493 | |||||||||||||
494 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
495 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
496 | .TraverseTemplateName(Template); | ||||||||||||
497 | assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs")(static_cast <bool> (!Unexpanded.empty() && "Unable to find unexpanded parameter packs" ) ? void (0) : __assert_fail ("!Unexpanded.empty() && \"Unable to find unexpanded parameter packs\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 497, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
498 | return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); | ||||||||||||
499 | } | ||||||||||||
500 | |||||||||||||
501 | bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, | ||||||||||||
502 | UnexpandedParameterPackContext UPPC) { | ||||||||||||
503 | if (Arg.getArgument().isNull() || | ||||||||||||
504 | !Arg.getArgument().containsUnexpandedParameterPack()) | ||||||||||||
505 | return false; | ||||||||||||
506 | |||||||||||||
507 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
508 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
509 | .TraverseTemplateArgumentLoc(Arg); | ||||||||||||
510 | assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs")(static_cast <bool> (!Unexpanded.empty() && "Unable to find unexpanded parameter packs" ) ? void (0) : __assert_fail ("!Unexpanded.empty() && \"Unable to find unexpanded parameter packs\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 510, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
511 | return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded); | ||||||||||||
512 | } | ||||||||||||
513 | |||||||||||||
514 | void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg, | ||||||||||||
515 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||||||
516 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
517 | .TraverseTemplateArgument(Arg); | ||||||||||||
518 | } | ||||||||||||
519 | |||||||||||||
520 | void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg, | ||||||||||||
521 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||||||
522 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
523 | .TraverseTemplateArgumentLoc(Arg); | ||||||||||||
524 | } | ||||||||||||
525 | |||||||||||||
526 | void Sema::collectUnexpandedParameterPacks(QualType T, | ||||||||||||
527 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||||||
528 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T); | ||||||||||||
529 | } | ||||||||||||
530 | |||||||||||||
531 | void Sema::collectUnexpandedParameterPacks(TypeLoc TL, | ||||||||||||
532 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||||||
533 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL); | ||||||||||||
534 | } | ||||||||||||
535 | |||||||||||||
536 | void Sema::collectUnexpandedParameterPacks( | ||||||||||||
537 | NestedNameSpecifierLoc NNS, | ||||||||||||
538 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||||||
539 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
540 | .TraverseNestedNameSpecifierLoc(NNS); | ||||||||||||
541 | } | ||||||||||||
542 | |||||||||||||
543 | void Sema::collectUnexpandedParameterPacks( | ||||||||||||
544 | const DeclarationNameInfo &NameInfo, | ||||||||||||
545 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||||||
546 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||||||
547 | .TraverseDeclarationNameInfo(NameInfo); | ||||||||||||
548 | } | ||||||||||||
549 | |||||||||||||
550 | |||||||||||||
551 | ParsedTemplateArgument | ||||||||||||
552 | Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, | ||||||||||||
553 | SourceLocation EllipsisLoc) { | ||||||||||||
554 | if (Arg.isInvalid()) | ||||||||||||
555 | return Arg; | ||||||||||||
556 | |||||||||||||
557 | switch (Arg.getKind()) { | ||||||||||||
558 | case ParsedTemplateArgument::Type: { | ||||||||||||
559 | TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc); | ||||||||||||
560 | if (Result.isInvalid()) | ||||||||||||
561 | return ParsedTemplateArgument(); | ||||||||||||
562 | |||||||||||||
563 | return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), | ||||||||||||
564 | Arg.getLocation()); | ||||||||||||
565 | } | ||||||||||||
566 | |||||||||||||
567 | case ParsedTemplateArgument::NonType: { | ||||||||||||
568 | ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc); | ||||||||||||
569 | if (Result.isInvalid()) | ||||||||||||
570 | return ParsedTemplateArgument(); | ||||||||||||
571 | |||||||||||||
572 | return ParsedTemplateArgument(Arg.getKind(), Result.get(), | ||||||||||||
573 | Arg.getLocation()); | ||||||||||||
574 | } | ||||||||||||
575 | |||||||||||||
576 | case ParsedTemplateArgument::Template: | ||||||||||||
577 | if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) { | ||||||||||||
578 | SourceRange R(Arg.getLocation()); | ||||||||||||
579 | if (Arg.getScopeSpec().isValid()) | ||||||||||||
580 | R.setBegin(Arg.getScopeSpec().getBeginLoc()); | ||||||||||||
581 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | ||||||||||||
582 | << R; | ||||||||||||
583 | return ParsedTemplateArgument(); | ||||||||||||
584 | } | ||||||||||||
585 | |||||||||||||
586 | return Arg.getTemplatePackExpansion(EllipsisLoc); | ||||||||||||
587 | } | ||||||||||||
588 | llvm_unreachable("Unhandled template argument kind?")::llvm::llvm_unreachable_internal("Unhandled template argument kind?" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 588); | ||||||||||||
589 | } | ||||||||||||
590 | |||||||||||||
591 | TypeResult Sema::ActOnPackExpansion(ParsedType Type, | ||||||||||||
592 | SourceLocation EllipsisLoc) { | ||||||||||||
593 | TypeSourceInfo *TSInfo; | ||||||||||||
594 | GetTypeFromParser(Type, &TSInfo); | ||||||||||||
595 | if (!TSInfo) | ||||||||||||
596 | return true; | ||||||||||||
597 | |||||||||||||
598 | TypeSourceInfo *TSResult = | ||||||||||||
599 | CheckPackExpansion(TSInfo, EllipsisLoc, std::nullopt); | ||||||||||||
600 | if (!TSResult) | ||||||||||||
601 | return true; | ||||||||||||
602 | |||||||||||||
603 | return CreateParsedType(TSResult->getType(), TSResult); | ||||||||||||
604 | } | ||||||||||||
605 | |||||||||||||
606 | TypeSourceInfo * | ||||||||||||
607 | Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, | ||||||||||||
608 | std::optional<unsigned> NumExpansions) { | ||||||||||||
609 | // Create the pack expansion type and source-location information. | ||||||||||||
610 | QualType Result = CheckPackExpansion(Pattern->getType(), | ||||||||||||
611 | Pattern->getTypeLoc().getSourceRange(), | ||||||||||||
612 | EllipsisLoc, NumExpansions); | ||||||||||||
613 | if (Result.isNull()) | ||||||||||||
614 | return nullptr; | ||||||||||||
615 | |||||||||||||
616 | TypeLocBuilder TLB; | ||||||||||||
617 | TLB.pushFullCopy(Pattern->getTypeLoc()); | ||||||||||||
618 | PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result); | ||||||||||||
619 | TL.setEllipsisLoc(EllipsisLoc); | ||||||||||||
620 | |||||||||||||
621 | return TLB.getTypeSourceInfo(Context, Result); | ||||||||||||
622 | } | ||||||||||||
623 | |||||||||||||
624 | QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange, | ||||||||||||
625 | SourceLocation EllipsisLoc, | ||||||||||||
626 | std::optional<unsigned> NumExpansions) { | ||||||||||||
627 | // C++11 [temp.variadic]p5: | ||||||||||||
628 | // The pattern of a pack expansion shall name one or more | ||||||||||||
629 | // parameter packs that are not expanded by a nested pack | ||||||||||||
630 | // expansion. | ||||||||||||
631 | // | ||||||||||||
632 | // A pattern containing a deduced type can't occur "naturally" but arises in | ||||||||||||
633 | // the desugaring of an init-capture pack. | ||||||||||||
634 | if (!Pattern->containsUnexpandedParameterPack() && | ||||||||||||
635 | !Pattern->getContainedDeducedType()) { | ||||||||||||
636 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | ||||||||||||
637 | << PatternRange; | ||||||||||||
638 | return QualType(); | ||||||||||||
639 | } | ||||||||||||
640 | |||||||||||||
641 | return Context.getPackExpansionType(Pattern, NumExpansions, | ||||||||||||
642 | /*ExpectPackInType=*/false); | ||||||||||||
643 | } | ||||||||||||
644 | |||||||||||||
645 | ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { | ||||||||||||
646 | return CheckPackExpansion(Pattern, EllipsisLoc, std::nullopt); | ||||||||||||
647 | } | ||||||||||||
648 | |||||||||||||
649 | ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, | ||||||||||||
650 | std::optional<unsigned> NumExpansions) { | ||||||||||||
651 | if (!Pattern) | ||||||||||||
652 | return ExprError(); | ||||||||||||
653 | |||||||||||||
654 | // C++0x [temp.variadic]p5: | ||||||||||||
655 | // The pattern of a pack expansion shall name one or more | ||||||||||||
656 | // parameter packs that are not expanded by a nested pack | ||||||||||||
657 | // expansion. | ||||||||||||
658 | if (!Pattern->containsUnexpandedParameterPack()) { | ||||||||||||
659 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | ||||||||||||
660 | << Pattern->getSourceRange(); | ||||||||||||
661 | CorrectDelayedTyposInExpr(Pattern); | ||||||||||||
662 | return ExprError(); | ||||||||||||
663 | } | ||||||||||||
664 | |||||||||||||
665 | // Create the pack expansion expression and source-location information. | ||||||||||||
666 | return new (Context) | ||||||||||||
667 | PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions); | ||||||||||||
668 | } | ||||||||||||
669 | |||||||||||||
670 | bool Sema::CheckParameterPacksForExpansion( | ||||||||||||
671 | SourceLocation EllipsisLoc, SourceRange PatternRange, | ||||||||||||
672 | ArrayRef<UnexpandedParameterPack> Unexpanded, | ||||||||||||
673 | const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, | ||||||||||||
674 | bool &RetainExpansion, std::optional<unsigned> &NumExpansions) { | ||||||||||||
675 | ShouldExpand = true; | ||||||||||||
676 | RetainExpansion = false; | ||||||||||||
677 | std::pair<IdentifierInfo *, SourceLocation> FirstPack; | ||||||||||||
678 | bool HaveFirstPack = false; | ||||||||||||
679 | std::optional<unsigned> NumPartialExpansions; | ||||||||||||
680 | SourceLocation PartiallySubstitutedPackLoc; | ||||||||||||
681 | |||||||||||||
682 | for (UnexpandedParameterPack ParmPack : Unexpanded) { | ||||||||||||
| |||||||||||||
683 | // Compute the depth and index for this parameter pack. | ||||||||||||
684 | unsigned Depth = 0, Index = 0; | ||||||||||||
685 | IdentifierInfo *Name; | ||||||||||||
686 | bool IsVarDeclPack = false; | ||||||||||||
687 | |||||||||||||
688 | if (const TemplateTypeParmType *TTP
| ||||||||||||
689 | ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) { | ||||||||||||
690 | Depth = TTP->getDepth(); | ||||||||||||
691 | Index = TTP->getIndex(); | ||||||||||||
692 | Name = TTP->getIdentifier(); | ||||||||||||
693 | } else { | ||||||||||||
694 | NamedDecl *ND = ParmPack.first.get<NamedDecl *>(); | ||||||||||||
695 | if (isa<VarDecl>(ND)) | ||||||||||||
696 | IsVarDeclPack = true; | ||||||||||||
697 | else | ||||||||||||
698 | std::tie(Depth, Index) = getDepthAndIndex(ND); | ||||||||||||
699 | |||||||||||||
700 | Name = ND->getIdentifier(); | ||||||||||||
701 | } | ||||||||||||
702 | |||||||||||||
703 | // Determine the size of this argument pack. | ||||||||||||
704 | unsigned NewPackSize; | ||||||||||||
705 | if (IsVarDeclPack
| ||||||||||||
706 | // Figure out whether we're instantiating to an argument pack or not. | ||||||||||||
707 | typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; | ||||||||||||
708 | |||||||||||||
709 | llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation = | ||||||||||||
710 | CurrentInstantiationScope->findInstantiationOf( | ||||||||||||
| |||||||||||||
711 | ParmPack.first.get<NamedDecl *>()); | ||||||||||||
712 | if (Instantiation->is<DeclArgumentPack *>()) { | ||||||||||||
713 | // We could expand this function parameter pack. | ||||||||||||
714 | NewPackSize = Instantiation->get<DeclArgumentPack *>()->size(); | ||||||||||||
715 | } else { | ||||||||||||
716 | // We can't expand this function parameter pack, so we can't expand | ||||||||||||
717 | // the pack expansion. | ||||||||||||
718 | ShouldExpand = false; | ||||||||||||
719 | continue; | ||||||||||||
720 | } | ||||||||||||
721 | } else { | ||||||||||||
722 | // If we don't have a template argument at this depth/index, then we | ||||||||||||
723 | // cannot expand the pack expansion. Make a note of this, but we still | ||||||||||||
724 | // want to check any parameter packs we *do* have arguments for. | ||||||||||||
725 | if (Depth >= TemplateArgs.getNumLevels() || | ||||||||||||
726 | !TemplateArgs.hasTemplateArgument(Depth, Index)) { | ||||||||||||
727 | ShouldExpand = false; | ||||||||||||
728 | continue; | ||||||||||||
729 | } | ||||||||||||
730 | |||||||||||||
731 | // Determine the size of the argument pack. | ||||||||||||
732 | NewPackSize = TemplateArgs(Depth, Index).pack_size(); | ||||||||||||
733 | } | ||||||||||||
734 | |||||||||||||
735 | // C++0x [temp.arg.explicit]p9: | ||||||||||||
736 | // Template argument deduction can extend the sequence of template | ||||||||||||
737 | // arguments corresponding to a template parameter pack, even when the | ||||||||||||
738 | // sequence contains explicitly specified template arguments. | ||||||||||||
739 | if (!IsVarDeclPack
| ||||||||||||
740 | if (NamedDecl *PartialPack = | ||||||||||||
741 | CurrentInstantiationScope->getPartiallySubstitutedPack()) { | ||||||||||||
742 | unsigned PartialDepth, PartialIndex; | ||||||||||||
743 | std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); | ||||||||||||
744 | if (PartialDepth == Depth && PartialIndex == Index) { | ||||||||||||
745 | RetainExpansion = true; | ||||||||||||
746 | // We don't actually know the new pack size yet. | ||||||||||||
747 | NumPartialExpansions = NewPackSize; | ||||||||||||
748 | PartiallySubstitutedPackLoc = ParmPack.second; | ||||||||||||
749 | continue; | ||||||||||||
750 | } | ||||||||||||
751 | } | ||||||||||||
752 | } | ||||||||||||
753 | |||||||||||||
754 | if (!NumExpansions) { | ||||||||||||
755 | // The is the first pack we've seen for which we have an argument. | ||||||||||||
756 | // Record it. | ||||||||||||
757 | NumExpansions = NewPackSize; | ||||||||||||
758 | FirstPack.first = Name; | ||||||||||||
759 | FirstPack.second = ParmPack.second; | ||||||||||||
760 | HaveFirstPack = true; | ||||||||||||
761 | continue; | ||||||||||||
762 | } | ||||||||||||
763 | |||||||||||||
764 | if (NewPackSize != *NumExpansions) { | ||||||||||||
765 | // C++0x [temp.variadic]p5: | ||||||||||||
766 | // All of the parameter packs expanded by a pack expansion shall have | ||||||||||||
767 | // the same number of arguments specified. | ||||||||||||
768 | if (HaveFirstPack) | ||||||||||||
769 | Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) | ||||||||||||
770 | << FirstPack.first << Name << *NumExpansions << NewPackSize | ||||||||||||
771 | << SourceRange(FirstPack.second) << SourceRange(ParmPack.second); | ||||||||||||
772 | else | ||||||||||||
773 | Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) | ||||||||||||
774 | << Name << *NumExpansions << NewPackSize | ||||||||||||
775 | << SourceRange(ParmPack.second); | ||||||||||||
776 | return true; | ||||||||||||
777 | } | ||||||||||||
778 | } | ||||||||||||
779 | |||||||||||||
780 | // If we're performing a partial expansion but we also have a full expansion, | ||||||||||||
781 | // expand to the number of common arguments. For example, given: | ||||||||||||
782 | // | ||||||||||||
783 | // template<typename ...T> struct A { | ||||||||||||
784 | // template<typename ...U> void f(pair<T, U>...); | ||||||||||||
785 | // }; | ||||||||||||
786 | // | ||||||||||||
787 | // ... a call to 'A<int, int>().f<int>' should expand the pack once and | ||||||||||||
788 | // retain an expansion. | ||||||||||||
789 | if (NumPartialExpansions) { | ||||||||||||
790 | if (NumExpansions && *NumExpansions < *NumPartialExpansions) { | ||||||||||||
791 | NamedDecl *PartialPack = | ||||||||||||
792 | CurrentInstantiationScope->getPartiallySubstitutedPack(); | ||||||||||||
793 | Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial) | ||||||||||||
794 | << PartialPack << *NumPartialExpansions << *NumExpansions | ||||||||||||
795 | << SourceRange(PartiallySubstitutedPackLoc); | ||||||||||||
796 | return true; | ||||||||||||
797 | } | ||||||||||||
798 | |||||||||||||
799 | NumExpansions = NumPartialExpansions; | ||||||||||||
800 | } | ||||||||||||
801 | |||||||||||||
802 | return false; | ||||||||||||
803 | } | ||||||||||||
804 | |||||||||||||
805 | std::optional<unsigned> Sema::getNumArgumentsInExpansion( | ||||||||||||
806 | QualType T, const MultiLevelTemplateArgumentList &TemplateArgs) { | ||||||||||||
807 | QualType Pattern = cast<PackExpansionType>(T)->getPattern(); | ||||||||||||
808 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||||||
809 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); | ||||||||||||
810 | |||||||||||||
811 | std::optional<unsigned> Result; | ||||||||||||
812 | for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { | ||||||||||||
813 | // Compute the depth and index for this parameter pack. | ||||||||||||
814 | unsigned Depth; | ||||||||||||
815 | unsigned Index; | ||||||||||||
816 | |||||||||||||
817 | if (const TemplateTypeParmType *TTP = | ||||||||||||
818 | Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) { | ||||||||||||
819 | Depth = TTP->getDepth(); | ||||||||||||
820 | Index = TTP->getIndex(); | ||||||||||||
821 | } else { | ||||||||||||
822 | NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>(); | ||||||||||||
823 | if (isa<VarDecl>(ND)) { | ||||||||||||
824 | // Function parameter pack or init-capture pack. | ||||||||||||
825 | typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; | ||||||||||||
826 | |||||||||||||
827 | llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation = | ||||||||||||
828 | CurrentInstantiationScope->findInstantiationOf( | ||||||||||||
829 | Unexpanded[I].first.get<NamedDecl *>()); | ||||||||||||
830 | if (Instantiation->is<Decl *>()) | ||||||||||||
831 | // The pattern refers to an unexpanded pack. We're not ready to expand | ||||||||||||
832 | // this pack yet. | ||||||||||||
833 | return std::nullopt; | ||||||||||||
834 | |||||||||||||
835 | unsigned Size = Instantiation->get<DeclArgumentPack *>()->size(); | ||||||||||||
836 | assert((!Result || *Result == Size) && "inconsistent pack sizes")(static_cast <bool> ((!Result || *Result == Size) && "inconsistent pack sizes") ? void (0) : __assert_fail ("(!Result || *Result == Size) && \"inconsistent pack sizes\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 836, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
837 | Result = Size; | ||||||||||||
838 | continue; | ||||||||||||
839 | } | ||||||||||||
840 | |||||||||||||
841 | std::tie(Depth, Index) = getDepthAndIndex(ND); | ||||||||||||
842 | } | ||||||||||||
843 | if (Depth >= TemplateArgs.getNumLevels() || | ||||||||||||
844 | !TemplateArgs.hasTemplateArgument(Depth, Index)) | ||||||||||||
845 | // The pattern refers to an unknown template argument. We're not ready to | ||||||||||||
846 | // expand this pack yet. | ||||||||||||
847 | return std::nullopt; | ||||||||||||
848 | |||||||||||||
849 | // Determine the size of the argument pack. | ||||||||||||
850 | unsigned Size = TemplateArgs(Depth, Index).pack_size(); | ||||||||||||
851 | assert((!Result || *Result == Size) && "inconsistent pack sizes")(static_cast <bool> ((!Result || *Result == Size) && "inconsistent pack sizes") ? void (0) : __assert_fail ("(!Result || *Result == Size) && \"inconsistent pack sizes\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 851, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
852 | Result = Size; | ||||||||||||
853 | } | ||||||||||||
854 | |||||||||||||
855 | return Result; | ||||||||||||
856 | } | ||||||||||||
857 | |||||||||||||
858 | bool Sema::containsUnexpandedParameterPacks(Declarator &D) { | ||||||||||||
859 | const DeclSpec &DS = D.getDeclSpec(); | ||||||||||||
860 | switch (DS.getTypeSpecType()) { | ||||||||||||
861 | case TST_typename: | ||||||||||||
862 | case TST_typeof_unqualType: | ||||||||||||
863 | case TST_typeofType: | ||||||||||||
864 | #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: | ||||||||||||
865 | #include "clang/Basic/TransformTypeTraits.def" | ||||||||||||
866 | case TST_atomic: { | ||||||||||||
867 | QualType T = DS.getRepAsType().get(); | ||||||||||||
868 | if (!T.isNull() && T->containsUnexpandedParameterPack()) | ||||||||||||
869 | return true; | ||||||||||||
870 | break; | ||||||||||||
871 | } | ||||||||||||
872 | |||||||||||||
873 | case TST_typeof_unqualExpr: | ||||||||||||
874 | case TST_typeofExpr: | ||||||||||||
875 | case TST_decltype: | ||||||||||||
876 | case TST_bitint: | ||||||||||||
877 | if (DS.getRepAsExpr() && | ||||||||||||
878 | DS.getRepAsExpr()->containsUnexpandedParameterPack()) | ||||||||||||
879 | return true; | ||||||||||||
880 | break; | ||||||||||||
881 | |||||||||||||
882 | case TST_unspecified: | ||||||||||||
883 | case TST_void: | ||||||||||||
884 | case TST_char: | ||||||||||||
885 | case TST_wchar: | ||||||||||||
886 | case TST_char8: | ||||||||||||
887 | case TST_char16: | ||||||||||||
888 | case TST_char32: | ||||||||||||
889 | case TST_int: | ||||||||||||
890 | case TST_int128: | ||||||||||||
891 | case TST_half: | ||||||||||||
892 | case TST_float: | ||||||||||||
893 | case TST_double: | ||||||||||||
894 | case TST_Accum: | ||||||||||||
895 | case TST_Fract: | ||||||||||||
896 | case TST_Float16: | ||||||||||||
897 | case TST_float128: | ||||||||||||
898 | case TST_ibm128: | ||||||||||||
899 | case TST_bool: | ||||||||||||
900 | case TST_decimal32: | ||||||||||||
901 | case TST_decimal64: | ||||||||||||
902 | case TST_decimal128: | ||||||||||||
903 | case TST_enum: | ||||||||||||
904 | case TST_union: | ||||||||||||
905 | case TST_struct: | ||||||||||||
906 | case TST_interface: | ||||||||||||
907 | case TST_class: | ||||||||||||
908 | case TST_auto: | ||||||||||||
909 | case TST_auto_type: | ||||||||||||
910 | case TST_decltype_auto: | ||||||||||||
911 | case TST_BFloat16: | ||||||||||||
912 | #define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: | ||||||||||||
913 | #include "clang/Basic/OpenCLImageTypes.def" | ||||||||||||
914 | case TST_unknown_anytype: | ||||||||||||
915 | case TST_error: | ||||||||||||
916 | break; | ||||||||||||
917 | } | ||||||||||||
918 | |||||||||||||
919 | for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) { | ||||||||||||
920 | const DeclaratorChunk &Chunk = D.getTypeObject(I); | ||||||||||||
921 | switch (Chunk.Kind) { | ||||||||||||
922 | case DeclaratorChunk::Pointer: | ||||||||||||
923 | case DeclaratorChunk::Reference: | ||||||||||||
924 | case DeclaratorChunk::Paren: | ||||||||||||
925 | case DeclaratorChunk::Pipe: | ||||||||||||
926 | case DeclaratorChunk::BlockPointer: | ||||||||||||
927 | // These declarator chunks cannot contain any parameter packs. | ||||||||||||
928 | break; | ||||||||||||
929 | |||||||||||||
930 | case DeclaratorChunk::Array: | ||||||||||||
931 | if (Chunk.Arr.NumElts && | ||||||||||||
932 | Chunk.Arr.NumElts->containsUnexpandedParameterPack()) | ||||||||||||
933 | return true; | ||||||||||||
934 | break; | ||||||||||||
935 | case DeclaratorChunk::Function: | ||||||||||||
936 | for (unsigned i = 0, e = Chunk.Fun.NumParams; i != e; ++i) { | ||||||||||||
937 | ParmVarDecl *Param = cast<ParmVarDecl>(Chunk.Fun.Params[i].Param); | ||||||||||||
938 | QualType ParamTy = Param->getType(); | ||||||||||||
939 | assert(!ParamTy.isNull() && "Couldn't parse type?")(static_cast <bool> (!ParamTy.isNull() && "Couldn't parse type?" ) ? void (0) : __assert_fail ("!ParamTy.isNull() && \"Couldn't parse type?\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 939, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
940 | if (ParamTy->containsUnexpandedParameterPack()) return true; | ||||||||||||
941 | } | ||||||||||||
942 | |||||||||||||
943 | if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) { | ||||||||||||
944 | for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) { | ||||||||||||
945 | if (Chunk.Fun.Exceptions[i] | ||||||||||||
946 | .Ty.get() | ||||||||||||
947 | ->containsUnexpandedParameterPack()) | ||||||||||||
948 | return true; | ||||||||||||
949 | } | ||||||||||||
950 | } else if (isComputedNoexcept(Chunk.Fun.getExceptionSpecType()) && | ||||||||||||
951 | Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack()) | ||||||||||||
952 | return true; | ||||||||||||
953 | |||||||||||||
954 | if (Chunk.Fun.hasTrailingReturnType()) { | ||||||||||||
955 | QualType T = Chunk.Fun.getTrailingReturnType().get(); | ||||||||||||
956 | if (!T.isNull() && T->containsUnexpandedParameterPack()) | ||||||||||||
957 | return true; | ||||||||||||
958 | } | ||||||||||||
959 | break; | ||||||||||||
960 | |||||||||||||
961 | case DeclaratorChunk::MemberPointer: | ||||||||||||
962 | if (Chunk.Mem.Scope().getScopeRep() && | ||||||||||||
963 | Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack()) | ||||||||||||
964 | return true; | ||||||||||||
965 | break; | ||||||||||||
966 | } | ||||||||||||
967 | } | ||||||||||||
968 | |||||||||||||
969 | if (Expr *TRC = D.getTrailingRequiresClause()) | ||||||||||||
970 | if (TRC->containsUnexpandedParameterPack()) | ||||||||||||
971 | return true; | ||||||||||||
972 | |||||||||||||
973 | return false; | ||||||||||||
974 | } | ||||||||||||
975 | |||||||||||||
976 | namespace { | ||||||||||||
977 | |||||||||||||
978 | // Callback to only accept typo corrections that refer to parameter packs. | ||||||||||||
979 | class ParameterPackValidatorCCC final : public CorrectionCandidateCallback { | ||||||||||||
980 | public: | ||||||||||||
981 | bool ValidateCandidate(const TypoCorrection &candidate) override { | ||||||||||||
982 | NamedDecl *ND = candidate.getCorrectionDecl(); | ||||||||||||
983 | return ND && ND->isParameterPack(); | ||||||||||||
984 | } | ||||||||||||
985 | |||||||||||||
986 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | ||||||||||||
987 | return std::make_unique<ParameterPackValidatorCCC>(*this); | ||||||||||||
988 | } | ||||||||||||
989 | }; | ||||||||||||
990 | |||||||||||||
991 | } | ||||||||||||
992 | |||||||||||||
993 | /// Called when an expression computing the size of a parameter pack | ||||||||||||
994 | /// is parsed. | ||||||||||||
995 | /// | ||||||||||||
996 | /// \code | ||||||||||||
997 | /// template<typename ...Types> struct count { | ||||||||||||
998 | /// static const unsigned value = sizeof...(Types); | ||||||||||||
999 | /// }; | ||||||||||||
1000 | /// \endcode | ||||||||||||
1001 | /// | ||||||||||||
1002 | // | ||||||||||||
1003 | /// \param OpLoc The location of the "sizeof" keyword. | ||||||||||||
1004 | /// \param Name The name of the parameter pack whose size will be determined. | ||||||||||||
1005 | /// \param NameLoc The source location of the name of the parameter pack. | ||||||||||||
1006 | /// \param RParenLoc The location of the closing parentheses. | ||||||||||||
1007 | ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, | ||||||||||||
1008 | SourceLocation OpLoc, | ||||||||||||
1009 | IdentifierInfo &Name, | ||||||||||||
1010 | SourceLocation NameLoc, | ||||||||||||
1011 | SourceLocation RParenLoc) { | ||||||||||||
1012 | // C++0x [expr.sizeof]p5: | ||||||||||||
1013 | // The identifier in a sizeof... expression shall name a parameter pack. | ||||||||||||
1014 | LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName); | ||||||||||||
1015 | LookupName(R, S); | ||||||||||||
1016 | |||||||||||||
1017 | NamedDecl *ParameterPack = nullptr; | ||||||||||||
1018 | switch (R.getResultKind()) { | ||||||||||||
1019 | case LookupResult::Found: | ||||||||||||
1020 | ParameterPack = R.getFoundDecl(); | ||||||||||||
1021 | break; | ||||||||||||
1022 | |||||||||||||
1023 | case LookupResult::NotFound: | ||||||||||||
1024 | case LookupResult::NotFoundInCurrentInstantiation: { | ||||||||||||
1025 | ParameterPackValidatorCCC CCC{}; | ||||||||||||
1026 | if (TypoCorrection Corrected = | ||||||||||||
1027 | CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr, | ||||||||||||
1028 | CCC, CTK_ErrorRecovery)) { | ||||||||||||
1029 | diagnoseTypo(Corrected, | ||||||||||||
1030 | PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name, | ||||||||||||
1031 | PDiag(diag::note_parameter_pack_here)); | ||||||||||||
1032 | ParameterPack = Corrected.getCorrectionDecl(); | ||||||||||||
1033 | } | ||||||||||||
1034 | break; | ||||||||||||
1035 | } | ||||||||||||
1036 | case LookupResult::FoundOverloaded: | ||||||||||||
1037 | case LookupResult::FoundUnresolvedValue: | ||||||||||||
1038 | break; | ||||||||||||
1039 | |||||||||||||
1040 | case LookupResult::Ambiguous: | ||||||||||||
1041 | DiagnoseAmbiguousLookup(R); | ||||||||||||
1042 | return ExprError(); | ||||||||||||
1043 | } | ||||||||||||
1044 | |||||||||||||
1045 | if (!ParameterPack || !ParameterPack->isParameterPack()) { | ||||||||||||
1046 | Diag(NameLoc, diag::err_sizeof_pack_no_pack_name) | ||||||||||||
1047 | << &Name; | ||||||||||||
1048 | return ExprError(); | ||||||||||||
1049 | } | ||||||||||||
1050 | |||||||||||||
1051 | MarkAnyDeclReferenced(OpLoc, ParameterPack, true); | ||||||||||||
1052 | |||||||||||||
1053 | return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc, | ||||||||||||
1054 | RParenLoc); | ||||||||||||
1055 | } | ||||||||||||
1056 | |||||||||||||
1057 | TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( | ||||||||||||
1058 | TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis, | ||||||||||||
1059 | std::optional<unsigned> &NumExpansions) const { | ||||||||||||
1060 | const TemplateArgument &Argument = OrigLoc.getArgument(); | ||||||||||||
1061 | assert(Argument.isPackExpansion())(static_cast <bool> (Argument.isPackExpansion()) ? void (0) : __assert_fail ("Argument.isPackExpansion()", "clang/lib/Sema/SemaTemplateVariadic.cpp" , 1061, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1062 | switch (Argument.getKind()) { | ||||||||||||
1063 | case TemplateArgument::Type: { | ||||||||||||
1064 | // FIXME: We shouldn't ever have to worry about missing | ||||||||||||
1065 | // type-source info! | ||||||||||||
1066 | TypeSourceInfo *ExpansionTSInfo = OrigLoc.getTypeSourceInfo(); | ||||||||||||
1067 | if (!ExpansionTSInfo) | ||||||||||||
1068 | ExpansionTSInfo = Context.getTrivialTypeSourceInfo(Argument.getAsType(), | ||||||||||||
1069 | Ellipsis); | ||||||||||||
1070 | PackExpansionTypeLoc Expansion = | ||||||||||||
1071 | ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>(); | ||||||||||||
1072 | Ellipsis = Expansion.getEllipsisLoc(); | ||||||||||||
1073 | |||||||||||||
1074 | TypeLoc Pattern = Expansion.getPatternLoc(); | ||||||||||||
1075 | NumExpansions = Expansion.getTypePtr()->getNumExpansions(); | ||||||||||||
1076 | |||||||||||||
1077 | // We need to copy the TypeLoc because TemplateArgumentLocs store a | ||||||||||||
1078 | // TypeSourceInfo. | ||||||||||||
1079 | // FIXME: Find some way to avoid the copy? | ||||||||||||
1080 | TypeLocBuilder TLB; | ||||||||||||
1081 | TLB.pushFullCopy(Pattern); | ||||||||||||
1082 | TypeSourceInfo *PatternTSInfo = | ||||||||||||
1083 | TLB.getTypeSourceInfo(Context, Pattern.getType()); | ||||||||||||
1084 | return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), | ||||||||||||
1085 | PatternTSInfo); | ||||||||||||
1086 | } | ||||||||||||
1087 | |||||||||||||
1088 | case TemplateArgument::Expression: { | ||||||||||||
1089 | PackExpansionExpr *Expansion | ||||||||||||
1090 | = cast<PackExpansionExpr>(Argument.getAsExpr()); | ||||||||||||
1091 | Expr *Pattern = Expansion->getPattern(); | ||||||||||||
1092 | Ellipsis = Expansion->getEllipsisLoc(); | ||||||||||||
1093 | NumExpansions = Expansion->getNumExpansions(); | ||||||||||||
1094 | return TemplateArgumentLoc(Pattern, Pattern); | ||||||||||||
1095 | } | ||||||||||||
1096 | |||||||||||||
1097 | case TemplateArgument::TemplateExpansion: | ||||||||||||
1098 | Ellipsis = OrigLoc.getTemplateEllipsisLoc(); | ||||||||||||
1099 | NumExpansions = Argument.getNumTemplateExpansions(); | ||||||||||||
1100 | return TemplateArgumentLoc(Context, Argument.getPackExpansionPattern(), | ||||||||||||
1101 | OrigLoc.getTemplateQualifierLoc(), | ||||||||||||
1102 | OrigLoc.getTemplateNameLoc()); | ||||||||||||
1103 | |||||||||||||
1104 | case TemplateArgument::Declaration: | ||||||||||||
1105 | case TemplateArgument::NullPtr: | ||||||||||||
1106 | case TemplateArgument::Template: | ||||||||||||
1107 | case TemplateArgument::Integral: | ||||||||||||
1108 | case TemplateArgument::Pack: | ||||||||||||
1109 | case TemplateArgument::Null: | ||||||||||||
1110 | return TemplateArgumentLoc(); | ||||||||||||
1111 | } | ||||||||||||
1112 | |||||||||||||
1113 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 1113); | ||||||||||||
1114 | } | ||||||||||||
1115 | |||||||||||||
1116 | std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) { | ||||||||||||
1117 | assert(Arg.containsUnexpandedParameterPack())(static_cast <bool> (Arg.containsUnexpandedParameterPack ()) ? void (0) : __assert_fail ("Arg.containsUnexpandedParameterPack()" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 1117, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1118 | |||||||||||||
1119 | // If this is a substituted pack, grab that pack. If not, we don't know | ||||||||||||
1120 | // the size yet. | ||||||||||||
1121 | // FIXME: We could find a size in more cases by looking for a substituted | ||||||||||||
1122 | // pack anywhere within this argument, but that's not necessary in the common | ||||||||||||
1123 | // case for 'sizeof...(A)' handling. | ||||||||||||
1124 | TemplateArgument Pack; | ||||||||||||
1125 | switch (Arg.getKind()) { | ||||||||||||
1126 | case TemplateArgument::Type: | ||||||||||||
1127 | if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>()) | ||||||||||||
1128 | Pack = Subst->getArgumentPack(); | ||||||||||||
1129 | else | ||||||||||||
1130 | return std::nullopt; | ||||||||||||
1131 | break; | ||||||||||||
1132 | |||||||||||||
1133 | case TemplateArgument::Expression: | ||||||||||||
1134 | if (auto *Subst = | ||||||||||||
1135 | dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr())) | ||||||||||||
1136 | Pack = Subst->getArgumentPack(); | ||||||||||||
1137 | else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) { | ||||||||||||
1138 | for (VarDecl *PD : *Subst) | ||||||||||||
1139 | if (PD->isParameterPack()) | ||||||||||||
1140 | return std::nullopt; | ||||||||||||
1141 | return Subst->getNumExpansions(); | ||||||||||||
1142 | } else | ||||||||||||
1143 | return std::nullopt; | ||||||||||||
1144 | break; | ||||||||||||
1145 | |||||||||||||
1146 | case TemplateArgument::Template: | ||||||||||||
1147 | if (SubstTemplateTemplateParmPackStorage *Subst = | ||||||||||||
1148 | Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack()) | ||||||||||||
1149 | Pack = Subst->getArgumentPack(); | ||||||||||||
1150 | else | ||||||||||||
1151 | return std::nullopt; | ||||||||||||
1152 | break; | ||||||||||||
1153 | |||||||||||||
1154 | case TemplateArgument::Declaration: | ||||||||||||
1155 | case TemplateArgument::NullPtr: | ||||||||||||
1156 | case TemplateArgument::TemplateExpansion: | ||||||||||||
1157 | case TemplateArgument::Integral: | ||||||||||||
1158 | case TemplateArgument::Pack: | ||||||||||||
1159 | case TemplateArgument::Null: | ||||||||||||
1160 | return std::nullopt; | ||||||||||||
1161 | } | ||||||||||||
1162 | |||||||||||||
1163 | // Check that no argument in the pack is itself a pack expansion. | ||||||||||||
1164 | for (TemplateArgument Elem : Pack.pack_elements()) { | ||||||||||||
1165 | // There's no point recursing in this case; we would have already | ||||||||||||
1166 | // expanded this pack expansion into the enclosing pack if we could. | ||||||||||||
1167 | if (Elem.isPackExpansion()) | ||||||||||||
1168 | return std::nullopt; | ||||||||||||
1169 | } | ||||||||||||
1170 | return Pack.pack_size(); | ||||||||||||
1171 | } | ||||||||||||
1172 | |||||||||||||
1173 | static void CheckFoldOperand(Sema &S, Expr *E) { | ||||||||||||
1174 | if (!E) | ||||||||||||
1175 | return; | ||||||||||||
1176 | |||||||||||||
1177 | E = E->IgnoreImpCasts(); | ||||||||||||
1178 | auto *OCE = dyn_cast<CXXOperatorCallExpr>(E); | ||||||||||||
1179 | if ((OCE && OCE->isInfixBinaryOp()) || isa<BinaryOperator>(E) || | ||||||||||||
1180 | isa<AbstractConditionalOperator>(E)) { | ||||||||||||
1181 | S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand) | ||||||||||||
1182 | << E->getSourceRange() | ||||||||||||
1183 | << FixItHint::CreateInsertion(E->getBeginLoc(), "(") | ||||||||||||
1184 | << FixItHint::CreateInsertion(E->getEndLoc(), ")"); | ||||||||||||
1185 | } | ||||||||||||
1186 | } | ||||||||||||
1187 | |||||||||||||
1188 | ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS, | ||||||||||||
1189 | tok::TokenKind Operator, | ||||||||||||
1190 | SourceLocation EllipsisLoc, Expr *RHS, | ||||||||||||
1191 | SourceLocation RParenLoc) { | ||||||||||||
1192 | // LHS and RHS must be cast-expressions. We allow an arbitrary expression | ||||||||||||
1193 | // in the parser and reduce down to just cast-expressions here. | ||||||||||||
1194 | CheckFoldOperand(*this, LHS); | ||||||||||||
1195 | CheckFoldOperand(*this, RHS); | ||||||||||||
1196 | |||||||||||||
1197 | auto DiscardOperands = [&] { | ||||||||||||
1198 | CorrectDelayedTyposInExpr(LHS); | ||||||||||||
1199 | CorrectDelayedTyposInExpr(RHS); | ||||||||||||
1200 | }; | ||||||||||||
1201 | |||||||||||||
1202 | // [expr.prim.fold]p3: | ||||||||||||
1203 | // In a binary fold, op1 and op2 shall be the same fold-operator, and | ||||||||||||
1204 | // either e1 shall contain an unexpanded parameter pack or e2 shall contain | ||||||||||||
1205 | // an unexpanded parameter pack, but not both. | ||||||||||||
1206 | if (LHS && RHS && | ||||||||||||
1207 | LHS->containsUnexpandedParameterPack() == | ||||||||||||
1208 | RHS->containsUnexpandedParameterPack()) { | ||||||||||||
1209 | DiscardOperands(); | ||||||||||||
1210 | return Diag(EllipsisLoc, | ||||||||||||
1211 | LHS->containsUnexpandedParameterPack() | ||||||||||||
1212 | ? diag::err_fold_expression_packs_both_sides | ||||||||||||
1213 | : diag::err_pack_expansion_without_parameter_packs) | ||||||||||||
1214 | << LHS->getSourceRange() << RHS->getSourceRange(); | ||||||||||||
1215 | } | ||||||||||||
1216 | |||||||||||||
1217 | // [expr.prim.fold]p2: | ||||||||||||
1218 | // In a unary fold, the cast-expression shall contain an unexpanded | ||||||||||||
1219 | // parameter pack. | ||||||||||||
1220 | if (!LHS || !RHS) { | ||||||||||||
1221 | Expr *Pack = LHS ? LHS : RHS; | ||||||||||||
1222 | assert(Pack && "fold expression with neither LHS nor RHS")(static_cast <bool> (Pack && "fold expression with neither LHS nor RHS" ) ? void (0) : __assert_fail ("Pack && \"fold expression with neither LHS nor RHS\"" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 1222, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1223 | if (!Pack->containsUnexpandedParameterPack()) { | ||||||||||||
1224 | DiscardOperands(); | ||||||||||||
1225 | return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | ||||||||||||
1226 | << Pack->getSourceRange(); | ||||||||||||
1227 | } | ||||||||||||
1228 | } | ||||||||||||
1229 | |||||||||||||
1230 | BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator); | ||||||||||||
1231 | |||||||||||||
1232 | // Perform first-phase name lookup now. | ||||||||||||
1233 | UnresolvedLookupExpr *ULE = nullptr; | ||||||||||||
1234 | { | ||||||||||||
1235 | UnresolvedSet<16> Functions; | ||||||||||||
1236 | LookupBinOp(S, EllipsisLoc, Opc, Functions); | ||||||||||||
1237 | if (!Functions.empty()) { | ||||||||||||
1238 | DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName( | ||||||||||||
1239 | BinaryOperator::getOverloadedOperator(Opc)); | ||||||||||||
1240 | ExprResult Callee = CreateUnresolvedLookupExpr( | ||||||||||||
1241 | /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), | ||||||||||||
1242 | DeclarationNameInfo(OpName, EllipsisLoc), Functions); | ||||||||||||
1243 | if (Callee.isInvalid()) | ||||||||||||
1244 | return ExprError(); | ||||||||||||
1245 | ULE = cast<UnresolvedLookupExpr>(Callee.get()); | ||||||||||||
1246 | } | ||||||||||||
1247 | } | ||||||||||||
1248 | |||||||||||||
1249 | return BuildCXXFoldExpr(ULE, LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc, | ||||||||||||
1250 | std::nullopt); | ||||||||||||
1251 | } | ||||||||||||
1252 | |||||||||||||
1253 | ExprResult Sema::BuildCXXFoldExpr(UnresolvedLookupExpr *Callee, | ||||||||||||
1254 | SourceLocation LParenLoc, Expr *LHS, | ||||||||||||
1255 | BinaryOperatorKind Operator, | ||||||||||||
1256 | SourceLocation EllipsisLoc, Expr *RHS, | ||||||||||||
1257 | SourceLocation RParenLoc, | ||||||||||||
1258 | std::optional<unsigned> NumExpansions) { | ||||||||||||
1259 | return new (Context) | ||||||||||||
1260 | CXXFoldExpr(Context.DependentTy, Callee, LParenLoc, LHS, Operator, | ||||||||||||
1261 | EllipsisLoc, RHS, RParenLoc, NumExpansions); | ||||||||||||
1262 | } | ||||||||||||
1263 | |||||||||||||
1264 | ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, | ||||||||||||
1265 | BinaryOperatorKind Operator) { | ||||||||||||
1266 | // [temp.variadic]p9: | ||||||||||||
1267 | // If N is zero for a unary fold-expression, the value of the expression is | ||||||||||||
1268 | // && -> true | ||||||||||||
1269 | // || -> false | ||||||||||||
1270 | // , -> void() | ||||||||||||
1271 | // if the operator is not listed [above], the instantiation is ill-formed. | ||||||||||||
1272 | // | ||||||||||||
1273 | // Note that we need to use something like int() here, not merely 0, to | ||||||||||||
1274 | // prevent the result from being a null pointer constant. | ||||||||||||
1275 | QualType ScalarType; | ||||||||||||
1276 | switch (Operator) { | ||||||||||||
1277 | case BO_LOr: | ||||||||||||
1278 | return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_false); | ||||||||||||
1279 | case BO_LAnd: | ||||||||||||
1280 | return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_true); | ||||||||||||
1281 | case BO_Comma: | ||||||||||||
1282 | ScalarType = Context.VoidTy; | ||||||||||||
1283 | break; | ||||||||||||
1284 | |||||||||||||
1285 | default: | ||||||||||||
1286 | return Diag(EllipsisLoc, diag::err_fold_expression_empty) | ||||||||||||
1287 | << BinaryOperator::getOpcodeStr(Operator); | ||||||||||||
1288 | } | ||||||||||||
1289 | |||||||||||||
1290 | return new (Context) CXXScalarValueInitExpr( | ||||||||||||
1291 | ScalarType, Context.getTrivialTypeSourceInfo(ScalarType, EllipsisLoc), | ||||||||||||
1292 | EllipsisLoc); | ||||||||||||
1293 | } |
1 | //===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===// |
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 | /// \file |
10 | /// This file defines the PointerUnion class, which is a discriminated union of |
11 | /// pointer types. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_ADT_POINTERUNION_H |
16 | #define LLVM_ADT_POINTERUNION_H |
17 | |
18 | #include "llvm/ADT/DenseMapInfo.h" |
19 | #include "llvm/ADT/PointerIntPair.h" |
20 | #include "llvm/ADT/STLExtras.h" |
21 | #include "llvm/Support/Casting.h" |
22 | #include "llvm/Support/PointerLikeTypeTraits.h" |
23 | #include <algorithm> |
24 | #include <cassert> |
25 | #include <cstddef> |
26 | #include <cstdint> |
27 | |
28 | namespace llvm { |
29 | |
30 | namespace pointer_union_detail { |
31 | /// Determine the number of bits required to store integers with values < n. |
32 | /// This is ceil(log2(n)). |
33 | constexpr int bitsRequired(unsigned n) { |
34 | return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0; |
35 | } |
36 | |
37 | template <typename... Ts> constexpr int lowBitsAvailable() { |
38 | return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...}); |
39 | } |
40 | |
41 | /// Find the first type in a list of types. |
42 | template <typename T, typename...> struct GetFirstType { |
43 | using type = T; |
44 | }; |
45 | |
46 | /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion |
47 | /// for the template arguments. |
48 | template <typename ...PTs> class PointerUnionUIntTraits { |
49 | public: |
50 | static inline void *getAsVoidPointer(void *P) { return P; } |
51 | static inline void *getFromVoidPointer(void *P) { return P; } |
52 | static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>(); |
53 | }; |
54 | |
55 | template <typename Derived, typename ValTy, int I, typename ...Types> |
56 | class PointerUnionMembers; |
57 | |
58 | template <typename Derived, typename ValTy, int I> |
59 | class PointerUnionMembers<Derived, ValTy, I> { |
60 | protected: |
61 | ValTy Val; |
62 | PointerUnionMembers() = default; |
63 | PointerUnionMembers(ValTy Val) : Val(Val) {} |
64 | |
65 | friend struct PointerLikeTypeTraits<Derived>; |
66 | }; |
67 | |
68 | template <typename Derived, typename ValTy, int I, typename Type, |
69 | typename ...Types> |
70 | class PointerUnionMembers<Derived, ValTy, I, Type, Types...> |
71 | : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> { |
72 | using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>; |
73 | public: |
74 | using Base::Base; |
75 | PointerUnionMembers() = default; |
76 | PointerUnionMembers(Type V) |
77 | : Base(ValTy(const_cast<void *>( |
78 | PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
79 | I)) {} |
80 | |
81 | using Base::operator=; |
82 | Derived &operator=(Type V) { |
83 | this->Val = ValTy( |
84 | const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
85 | I); |
86 | return static_cast<Derived &>(*this); |
87 | }; |
88 | }; |
89 | } |
90 | |
91 | // This is a forward declaration of CastInfoPointerUnionImpl |
92 | // Refer to its definition below for further details |
93 | template <typename... PTs> struct CastInfoPointerUnionImpl; |
94 | /// A discriminated union of two or more pointer types, with the discriminator |
95 | /// in the low bit of the pointer. |
96 | /// |
97 | /// This implementation is extremely efficient in space due to leveraging the |
98 | /// low bits of the pointer, while exposing a natural and type-safe API. |
99 | /// |
100 | /// Common use patterns would be something like this: |
101 | /// PointerUnion<int*, float*> P; |
102 | /// P = (int*)0; |
103 | /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" |
104 | /// X = P.get<int*>(); // ok. |
105 | /// Y = P.get<float*>(); // runtime assertion failure. |
106 | /// Z = P.get<double*>(); // compile time failure. |
107 | /// P = (float*)0; |
108 | /// Y = P.get<float*>(); // ok. |
109 | /// X = P.get<int*>(); // runtime assertion failure. |
110 | /// PointerUnion<int*, int*> Q; // compile time failure. |
111 | template <typename... PTs> |
112 | class PointerUnion |
113 | : public pointer_union_detail::PointerUnionMembers< |
114 | PointerUnion<PTs...>, |
115 | PointerIntPair< |
116 | void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int, |
117 | pointer_union_detail::PointerUnionUIntTraits<PTs...>>, |
118 | 0, PTs...> { |
119 | static_assert(TypesAreDistinct<PTs...>::value, |
120 | "PointerUnion alternative types cannot be repeated"); |
121 | // The first type is special because we want to directly cast a pointer to a |
122 | // default-initialized union to a pointer to the first type. But we don't |
123 | // want PointerUnion to be a 'template <typename First, typename ...Rest>' |
124 | // because it's much more convenient to have a name for the whole pack. So |
125 | // split off the first type here. |
126 | using First = TypeAtIndex<0, PTs...>; |
127 | using Base = typename PointerUnion::PointerUnionMembers; |
128 | |
129 | /// This is needed to give the CastInfo implementation below access |
130 | /// to protected members. |
131 | /// Refer to its definition for further details. |
132 | friend struct CastInfoPointerUnionImpl<PTs...>; |
133 | |
134 | public: |
135 | PointerUnion() = default; |
136 | |
137 | PointerUnion(std::nullptr_t) : PointerUnion() {} |
138 | using Base::Base; |
139 | |
140 | /// Test if the pointer held in the union is null, regardless of |
141 | /// which type it is. |
142 | bool isNull() const { return !this->Val.getPointer(); } |
143 | |
144 | explicit operator bool() const { return !isNull(); } |
145 | |
146 | // FIXME: Replace the uses of is(), get() and dyn_cast() with |
147 | // isa<T>, cast<T> and the llvm::dyn_cast<T> |
148 | |
149 | /// Test if the Union currently holds the type matching T. |
150 | template <typename T> inline bool is() const { return isa<T>(*this); } |
151 | |
152 | /// Returns the value of the specified pointer type. |
153 | /// |
154 | /// If the specified pointer type is incorrect, assert. |
155 | template <typename T> inline T get() const { |
156 | assert(isa<T>(*this) && "Invalid accessor called")(static_cast <bool> (isa<T>(*this) && "Invalid accessor called" ) ? void (0) : __assert_fail ("isa<T>(*this) && \"Invalid accessor called\"" , "llvm/include/llvm/ADT/PointerUnion.h", 156, __extension__ __PRETTY_FUNCTION__ )); |
157 | return cast<T>(*this); |
158 | } |
159 | |
160 | /// Returns the current pointer if it is of the specified pointer type, |
161 | /// otherwise returns null. |
162 | template <typename T> inline T dyn_cast() const { |
163 | return llvm::dyn_cast_if_present<T>(*this); |
164 | } |
165 | |
166 | /// If the union is set to the first pointer type get an address pointing to |
167 | /// it. |
168 | First const *getAddrOfPtr1() const { |
169 | return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); |
170 | } |
171 | |
172 | /// If the union is set to the first pointer type get an address pointing to |
173 | /// it. |
174 | First *getAddrOfPtr1() { |
175 | assert(is<First>() && "Val is not the first pointer")(static_cast <bool> (is<First>() && "Val is not the first pointer" ) ? void (0) : __assert_fail ("is<First>() && \"Val is not the first pointer\"" , "llvm/include/llvm/ADT/PointerUnion.h", 175, __extension__ __PRETTY_FUNCTION__ )); |
176 | assert((static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(get<First>()) == this->Val.getPointer () && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )) |
177 | PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) ==(static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(get<First>()) == this->Val.getPointer () && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )) |
178 | this->Val.getPointer() &&(static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(get<First>()) == this->Val.getPointer () && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )) |
179 | "Can't get the address because PointerLikeTypeTraits changes the ptr")(static_cast <bool> (PointerLikeTypeTraits<First> ::getAsVoidPointer(get<First>()) == this->Val.getPointer () && "Can't get the address because PointerLikeTypeTraits changes the ptr" ) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\"" , "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__ )); |
180 | return const_cast<First *>( |
181 | reinterpret_cast<const First *>(this->Val.getAddrOfPointer())); |
182 | } |
183 | |
184 | /// Assignment from nullptr which just clears the union. |
185 | const PointerUnion &operator=(std::nullptr_t) { |
186 | this->Val.initWithPointer(nullptr); |
187 | return *this; |
188 | } |
189 | |
190 | /// Assignment from elements of the union. |
191 | using Base::operator=; |
192 | |
193 | void *getOpaqueValue() const { return this->Val.getOpaqueValue(); } |
194 | static inline PointerUnion getFromOpaqueValue(void *VP) { |
195 | PointerUnion V; |
196 | V.Val = decltype(V.Val)::getFromOpaqueValue(VP); |
197 | return V; |
198 | } |
199 | }; |
200 | |
201 | template <typename ...PTs> |
202 | bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
203 | return lhs.getOpaqueValue() == rhs.getOpaqueValue(); |
204 | } |
205 | |
206 | template <typename ...PTs> |
207 | bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
208 | return lhs.getOpaqueValue() != rhs.getOpaqueValue(); |
209 | } |
210 | |
211 | template <typename ...PTs> |
212 | bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
213 | return lhs.getOpaqueValue() < rhs.getOpaqueValue(); |
214 | } |
215 | |
216 | /// We can't (at least, at this moment with C++14) declare CastInfo |
217 | /// as a friend of PointerUnion like this: |
218 | /// ``` |
219 | /// template<typename To> |
220 | /// friend struct CastInfo<To, PointerUnion<PTs...>>; |
221 | /// ``` |
222 | /// The compiler complains 'Partial specialization cannot be declared as a |
223 | /// friend'. |
224 | /// So we define this struct to be a bridge between CastInfo and |
225 | /// PointerUnion. |
226 | template <typename... PTs> struct CastInfoPointerUnionImpl { |
227 | using From = PointerUnion<PTs...>; |
228 | |
229 | template <typename To> static inline bool isPossible(From &F) { |
230 | return F.Val.getInt() == FirstIndexOfType<To, PTs...>::value; |
231 | } |
232 | |
233 | template <typename To> static To doCast(From &F) { |
234 | assert(isPossible<To>(F) && "cast to an incompatible type !")(static_cast <bool> (isPossible<To>(F) && "cast to an incompatible type !") ? void (0) : __assert_fail ("isPossible<To>(F) && \"cast to an incompatible type !\"" , "llvm/include/llvm/ADT/PointerUnion.h", 234, __extension__ __PRETTY_FUNCTION__ )); |
235 | return PointerLikeTypeTraits<To>::getFromVoidPointer(F.Val.getPointer()); |
236 | } |
237 | }; |
238 | |
239 | // Specialization of CastInfo for PointerUnion |
240 | template <typename To, typename... PTs> |
241 | struct CastInfo<To, PointerUnion<PTs...>> |
242 | : public DefaultDoCastIfPossible<To, PointerUnion<PTs...>, |
243 | CastInfo<To, PointerUnion<PTs...>>> { |
244 | using From = PointerUnion<PTs...>; |
245 | using Impl = CastInfoPointerUnionImpl<PTs...>; |
246 | |
247 | static inline bool isPossible(From &f) { |
248 | return Impl::template isPossible<To>(f); |
249 | } |
250 | |
251 | static To doCast(From &f) { return Impl::template doCast<To>(f); } |
252 | |
253 | static inline To castFailed() { return To(); } |
254 | }; |
255 | |
256 | template <typename To, typename... PTs> |
257 | struct CastInfo<To, const PointerUnion<PTs...>> |
258 | : public ConstStrippingForwardingCast<To, const PointerUnion<PTs...>, |
259 | CastInfo<To, PointerUnion<PTs...>>> { |
260 | }; |
261 | |
262 | // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has |
263 | // # low bits available = min(PT1bits,PT2bits)-1. |
264 | template <typename ...PTs> |
265 | struct PointerLikeTypeTraits<PointerUnion<PTs...>> { |
266 | static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) { |
267 | return P.getOpaqueValue(); |
268 | } |
269 | |
270 | static inline PointerUnion<PTs...> getFromVoidPointer(void *P) { |
271 | return PointerUnion<PTs...>::getFromOpaqueValue(P); |
272 | } |
273 | |
274 | // The number of bits available are the min of the pointer types minus the |
275 | // bits needed for the discriminator. |
276 | static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype( |
277 | PointerUnion<PTs...>::Val)>::NumLowBitsAvailable; |
278 | }; |
279 | |
280 | // Teach DenseMap how to use PointerUnions as keys. |
281 | template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> { |
282 | using Union = PointerUnion<PTs...>; |
283 | using FirstInfo = |
284 | DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>; |
285 | |
286 | static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); } |
287 | |
288 | static inline Union getTombstoneKey() { |
289 | return Union(FirstInfo::getTombstoneKey()); |
290 | } |
291 | |
292 | static unsigned getHashValue(const Union &UnionVal) { |
293 | intptr_t key = (intptr_t)UnionVal.getOpaqueValue(); |
294 | return DenseMapInfo<intptr_t>::getHashValue(key); |
295 | } |
296 | |
297 | static bool isEqual(const Union &LHS, const Union &RHS) { |
298 | return LHS == RHS; |
299 | } |
300 | }; |
301 | |
302 | } // end namespace llvm |
303 | |
304 | #endif // LLVM_ADT_POINTERUNION_H |
1 | //===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===// |
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 isa<X>(), cast<X>(), dyn_cast<X>(), |
10 | // cast_if_present<X>(), and dyn_cast_if_present<X>() templates. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_SUPPORT_CASTING_H |
15 | #define LLVM_SUPPORT_CASTING_H |
16 | |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/type_traits.h" |
19 | #include <cassert> |
20 | #include <memory> |
21 | #include <optional> |
22 | #include <type_traits> |
23 | |
24 | namespace llvm { |
25 | |
26 | //===----------------------------------------------------------------------===// |
27 | // simplify_type |
28 | //===----------------------------------------------------------------------===// |
29 | |
30 | /// Define a template that can be specialized by smart pointers to reflect the |
31 | /// fact that they are automatically dereferenced, and are not involved with the |
32 | /// template selection process... the default implementation is a noop. |
33 | // TODO: rename this and/or replace it with other cast traits. |
34 | template <typename From> struct simplify_type { |
35 | using SimpleType = From; // The real type this represents... |
36 | |
37 | // An accessor to get the real value... |
38 | static SimpleType &getSimplifiedValue(From &Val) { return Val; } |
39 | }; |
40 | |
41 | template <typename From> struct simplify_type<const From> { |
42 | using NonConstSimpleType = typename simplify_type<From>::SimpleType; |
43 | using SimpleType = typename add_const_past_pointer<NonConstSimpleType>::type; |
44 | using RetType = |
45 | typename add_lvalue_reference_if_not_pointer<SimpleType>::type; |
46 | |
47 | static RetType getSimplifiedValue(const From &Val) { |
48 | return simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val)); |
49 | } |
50 | }; |
51 | |
52 | // TODO: add this namespace once everyone is switched to using the new |
53 | // interface. |
54 | // namespace detail { |
55 | |
56 | //===----------------------------------------------------------------------===// |
57 | // isa_impl |
58 | //===----------------------------------------------------------------------===// |
59 | |
60 | // The core of the implementation of isa<X> is here; To and From should be |
61 | // the names of classes. This template can be specialized to customize the |
62 | // implementation of isa<> without rewriting it from scratch. |
63 | template <typename To, typename From, typename Enabler = void> struct isa_impl { |
64 | static inline bool doit(const From &Val) { return To::classof(&Val); } |
65 | }; |
66 | |
67 | // Always allow upcasts, and perform no dynamic check for them. |
68 | template <typename To, typename From> |
69 | struct isa_impl<To, From, std::enable_if_t<std::is_base_of<To, From>::value>> { |
70 | static inline bool doit(const From &) { return true; } |
71 | }; |
72 | |
73 | template <typename To, typename From> struct isa_impl_cl { |
74 | static inline bool doit(const From &Val) { |
75 | return isa_impl<To, From>::doit(Val); |
76 | } |
77 | }; |
78 | |
79 | template <typename To, typename From> struct isa_impl_cl<To, const From> { |
80 | static inline bool doit(const From &Val) { |
81 | return isa_impl<To, From>::doit(Val); |
82 | } |
83 | }; |
84 | |
85 | template <typename To, typename From> |
86 | struct isa_impl_cl<To, const std::unique_ptr<From>> { |
87 | static inline bool doit(const std::unique_ptr<From> &Val) { |
88 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 88, __extension__ __PRETTY_FUNCTION__ )); |
89 | return isa_impl_cl<To, From>::doit(*Val); |
90 | } |
91 | }; |
92 | |
93 | template <typename To, typename From> struct isa_impl_cl<To, From *> { |
94 | static inline bool doit(const From *Val) { |
95 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 95, __extension__ __PRETTY_FUNCTION__ )); |
96 | return isa_impl<To, From>::doit(*Val); |
97 | } |
98 | }; |
99 | |
100 | template <typename To, typename From> struct isa_impl_cl<To, From *const> { |
101 | static inline bool doit(const From *Val) { |
102 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 102, __extension__ __PRETTY_FUNCTION__ )); |
103 | return isa_impl<To, From>::doit(*Val); |
104 | } |
105 | }; |
106 | |
107 | template <typename To, typename From> struct isa_impl_cl<To, const From *> { |
108 | static inline bool doit(const From *Val) { |
109 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 109, __extension__ __PRETTY_FUNCTION__ )); |
110 | return isa_impl<To, From>::doit(*Val); |
111 | } |
112 | }; |
113 | |
114 | template <typename To, typename From> |
115 | struct isa_impl_cl<To, const From *const> { |
116 | static inline bool doit(const From *Val) { |
117 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 117, __extension__ __PRETTY_FUNCTION__ )); |
118 | return isa_impl<To, From>::doit(*Val); |
119 | } |
120 | }; |
121 | |
122 | template <typename To, typename From, typename SimpleFrom> |
123 | struct isa_impl_wrap { |
124 | // When From != SimplifiedType, we can simplify the type some more by using |
125 | // the simplify_type template. |
126 | static bool doit(const From &Val) { |
127 | return isa_impl_wrap<To, SimpleFrom, |
128 | typename simplify_type<SimpleFrom>::SimpleType>:: |
129 | doit(simplify_type<const From>::getSimplifiedValue(Val)); |
130 | } |
131 | }; |
132 | |
133 | template <typename To, typename FromTy> |
134 | struct isa_impl_wrap<To, FromTy, FromTy> { |
135 | // When From == SimpleType, we are as simple as we are going to get. |
136 | static bool doit(const FromTy &Val) { |
137 | return isa_impl_cl<To, FromTy>::doit(Val); |
138 | } |
139 | }; |
140 | |
141 | //===----------------------------------------------------------------------===// |
142 | // cast_retty + cast_retty_impl |
143 | //===----------------------------------------------------------------------===// |
144 | |
145 | template <class To, class From> struct cast_retty; |
146 | |
147 | // Calculate what type the 'cast' function should return, based on a requested |
148 | // type of To and a source type of From. |
149 | template <class To, class From> struct cast_retty_impl { |
150 | using ret_type = To &; // Normal case, return Ty& |
151 | }; |
152 | template <class To, class From> struct cast_retty_impl<To, const From> { |
153 | using ret_type = const To &; // Normal case, return Ty& |
154 | }; |
155 | |
156 | template <class To, class From> struct cast_retty_impl<To, From *> { |
157 | using ret_type = To *; // Pointer arg case, return Ty* |
158 | }; |
159 | |
160 | template <class To, class From> struct cast_retty_impl<To, const From *> { |
161 | using ret_type = const To *; // Constant pointer arg case, return const Ty* |
162 | }; |
163 | |
164 | template <class To, class From> struct cast_retty_impl<To, const From *const> { |
165 | using ret_type = const To *; // Constant pointer arg case, return const Ty* |
166 | }; |
167 | |
168 | template <class To, class From> |
169 | struct cast_retty_impl<To, std::unique_ptr<From>> { |
170 | private: |
171 | using PointerType = typename cast_retty_impl<To, From *>::ret_type; |
172 | using ResultType = std::remove_pointer_t<PointerType>; |
173 | |
174 | public: |
175 | using ret_type = std::unique_ptr<ResultType>; |
176 | }; |
177 | |
178 | template <class To, class From, class SimpleFrom> struct cast_retty_wrap { |
179 | // When the simplified type and the from type are not the same, use the type |
180 | // simplifier to reduce the type, then reuse cast_retty_impl to get the |
181 | // resultant type. |
182 | using ret_type = typename cast_retty<To, SimpleFrom>::ret_type; |
183 | }; |
184 | |
185 | template <class To, class FromTy> struct cast_retty_wrap<To, FromTy, FromTy> { |
186 | // When the simplified type is equal to the from type, use it directly. |
187 | using ret_type = typename cast_retty_impl<To, FromTy>::ret_type; |
188 | }; |
189 | |
190 | template <class To, class From> struct cast_retty { |
191 | using ret_type = typename cast_retty_wrap< |
192 | To, From, typename simplify_type<From>::SimpleType>::ret_type; |
193 | }; |
194 | |
195 | //===----------------------------------------------------------------------===// |
196 | // cast_convert_val |
197 | //===----------------------------------------------------------------------===// |
198 | |
199 | // Ensure the non-simple values are converted using the simplify_type template |
200 | // that may be specialized by smart pointers... |
201 | // |
202 | template <class To, class From, class SimpleFrom> struct cast_convert_val { |
203 | // This is not a simple type, use the template to simplify it... |
204 | static typename cast_retty<To, From>::ret_type doit(const From &Val) { |
205 | return cast_convert_val<To, SimpleFrom, |
206 | typename simplify_type<SimpleFrom>::SimpleType>:: |
207 | doit(simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val))); |
208 | } |
209 | }; |
210 | |
211 | template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> { |
212 | // If it's a reference, switch to a pointer to do the cast and then deref it. |
213 | static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { |
214 | return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type> |
215 | *)&const_cast<FromTy &>(Val); |
216 | } |
217 | }; |
218 | |
219 | template <class To, class FromTy> |
220 | struct cast_convert_val<To, FromTy *, FromTy *> { |
221 | // If it's a pointer, we can use c-style casting directly. |
222 | static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) { |
223 | return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>( |
224 | Val); |
225 | } |
226 | }; |
227 | |
228 | //===----------------------------------------------------------------------===// |
229 | // is_simple_type |
230 | //===----------------------------------------------------------------------===// |
231 | |
232 | template <class X> struct is_simple_type { |
233 | static const bool value = |
234 | std::is_same<X, typename simplify_type<X>::SimpleType>::value; |
235 | }; |
236 | |
237 | // } // namespace detail |
238 | |
239 | //===----------------------------------------------------------------------===// |
240 | // CastIsPossible |
241 | //===----------------------------------------------------------------------===// |
242 | |
243 | /// This struct provides a way to check if a given cast is possible. It provides |
244 | /// a static function called isPossible that is used to check if a cast can be |
245 | /// performed. It should be overridden like this: |
246 | /// |
247 | /// template<> struct CastIsPossible<foo, bar> { |
248 | /// static inline bool isPossible(const bar &b) { |
249 | /// return bar.isFoo(); |
250 | /// } |
251 | /// }; |
252 | template <typename To, typename From, typename Enable = void> |
253 | struct CastIsPossible { |
254 | static inline bool isPossible(const From &f) { |
255 | return isa_impl_wrap< |
256 | To, const From, |
257 | typename simplify_type<const From>::SimpleType>::doit(f); |
258 | } |
259 | }; |
260 | |
261 | // Needed for optional unwrapping. This could be implemented with isa_impl, but |
262 | // we want to implement things in the new method and move old implementations |
263 | // over. In fact, some of the isa_impl templates should be moved over to |
264 | // CastIsPossible. |
265 | template <typename To, typename From> |
266 | struct CastIsPossible<To, std::optional<From>> { |
267 | static inline bool isPossible(const std::optional<From> &f) { |
268 | assert(f && "CastIsPossible::isPossible called on a nullopt!")(static_cast <bool> (f && "CastIsPossible::isPossible called on a nullopt!" ) ? void (0) : __assert_fail ("f && \"CastIsPossible::isPossible called on a nullopt!\"" , "llvm/include/llvm/Support/Casting.h", 268, __extension__ __PRETTY_FUNCTION__ )); |
269 | return isa_impl_wrap< |
270 | To, const From, |
271 | typename simplify_type<const From>::SimpleType>::doit(*f); |
272 | } |
273 | }; |
274 | |
275 | /// Upcasting (from derived to base) and casting from a type to itself should |
276 | /// always be possible. |
277 | template <typename To, typename From> |
278 | struct CastIsPossible<To, From, |
279 | std::enable_if_t<std::is_base_of<To, From>::value>> { |
280 | static inline bool isPossible(const From &f) { return true; } |
281 | }; |
282 | |
283 | //===----------------------------------------------------------------------===// |
284 | // Cast traits |
285 | //===----------------------------------------------------------------------===// |
286 | |
287 | /// All of these cast traits are meant to be implementations for useful casts |
288 | /// that users may want to use that are outside the standard behavior. An |
289 | /// example of how to use a special cast called `CastTrait` is: |
290 | /// |
291 | /// template<> struct CastInfo<foo, bar> : public CastTrait<foo, bar> {}; |
292 | /// |
293 | /// Essentially, if your use case falls directly into one of the use cases |
294 | /// supported by a given cast trait, simply inherit your special CastInfo |
295 | /// directly from one of these to avoid having to reimplement the boilerplate |
296 | /// `isPossible/castFailed/doCast/doCastIfPossible`. A cast trait can also |
297 | /// provide a subset of those functions. |
298 | |
299 | /// This cast trait just provides castFailed for the specified `To` type to make |
300 | /// CastInfo specializations more declarative. In order to use this, the target |
301 | /// result type must be `To` and `To` must be constructible from `nullptr`. |
302 | template <typename To> struct NullableValueCastFailed { |
303 | static To castFailed() { return To(nullptr); } |
304 | }; |
305 | |
306 | /// This cast trait just provides the default implementation of doCastIfPossible |
307 | /// to make CastInfo specializations more declarative. The `Derived` template |
308 | /// parameter *must* be provided for forwarding castFailed and doCast. |
309 | template <typename To, typename From, typename Derived> |
310 | struct DefaultDoCastIfPossible { |
311 | static To doCastIfPossible(From f) { |
312 | if (!Derived::isPossible(f)) |
313 | return Derived::castFailed(); |
314 | return Derived::doCast(f); |
315 | } |
316 | }; |
317 | |
318 | namespace detail { |
319 | /// A helper to derive the type to use with `Self` for cast traits, when the |
320 | /// provided CRTP derived type is allowed to be void. |
321 | template <typename OptionalDerived, typename Default> |
322 | using SelfType = std::conditional_t<std::is_same<OptionalDerived, void>::value, |
323 | Default, OptionalDerived>; |
324 | } // namespace detail |
325 | |
326 | /// This cast trait provides casting for the specific case of casting to a |
327 | /// value-typed object from a pointer-typed object. Note that `To` must be |
328 | /// nullable/constructible from a pointer to `From` to use this cast. |
329 | template <typename To, typename From, typename Derived = void> |
330 | struct ValueFromPointerCast |
331 | : public CastIsPossible<To, From *>, |
332 | public NullableValueCastFailed<To>, |
333 | public DefaultDoCastIfPossible< |
334 | To, From *, |
335 | detail::SelfType<Derived, ValueFromPointerCast<To, From>>> { |
336 | static inline To doCast(From *f) { return To(f); } |
337 | }; |
338 | |
339 | /// This cast trait provides std::unique_ptr casting. It has the semantics of |
340 | /// moving the contents of the input unique_ptr into the output unique_ptr |
341 | /// during the cast. It's also a good example of how to implement a move-only |
342 | /// cast. |
343 | template <typename To, typename From, typename Derived = void> |
344 | struct UniquePtrCast : public CastIsPossible<To, From *> { |
345 | using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>; |
346 | using CastResultType = std::unique_ptr< |
347 | std::remove_reference_t<typename cast_retty<To, From>::ret_type>>; |
348 | |
349 | static inline CastResultType doCast(std::unique_ptr<From> &&f) { |
350 | return CastResultType((typename CastResultType::element_type *)f.release()); |
351 | } |
352 | |
353 | static inline CastResultType castFailed() { return CastResultType(nullptr); } |
354 | |
355 | static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) { |
356 | if (!Self::isPossible(f)) |
357 | return castFailed(); |
358 | return doCast(f); |
359 | } |
360 | }; |
361 | |
362 | /// This cast trait provides std::optional<T> casting. This means that if you |
363 | /// have a value type, you can cast it to another value type and have dyn_cast |
364 | /// return an std::optional<T>. |
365 | template <typename To, typename From, typename Derived = void> |
366 | struct OptionalValueCast |
367 | : public CastIsPossible<To, From>, |
368 | public DefaultDoCastIfPossible< |
369 | std::optional<To>, From, |
370 | detail::SelfType<Derived, OptionalValueCast<To, From>>> { |
371 | static inline std::optional<To> castFailed() { return std::optional<To>{}; } |
372 | |
373 | static inline std::optional<To> doCast(const From &f) { return To(f); } |
374 | }; |
375 | |
376 | /// Provides a cast trait that strips `const` from types to make it easier to |
377 | /// implement a const-version of a non-const cast. It just removes boilerplate |
378 | /// and reduces the amount of code you as the user need to implement. You can |
379 | /// use it like this: |
380 | /// |
381 | /// template<> struct CastInfo<foo, bar> { |
382 | /// ...verbose implementation... |
383 | /// }; |
384 | /// |
385 | /// template<> struct CastInfo<foo, const bar> : public |
386 | /// ConstStrippingForwardingCast<foo, const bar, CastInfo<foo, bar>> {}; |
387 | /// |
388 | template <typename To, typename From, typename ForwardTo> |
389 | struct ConstStrippingForwardingCast { |
390 | // Remove the pointer if it exists, then we can get rid of consts/volatiles. |
391 | using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>; |
392 | // Now if it's a pointer, add it back. Otherwise, we want a ref. |
393 | using NonConstFrom = std::conditional_t<std::is_pointer<From>::value, |
394 | DecayedFrom *, DecayedFrom &>; |
395 | |
396 | static inline bool isPossible(const From &f) { |
397 | return ForwardTo::isPossible(const_cast<NonConstFrom>(f)); |
398 | } |
399 | |
400 | static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); } |
401 | |
402 | static inline decltype(auto) doCast(const From &f) { |
403 | return ForwardTo::doCast(const_cast<NonConstFrom>(f)); |
404 | } |
405 | |
406 | static inline decltype(auto) doCastIfPossible(const From &f) { |
407 | return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f)); |
408 | } |
409 | }; |
410 | |
411 | /// Provides a cast trait that uses a defined pointer to pointer cast as a base |
412 | /// for reference-to-reference casts. Note that it does not provide castFailed |
413 | /// and doCastIfPossible because a pointer-to-pointer cast would likely just |
414 | /// return `nullptr` which could cause nullptr dereference. You can use it like |
415 | /// this: |
416 | /// |
417 | /// template <> struct CastInfo<foo, bar *> { ... verbose implementation... }; |
418 | /// |
419 | /// template <> |
420 | /// struct CastInfo<foo, bar> |
421 | /// : public ForwardToPointerCast<foo, bar, CastInfo<foo, bar *>> {}; |
422 | /// |
423 | template <typename To, typename From, typename ForwardTo> |
424 | struct ForwardToPointerCast { |
425 | static inline bool isPossible(const From &f) { |
426 | return ForwardTo::isPossible(&f); |
427 | } |
428 | |
429 | static inline decltype(auto) doCast(const From &f) { |
430 | return *ForwardTo::doCast(&f); |
431 | } |
432 | }; |
433 | |
434 | //===----------------------------------------------------------------------===// |
435 | // CastInfo |
436 | //===----------------------------------------------------------------------===// |
437 | |
438 | /// This struct provides a method for customizing the way a cast is performed. |
439 | /// It inherits from CastIsPossible, to support the case of declaring many |
440 | /// CastIsPossible specializations without having to specialize the full |
441 | /// CastInfo. |
442 | /// |
443 | /// In order to specialize different behaviors, specify different functions in |
444 | /// your CastInfo specialization. |
445 | /// For isa<> customization, provide: |
446 | /// |
447 | /// `static bool isPossible(const From &f)` |
448 | /// |
449 | /// For cast<> customization, provide: |
450 | /// |
451 | /// `static To doCast(const From &f)` |
452 | /// |
453 | /// For dyn_cast<> and the *_if_present<> variants' customization, provide: |
454 | /// |
455 | /// `static To castFailed()` and `static To doCastIfPossible(const From &f)` |
456 | /// |
457 | /// Your specialization might look something like this: |
458 | /// |
459 | /// template<> struct CastInfo<foo, bar> : public CastIsPossible<foo, bar> { |
460 | /// static inline foo doCast(const bar &b) { |
461 | /// return foo(const_cast<bar &>(b)); |
462 | /// } |
463 | /// static inline foo castFailed() { return foo(); } |
464 | /// static inline foo doCastIfPossible(const bar &b) { |
465 | /// if (!CastInfo<foo, bar>::isPossible(b)) |
466 | /// return castFailed(); |
467 | /// return doCast(b); |
468 | /// } |
469 | /// }; |
470 | |
471 | // The default implementations of CastInfo don't use cast traits for now because |
472 | // we need to specify types all over the place due to the current expected |
473 | // casting behavior and the way cast_retty works. New use cases can and should |
474 | // take advantage of the cast traits whenever possible! |
475 | |
476 | template <typename To, typename From, typename Enable = void> |
477 | struct CastInfo : public CastIsPossible<To, From> { |
478 | using Self = CastInfo<To, From, Enable>; |
479 | |
480 | using CastReturnType = typename cast_retty<To, From>::ret_type; |
481 | |
482 | static inline CastReturnType doCast(const From &f) { |
483 | return cast_convert_val< |
484 | To, From, |
485 | typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f)); |
486 | } |
487 | |
488 | // This assumes that you can construct the cast return type from `nullptr`. |
489 | // This is largely to support legacy use cases - if you don't want this |
490 | // behavior you should specialize CastInfo for your use case. |
491 | static inline CastReturnType castFailed() { return CastReturnType(nullptr); } |
492 | |
493 | static inline CastReturnType doCastIfPossible(const From &f) { |
494 | if (!Self::isPossible(f)) |
495 | return castFailed(); |
496 | return doCast(f); |
497 | } |
498 | }; |
499 | |
500 | /// This struct provides an overload for CastInfo where From has simplify_type |
501 | /// defined. This simply forwards to the appropriate CastInfo with the |
502 | /// simplified type/value, so you don't have to implement both. |
503 | template <typename To, typename From> |
504 | struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> { |
505 | using Self = CastInfo<To, From>; |
506 | using SimpleFrom = typename simplify_type<From>::SimpleType; |
507 | using SimplifiedSelf = CastInfo<To, SimpleFrom>; |
508 | |
509 | static inline bool isPossible(From &f) { |
510 | return SimplifiedSelf::isPossible( |
511 | simplify_type<From>::getSimplifiedValue(f)); |
512 | } |
513 | |
514 | static inline decltype(auto) doCast(From &f) { |
515 | return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f)); |
516 | } |
517 | |
518 | static inline decltype(auto) castFailed() { |
519 | return SimplifiedSelf::castFailed(); |
520 | } |
521 | |
522 | static inline decltype(auto) doCastIfPossible(From &f) { |
523 | return SimplifiedSelf::doCastIfPossible( |
524 | simplify_type<From>::getSimplifiedValue(f)); |
525 | } |
526 | }; |
527 | |
528 | //===----------------------------------------------------------------------===// |
529 | // Pre-specialized CastInfo |
530 | //===----------------------------------------------------------------------===// |
531 | |
532 | /// Provide a CastInfo specialized for std::unique_ptr. |
533 | template <typename To, typename From> |
534 | struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {}; |
535 | |
536 | /// Provide a CastInfo specialized for std::optional<From>. It's assumed that if |
537 | /// the input is std::optional<From> that the output can be std::optional<To>. |
538 | /// If that's not the case, specialize CastInfo for your use case. |
539 | template <typename To, typename From> |
540 | struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> { |
541 | }; |
542 | |
543 | /// isa<X> - Return true if the parameter to the template is an instance of one |
544 | /// of the template type arguments. Used like this: |
545 | /// |
546 | /// if (isa<Type>(myVal)) { ... } |
547 | /// if (isa<Type0, Type1, Type2>(myVal)) { ... } |
548 | template <typename To, typename From> |
549 | [[nodiscard]] inline bool isa(const From &Val) { |
550 | return CastInfo<To, const From>::isPossible(Val); |
551 | } |
552 | |
553 | template <typename First, typename Second, typename... Rest, typename From> |
554 | [[nodiscard]] inline bool isa(const From &Val) { |
555 | return isa<First>(Val) || isa<Second, Rest...>(Val); |
556 | } |
557 | |
558 | /// cast<X> - Return the argument parameter cast to the specified type. This |
559 | /// casting operator asserts that the type is correct, so it does not return |
560 | /// null on failure. It does not allow a null argument (use cast_if_present for |
561 | /// that). It is typically used like this: |
562 | /// |
563 | /// cast<Instruction>(myVal)->getParent() |
564 | |
565 | template <typename To, typename From> |
566 | [[nodiscard]] inline decltype(auto) cast(const From &Val) { |
567 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 567, __extension__ __PRETTY_FUNCTION__ )); |
568 | return CastInfo<To, const From>::doCast(Val); |
569 | } |
570 | |
571 | template <typename To, typename From> |
572 | [[nodiscard]] inline decltype(auto) cast(From &Val) { |
573 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 573, __extension__ __PRETTY_FUNCTION__ )); |
574 | return CastInfo<To, From>::doCast(Val); |
575 | } |
576 | |
577 | template <typename To, typename From> |
578 | [[nodiscard]] inline decltype(auto) cast(From *Val) { |
579 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 579, __extension__ __PRETTY_FUNCTION__ )); |
580 | return CastInfo<To, From *>::doCast(Val); |
581 | } |
582 | |
583 | template <typename To, typename From> |
584 | [[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) { |
585 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 585, __extension__ __PRETTY_FUNCTION__ )); |
586 | return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val)); |
587 | } |
588 | |
589 | //===----------------------------------------------------------------------===// |
590 | // ValueIsPresent |
591 | //===----------------------------------------------------------------------===// |
592 | |
593 | template <typename T> |
594 | constexpr bool IsNullable = |
595 | std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>; |
596 | |
597 | /// ValueIsPresent provides a way to check if a value is, well, present. For |
598 | /// pointers, this is the equivalent of checking against nullptr, for Optionals |
599 | /// this is the equivalent of checking hasValue(). It also provides a method for |
600 | /// unwrapping a value (think calling .value() on an optional). |
601 | |
602 | // Generic values can't *not* be present. |
603 | template <typename T, typename Enable = void> struct ValueIsPresent { |
604 | using UnwrappedType = T; |
605 | static inline bool isPresent(const T &t) { return true; } |
606 | static inline decltype(auto) unwrapValue(T &t) { return t; } |
607 | }; |
608 | |
609 | // Optional provides its own way to check if something is present. |
610 | template <typename T> struct ValueIsPresent<std::optional<T>> { |
611 | using UnwrappedType = T; |
612 | static inline bool isPresent(const std::optional<T> &t) { |
613 | return t.has_value(); |
614 | } |
615 | static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; } |
616 | }; |
617 | |
618 | // If something is "nullable" then we just compare it to nullptr to see if it |
619 | // exists. |
620 | template <typename T> |
621 | struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> { |
622 | using UnwrappedType = T; |
623 | static inline bool isPresent(const T &t) { return t != T(nullptr); } |
624 | static inline decltype(auto) unwrapValue(T &t) { return t; } |
625 | }; |
626 | |
627 | namespace detail { |
628 | // Convenience function we can use to check if a value is present. Because of |
629 | // simplify_type, we have to call it on the simplified type for now. |
630 | template <typename T> inline bool isPresent(const T &t) { |
631 | return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent( |
632 | simplify_type<T>::getSimplifiedValue(const_cast<T &>(t))); |
633 | } |
634 | |
635 | // Convenience function we can use to unwrap a value. |
636 | template <typename T> inline decltype(auto) unwrapValue(T &t) { |
637 | return ValueIsPresent<T>::unwrapValue(t); |
638 | } |
639 | } // namespace detail |
640 | |
641 | /// dyn_cast<X> - Return the argument parameter cast to the specified type. This |
642 | /// casting operator returns null if the argument is of the wrong type, so it |
643 | /// can be used to test for a type as well as cast if successful. The value |
644 | /// passed in must be present, if not, use dyn_cast_if_present. This should be |
645 | /// used in the context of an if statement like this: |
646 | /// |
647 | /// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } |
648 | |
649 | template <typename To, typename From> |
650 | [[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) { |
651 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 651, __extension__ __PRETTY_FUNCTION__ )); |
652 | return CastInfo<To, const From>::doCastIfPossible(Val); |
653 | } |
654 | |
655 | template <typename To, typename From> |
656 | [[nodiscard]] inline decltype(auto) dyn_cast(From &Val) { |
657 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 657, __extension__ __PRETTY_FUNCTION__ )); |
658 | return CastInfo<To, From>::doCastIfPossible(Val); |
659 | } |
660 | |
661 | template <typename To, typename From> |
662 | [[nodiscard]] inline decltype(auto) dyn_cast(From *Val) { |
663 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 663, __extension__ __PRETTY_FUNCTION__ )); |
664 | return CastInfo<To, From *>::doCastIfPossible(Val); |
665 | } |
666 | |
667 | template <typename To, typename From> |
668 | [[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) { |
669 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 669, __extension__ __PRETTY_FUNCTION__ )); |
670 | return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible( |
671 | std::forward<std::unique_ptr<From> &&>(Val)); |
672 | } |
673 | |
674 | /// isa_and_present<X> - Functionally identical to isa, except that a null value |
675 | /// is accepted. |
676 | template <typename... X, class Y> |
677 | [[nodiscard]] inline bool isa_and_present(const Y &Val) { |
678 | if (!detail::isPresent(Val)) |
679 | return false; |
680 | return isa<X...>(Val); |
681 | } |
682 | |
683 | template <typename... X, class Y> |
684 | [[nodiscard]] inline bool isa_and_nonnull(const Y &Val) { |
685 | return isa_and_present<X...>(Val); |
686 | } |
687 | |
688 | /// cast_if_present<X> - Functionally identical to cast, except that a null |
689 | /// value is accepted. |
690 | template <class X, class Y> |
691 | [[nodiscard]] inline auto cast_if_present(const Y &Val) { |
692 | if (!detail::isPresent(Val)) |
693 | return CastInfo<X, const Y>::castFailed(); |
694 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 694, __extension__ __PRETTY_FUNCTION__ )); |
695 | return cast<X>(detail::unwrapValue(Val)); |
696 | } |
697 | |
698 | template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) { |
699 | if (!detail::isPresent(Val)) |
700 | return CastInfo<X, Y>::castFailed(); |
701 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 701, __extension__ __PRETTY_FUNCTION__ )); |
702 | return cast<X>(detail::unwrapValue(Val)); |
703 | } |
704 | |
705 | template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) { |
706 | if (!detail::isPresent(Val)) |
707 | return CastInfo<X, Y *>::castFailed(); |
708 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 708, __extension__ __PRETTY_FUNCTION__ )); |
709 | return cast<X>(detail::unwrapValue(Val)); |
710 | } |
711 | |
712 | template <class X, class Y> |
713 | [[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) { |
714 | if (!detail::isPresent(Val)) |
715 | return UniquePtrCast<X, Y>::castFailed(); |
716 | return UniquePtrCast<X, Y>::doCast(std::move(Val)); |
717 | } |
718 | |
719 | // Provide a forwarding from cast_or_null to cast_if_present for current |
720 | // users. This is deprecated and will be removed in a future patch, use |
721 | // cast_if_present instead. |
722 | template <class X, class Y> auto cast_or_null(const Y &Val) { |
723 | return cast_if_present<X>(Val); |
724 | } |
725 | |
726 | template <class X, class Y> auto cast_or_null(Y &Val) { |
727 | return cast_if_present<X>(Val); |
728 | } |
729 | |
730 | template <class X, class Y> auto cast_or_null(Y *Val) { |
731 | return cast_if_present<X>(Val); |
732 | } |
733 | |
734 | template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) { |
735 | return cast_if_present<X>(std::move(Val)); |
736 | } |
737 | |
738 | /// dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a |
739 | /// null (or none in the case of optionals) value is accepted. |
740 | template <class X, class Y> auto dyn_cast_if_present(const Y &Val) { |
741 | if (!detail::isPresent(Val)) |
742 | return CastInfo<X, const Y>::castFailed(); |
743 | return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val)); |
744 | } |
745 | |
746 | template <class X, class Y> auto dyn_cast_if_present(Y &Val) { |
747 | if (!detail::isPresent(Val)) |
748 | return CastInfo<X, Y>::castFailed(); |
749 | return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val)); |
750 | } |
751 | |
752 | template <class X, class Y> auto dyn_cast_if_present(Y *Val) { |
753 | if (!detail::isPresent(Val)) |
754 | return CastInfo<X, Y *>::castFailed(); |
755 | return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val)); |
756 | } |
757 | |
758 | // Forwards to dyn_cast_if_present to avoid breaking current users. This is |
759 | // deprecated and will be removed in a future patch, use |
760 | // cast_if_present instead. |
761 | template <class X, class Y> auto dyn_cast_or_null(const Y &Val) { |
762 | return dyn_cast_if_present<X>(Val); |
763 | } |
764 | |
765 | template <class X, class Y> auto dyn_cast_or_null(Y &Val) { |
766 | return dyn_cast_if_present<X>(Val); |
767 | } |
768 | |
769 | template <class X, class Y> auto dyn_cast_or_null(Y *Val) { |
770 | return dyn_cast_if_present<X>(Val); |
771 | } |
772 | |
773 | /// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>, |
774 | /// taking ownership of the input pointer iff isa<X>(Val) is true. If the |
775 | /// cast is successful, From refers to nullptr on exit and the casted value |
776 | /// is returned. If the cast is unsuccessful, the function returns nullptr |
777 | /// and From is unchanged. |
778 | template <class X, class Y> |
779 | [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType |
780 | unique_dyn_cast(std::unique_ptr<Y> &Val) { |
781 | if (!isa<X>(Val)) |
782 | return nullptr; |
783 | return cast<X>(std::move(Val)); |
784 | } |
785 | |
786 | template <class X, class Y> |
787 | [[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) { |
788 | return unique_dyn_cast<X, Y>(Val); |
789 | } |
790 | |
791 | // unique_dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast, |
792 | // except that a null value is accepted. |
793 | template <class X, class Y> |
794 | [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType |
795 | unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) { |
796 | if (!Val) |
797 | return nullptr; |
798 | return unique_dyn_cast<X, Y>(Val); |
799 | } |
800 | |
801 | template <class X, class Y> |
802 | [[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) { |
803 | return unique_dyn_cast_or_null<X, Y>(Val); |
804 | } |
805 | |
806 | } // end namespace llvm |
807 | |
808 | #endif // LLVM_SUPPORT_CASTING_H |