File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/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 | |||||||||
22 | using namespace clang; | ||||||||
23 | |||||||||
24 | //---------------------------------------------------------------------------- | ||||||||
25 | // Visitor that collects unexpanded parameter packs | ||||||||
26 | //---------------------------------------------------------------------------- | ||||||||
27 | |||||||||
28 | namespace { | ||||||||
29 | /// A class that collects unexpanded parameter packs. | ||||||||
30 | class CollectUnexpandedParameterPacksVisitor : | ||||||||
31 | public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> | ||||||||
32 | { | ||||||||
33 | typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> | ||||||||
34 | inherited; | ||||||||
35 | |||||||||
36 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded; | ||||||||
37 | |||||||||
38 | bool InLambda = false; | ||||||||
39 | unsigned DepthLimit = (unsigned)-1; | ||||||||
40 | |||||||||
41 | void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) { | ||||||||
42 | if (auto *VD = dyn_cast<VarDecl>(ND)) { | ||||||||
43 | // For now, the only problematic case is a generic lambda's templated | ||||||||
44 | // call operator, so we don't need to look for all the other ways we | ||||||||
45 | // could have reached a dependent parameter pack. | ||||||||
46 | auto *FD = dyn_cast<FunctionDecl>(VD->getDeclContext()); | ||||||||
47 | auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr; | ||||||||
48 | if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit) | ||||||||
49 | return; | ||||||||
50 | } else if (getDepthAndIndex(ND).first >= DepthLimit) | ||||||||
51 | return; | ||||||||
52 | |||||||||
53 | Unexpanded.push_back({ND, Loc}); | ||||||||
54 | } | ||||||||
55 | void addUnexpanded(const TemplateTypeParmType *T, | ||||||||
56 | SourceLocation Loc = SourceLocation()) { | ||||||||
57 | if (T->getDepth() < DepthLimit) | ||||||||
58 | Unexpanded.push_back({T, Loc}); | ||||||||
59 | } | ||||||||
60 | |||||||||
61 | public: | ||||||||
62 | explicit CollectUnexpandedParameterPacksVisitor( | ||||||||
63 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) | ||||||||
64 | : Unexpanded(Unexpanded) {} | ||||||||
65 | |||||||||
66 | bool shouldWalkTypesOfTypeLocs() const { return false; } | ||||||||
67 | |||||||||
68 | //------------------------------------------------------------------------ | ||||||||
69 | // Recording occurrences of (unexpanded) parameter packs. | ||||||||
70 | //------------------------------------------------------------------------ | ||||||||
71 | |||||||||
72 | /// Record occurrences of template type parameter packs. | ||||||||
73 | bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { | ||||||||
74 | if (TL.getTypePtr()->isParameterPack()) | ||||||||
75 | addUnexpanded(TL.getTypePtr(), TL.getNameLoc()); | ||||||||
76 | return true; | ||||||||
77 | } | ||||||||
78 | |||||||||
79 | /// Record occurrences of template type parameter packs | ||||||||
80 | /// when we don't have proper source-location information for | ||||||||
81 | /// them. | ||||||||
82 | /// | ||||||||
83 | /// Ideally, this routine would never be used. | ||||||||
84 | bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { | ||||||||
85 | if (T->isParameterPack()) | ||||||||
86 | addUnexpanded(T); | ||||||||
87 | |||||||||
88 | return true; | ||||||||
89 | } | ||||||||
90 | |||||||||
91 | /// Record occurrences of function and non-type template | ||||||||
92 | /// parameter packs in an expression. | ||||||||
93 | bool VisitDeclRefExpr(DeclRefExpr *E) { | ||||||||
94 | if (E->getDecl()->isParameterPack()) | ||||||||
95 | addUnexpanded(E->getDecl(), E->getLocation()); | ||||||||
96 | |||||||||
97 | return true; | ||||||||
98 | } | ||||||||
99 | |||||||||
100 | /// Record occurrences of template template parameter packs. | ||||||||
101 | bool TraverseTemplateName(TemplateName Template) { | ||||||||
102 | if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>( | ||||||||
103 | Template.getAsTemplateDecl())) { | ||||||||
104 | if (TTP->isParameterPack()) | ||||||||
105 | addUnexpanded(TTP); | ||||||||
106 | } | ||||||||
107 | |||||||||
108 | return inherited::TraverseTemplateName(Template); | ||||||||
109 | } | ||||||||
110 | |||||||||
111 | /// Suppress traversal into Objective-C container literal | ||||||||
112 | /// elements that are pack expansions. | ||||||||
113 | bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { | ||||||||
114 | if (!E->containsUnexpandedParameterPack()) | ||||||||
115 | return true; | ||||||||
116 | |||||||||
117 | for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { | ||||||||
118 | ObjCDictionaryElement Element = E->getKeyValueElement(I); | ||||||||
119 | if (Element.isPackExpansion()) | ||||||||
120 | continue; | ||||||||
121 | |||||||||
122 | TraverseStmt(Element.Key); | ||||||||
123 | TraverseStmt(Element.Value); | ||||||||
124 | } | ||||||||
125 | return true; | ||||||||
126 | } | ||||||||
127 | //------------------------------------------------------------------------ | ||||||||
128 | // Pruning the search for unexpanded parameter packs. | ||||||||
129 | //------------------------------------------------------------------------ | ||||||||
130 | |||||||||
131 | /// Suppress traversal into statements and expressions that | ||||||||
132 | /// do not contain unexpanded parameter packs. | ||||||||
133 | bool TraverseStmt(Stmt *S) { | ||||||||
134 | Expr *E = dyn_cast_or_null<Expr>(S); | ||||||||
135 | if ((E && E->containsUnexpandedParameterPack()) || InLambda) | ||||||||
136 | return inherited::TraverseStmt(S); | ||||||||
137 | |||||||||
138 | return true; | ||||||||
139 | } | ||||||||
140 | |||||||||
141 | /// Suppress traversal into types that do not contain | ||||||||
142 | /// unexpanded parameter packs. | ||||||||
143 | bool TraverseType(QualType T) { | ||||||||
144 | if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda) | ||||||||
145 | return inherited::TraverseType(T); | ||||||||
146 | |||||||||
147 | return true; | ||||||||
148 | } | ||||||||
149 | |||||||||
150 | /// Suppress traversal into types with location information | ||||||||
151 | /// that do not contain unexpanded parameter packs. | ||||||||
152 | bool TraverseTypeLoc(TypeLoc TL) { | ||||||||
153 | if ((!TL.getType().isNull() && | ||||||||
154 | TL.getType()->containsUnexpandedParameterPack()) || | ||||||||
155 | InLambda) | ||||||||
156 | return inherited::TraverseTypeLoc(TL); | ||||||||
157 | |||||||||
158 | return true; | ||||||||
159 | } | ||||||||
160 | |||||||||
161 | /// Suppress traversal of parameter packs. | ||||||||
162 | bool TraverseDecl(Decl *D) { | ||||||||
163 | // A function parameter pack is a pack expansion, so cannot contain | ||||||||
164 | // an unexpanded parameter pack. Likewise for a template parameter | ||||||||
165 | // pack that contains any references to other packs. | ||||||||
166 | if (D && D->isParameterPack()) | ||||||||
167 | return true; | ||||||||
168 | |||||||||
169 | return inherited::TraverseDecl(D); | ||||||||
170 | } | ||||||||
171 | |||||||||
172 | /// Suppress traversal of pack-expanded attributes. | ||||||||
173 | bool TraverseAttr(Attr *A) { | ||||||||
174 | if (A->isPackExpansion()) | ||||||||
175 | return true; | ||||||||
176 | |||||||||
177 | return inherited::TraverseAttr(A); | ||||||||
178 | } | ||||||||
179 | |||||||||
180 | /// Suppress traversal of pack expansion expressions and types. | ||||||||
181 | ///@{ | ||||||||
182 | bool TraversePackExpansionType(PackExpansionType *T) { return true; } | ||||||||
183 | bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; } | ||||||||
184 | bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; } | ||||||||
185 | bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; } | ||||||||
186 | |||||||||
187 | ///@} | ||||||||
188 | |||||||||
189 | /// Suppress traversal of using-declaration pack expansion. | ||||||||
190 | bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { | ||||||||
191 | if (D->isPackExpansion()) | ||||||||
192 | return true; | ||||||||
193 | |||||||||
194 | return inherited::TraverseUnresolvedUsingValueDecl(D); | ||||||||
195 | } | ||||||||
196 | |||||||||
197 | /// Suppress traversal of using-declaration pack expansion. | ||||||||
198 | bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { | ||||||||
199 | if (D->isPackExpansion()) | ||||||||
200 | return true; | ||||||||
201 | |||||||||
202 | return inherited::TraverseUnresolvedUsingTypenameDecl(D); | ||||||||
203 | } | ||||||||
204 | |||||||||
205 | /// Suppress traversal of template argument pack expansions. | ||||||||
206 | bool TraverseTemplateArgument(const TemplateArgument &Arg) { | ||||||||
207 | if (Arg.isPackExpansion()) | ||||||||
208 | return true; | ||||||||
209 | |||||||||
210 | return inherited::TraverseTemplateArgument(Arg); | ||||||||
211 | } | ||||||||
212 | |||||||||
213 | /// Suppress traversal of template argument pack expansions. | ||||||||
214 | bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { | ||||||||
215 | if (ArgLoc.getArgument().isPackExpansion()) | ||||||||
216 | return true; | ||||||||
217 | |||||||||
218 | return inherited::TraverseTemplateArgumentLoc(ArgLoc); | ||||||||
219 | } | ||||||||
220 | |||||||||
221 | /// Suppress traversal of base specifier pack expansions. | ||||||||
222 | bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) { | ||||||||
223 | if (Base.isPackExpansion()) | ||||||||
224 | return true; | ||||||||
225 | |||||||||
226 | return inherited::TraverseCXXBaseSpecifier(Base); | ||||||||
227 | } | ||||||||
228 | |||||||||
229 | /// Suppress traversal of mem-initializer pack expansions. | ||||||||
230 | bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { | ||||||||
231 | if (Init->isPackExpansion()) | ||||||||
232 | return true; | ||||||||
233 | |||||||||
234 | return inherited::TraverseConstructorInitializer(Init); | ||||||||
235 | } | ||||||||
236 | |||||||||
237 | /// Note whether we're traversing a lambda containing an unexpanded | ||||||||
238 | /// parameter pack. In this case, the unexpanded pack can occur anywhere, | ||||||||
239 | /// including all the places where we normally wouldn't look. Within a | ||||||||
240 | /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit | ||||||||
241 | /// outside an expression. | ||||||||
242 | bool TraverseLambdaExpr(LambdaExpr *Lambda) { | ||||||||
243 | // The ContainsUnexpandedParameterPack bit on a lambda is always correct, | ||||||||
244 | // even if it's contained within another lambda. | ||||||||
245 | if (!Lambda->containsUnexpandedParameterPack()) | ||||||||
246 | return true; | ||||||||
247 | |||||||||
248 | bool WasInLambda = InLambda; | ||||||||
249 | unsigned OldDepthLimit = DepthLimit; | ||||||||
250 | |||||||||
251 | InLambda = true; | ||||||||
252 | if (auto *TPL = Lambda->getTemplateParameterList()) | ||||||||
253 | DepthLimit = TPL->getDepth(); | ||||||||
254 | |||||||||
255 | inherited::TraverseLambdaExpr(Lambda); | ||||||||
256 | |||||||||
257 | InLambda = WasInLambda; | ||||||||
258 | DepthLimit = OldDepthLimit; | ||||||||
259 | return true; | ||||||||
260 | } | ||||||||
261 | |||||||||
262 | /// Suppress traversal within pack expansions in lambda captures. | ||||||||
263 | bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C, | ||||||||
264 | Expr *Init) { | ||||||||
265 | if (C->isPackExpansion()) | ||||||||
266 | return true; | ||||||||
267 | |||||||||
268 | return inherited::TraverseLambdaCapture(Lambda, C, Init); | ||||||||
269 | } | ||||||||
270 | }; | ||||||||
271 | } | ||||||||
272 | |||||||||
273 | /// Determine whether it's possible for an unexpanded parameter pack to | ||||||||
274 | /// be valid in this location. This only happens when we're in a declaration | ||||||||
275 | /// that is nested within an expression that could be expanded, such as a | ||||||||
276 | /// lambda-expression within a function call. | ||||||||
277 | /// | ||||||||
278 | /// This is conservatively correct, but may claim that some unexpanded packs are | ||||||||
279 | /// permitted when they are not. | ||||||||
280 | bool Sema::isUnexpandedParameterPackPermitted() { | ||||||||
281 | for (auto *SI : FunctionScopes) | ||||||||
282 | if (isa<sema::LambdaScopeInfo>(SI)) | ||||||||
283 | return true; | ||||||||
284 | return false; | ||||||||
285 | } | ||||||||
286 | |||||||||
287 | /// Diagnose all of the unexpanded parameter packs in the given | ||||||||
288 | /// vector. | ||||||||
289 | bool | ||||||||
290 | Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, | ||||||||
291 | UnexpandedParameterPackContext UPPC, | ||||||||
292 | ArrayRef<UnexpandedParameterPack> Unexpanded) { | ||||||||
293 | if (Unexpanded.empty()) | ||||||||
294 | return false; | ||||||||
295 | |||||||||
296 | // If we are within a lambda expression and referencing a pack that is not | ||||||||
297 | // declared within the lambda itself, that lambda contains an unexpanded | ||||||||
298 | // parameter pack, and we are done. | ||||||||
299 | // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it | ||||||||
300 | // later. | ||||||||
301 | SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences; | ||||||||
302 | if (auto *LSI = getEnclosingLambda()) { | ||||||||
303 | for (auto &Pack : Unexpanded) { | ||||||||
304 | auto DeclaresThisPack = [&](NamedDecl *LocalPack) { | ||||||||
305 | if (auto *TTPT = Pack.first.dyn_cast<const TemplateTypeParmType *>()) { | ||||||||
306 | auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack); | ||||||||
307 | return TTPD && TTPD->getTypeForDecl() == TTPT; | ||||||||
308 | } | ||||||||
309 | return declaresSameEntity(Pack.first.get<NamedDecl *>(), LocalPack); | ||||||||
310 | }; | ||||||||
311 | if (llvm::any_of(LSI->LocalPacks, DeclaresThisPack)) | ||||||||
312 | LambdaParamPackReferences.push_back(Pack); | ||||||||
313 | } | ||||||||
314 | |||||||||
315 | if (LambdaParamPackReferences.empty()) { | ||||||||
316 | // Construct in lambda only references packs declared outside the lambda. | ||||||||
317 | // That's OK for now, but the lambda itself is considered to contain an | ||||||||
318 | // unexpanded pack in this case, which will require expansion outside the | ||||||||
319 | // lambda. | ||||||||
320 | |||||||||
321 | // We do not permit pack expansion that would duplicate a statement | ||||||||
322 | // expression, not even within a lambda. | ||||||||
323 | // FIXME: We could probably support this for statement expressions that | ||||||||
324 | // do not contain labels. | ||||||||
325 | // FIXME: This is insufficient to detect this problem; consider | ||||||||
326 | // f( ({ bad: 0; }) + pack ... ); | ||||||||
327 | bool EnclosingStmtExpr = false; | ||||||||
328 | for (unsigned N = FunctionScopes.size(); N; --N) { | ||||||||
329 | sema::FunctionScopeInfo *Func = FunctionScopes[N-1]; | ||||||||
330 | if (llvm::any_of( | ||||||||
331 | Func->CompoundScopes, | ||||||||
332 | [](sema::CompoundScopeInfo &CSI) { return CSI.IsStmtExpr; })) { | ||||||||
333 | EnclosingStmtExpr = true; | ||||||||
334 | break; | ||||||||
335 | } | ||||||||
336 | // Coumpound-statements outside the lambda are OK for now; we'll check | ||||||||
337 | // for those when we finish handling the lambda. | ||||||||
338 | if (Func == LSI) | ||||||||
339 | break; | ||||||||
340 | } | ||||||||
341 | |||||||||
342 | if (!EnclosingStmtExpr) { | ||||||||
343 | LSI->ContainsUnexpandedParameterPack = true; | ||||||||
344 | return false; | ||||||||
345 | } | ||||||||
346 | } else { | ||||||||
347 | Unexpanded = LambdaParamPackReferences; | ||||||||
348 | } | ||||||||
349 | } | ||||||||
350 | |||||||||
351 | SmallVector<SourceLocation, 4> Locations; | ||||||||
352 | SmallVector<IdentifierInfo *, 4> Names; | ||||||||
353 | llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown; | ||||||||
354 | |||||||||
355 | for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { | ||||||||
356 | IdentifierInfo *Name = nullptr; | ||||||||
357 | if (const TemplateTypeParmType *TTP | ||||||||
358 | = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) | ||||||||
359 | Name = TTP->getIdentifier(); | ||||||||
360 | else | ||||||||
361 | Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier(); | ||||||||
362 | |||||||||
363 | if (Name && NamesKnown.insert(Name).second) | ||||||||
364 | Names.push_back(Name); | ||||||||
365 | |||||||||
366 | if (Unexpanded[I].second.isValid()) | ||||||||
367 | Locations.push_back(Unexpanded[I].second); | ||||||||
368 | } | ||||||||
369 | |||||||||
370 | auto DB = Diag(Loc, diag::err_unexpanded_parameter_pack) | ||||||||
371 | << (int)UPPC << (int)Names.size(); | ||||||||
372 | for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I) | ||||||||
373 | DB << Names[I]; | ||||||||
374 | |||||||||
375 | for (unsigned I = 0, N = Locations.size(); I != N; ++I) | ||||||||
376 | DB << SourceRange(Locations[I]); | ||||||||
377 | return true; | ||||||||
378 | } | ||||||||
379 | |||||||||
380 | bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, | ||||||||
381 | TypeSourceInfo *T, | ||||||||
382 | UnexpandedParameterPackContext UPPC) { | ||||||||
383 | // C++0x [temp.variadic]p5: | ||||||||
384 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||
385 | // ill-formed. | ||||||||
386 | if (!T->getType()->containsUnexpandedParameterPack()) | ||||||||
387 | return false; | ||||||||
388 | |||||||||
389 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||
390 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc( | ||||||||
391 | T->getTypeLoc()); | ||||||||
392 | 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", 392, __extension__ __PRETTY_FUNCTION__)); | ||||||||
393 | return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); | ||||||||
394 | } | ||||||||
395 | |||||||||
396 | bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, | ||||||||
397 | UnexpandedParameterPackContext UPPC) { | ||||||||
398 | // C++0x [temp.variadic]p5: | ||||||||
399 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||
400 | // ill-formed. | ||||||||
401 | if (!E->containsUnexpandedParameterPack()) | ||||||||
402 | return false; | ||||||||
403 | |||||||||
404 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||
405 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); | ||||||||
406 | 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", 406, __extension__ __PRETTY_FUNCTION__)); | ||||||||
407 | return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded); | ||||||||
408 | } | ||||||||
409 | |||||||||
410 | bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) { | ||||||||
411 | if (!RE->containsUnexpandedParameterPack()) | ||||||||
412 | return false; | ||||||||
413 | |||||||||
414 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||
415 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(RE); | ||||||||
416 | 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", 416, __extension__ __PRETTY_FUNCTION__)); | ||||||||
417 | |||||||||
418 | // We only care about unexpanded references to the RequiresExpr's own | ||||||||
419 | // parameter packs. | ||||||||
420 | auto Parms = RE->getLocalParameters(); | ||||||||
421 | llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end()); | ||||||||
422 | SmallVector<UnexpandedParameterPack, 2> UnexpandedParms; | ||||||||
423 | for (auto Parm : Unexpanded) | ||||||||
424 | if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl*>())) | ||||||||
425 | UnexpandedParms.push_back(Parm); | ||||||||
426 | if (UnexpandedParms.empty()) | ||||||||
427 | return false; | ||||||||
428 | |||||||||
429 | return DiagnoseUnexpandedParameterPacks(RE->getBeginLoc(), UPPC_Requirement, | ||||||||
430 | UnexpandedParms); | ||||||||
431 | } | ||||||||
432 | |||||||||
433 | bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, | ||||||||
434 | UnexpandedParameterPackContext UPPC) { | ||||||||
435 | // C++0x [temp.variadic]p5: | ||||||||
436 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||
437 | // ill-formed. | ||||||||
438 | if (!SS.getScopeRep() || | ||||||||
439 | !SS.getScopeRep()->containsUnexpandedParameterPack()) | ||||||||
440 | return false; | ||||||||
441 | |||||||||
442 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||
443 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
444 | .TraverseNestedNameSpecifier(SS.getScopeRep()); | ||||||||
445 | 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", 445, __extension__ __PRETTY_FUNCTION__)); | ||||||||
446 | return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), | ||||||||
447 | UPPC, Unexpanded); | ||||||||
448 | } | ||||||||
449 | |||||||||
450 | bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, | ||||||||
451 | UnexpandedParameterPackContext UPPC) { | ||||||||
452 | // C++0x [temp.variadic]p5: | ||||||||
453 | // An appearance of a name of a parameter pack that is not expanded is | ||||||||
454 | // ill-formed. | ||||||||
455 | switch (NameInfo.getName().getNameKind()) { | ||||||||
456 | case DeclarationName::Identifier: | ||||||||
457 | case DeclarationName::ObjCZeroArgSelector: | ||||||||
458 | case DeclarationName::ObjCOneArgSelector: | ||||||||
459 | case DeclarationName::ObjCMultiArgSelector: | ||||||||
460 | case DeclarationName::CXXOperatorName: | ||||||||
461 | case DeclarationName::CXXLiteralOperatorName: | ||||||||
462 | case DeclarationName::CXXUsingDirective: | ||||||||
463 | case DeclarationName::CXXDeductionGuideName: | ||||||||
464 | return false; | ||||||||
465 | |||||||||
466 | case DeclarationName::CXXConstructorName: | ||||||||
467 | case DeclarationName::CXXDestructorName: | ||||||||
468 | case DeclarationName::CXXConversionFunctionName: | ||||||||
469 | // FIXME: We shouldn't need this null check! | ||||||||
470 | if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) | ||||||||
471 | return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC); | ||||||||
472 | |||||||||
473 | if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack()) | ||||||||
474 | return false; | ||||||||
475 | |||||||||
476 | break; | ||||||||
477 | } | ||||||||
478 | |||||||||
479 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||
480 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
481 | .TraverseType(NameInfo.getName().getCXXNameType()); | ||||||||
482 | 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", 482, __extension__ __PRETTY_FUNCTION__)); | ||||||||
483 | return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded); | ||||||||
484 | } | ||||||||
485 | |||||||||
486 | bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, | ||||||||
487 | TemplateName Template, | ||||||||
488 | UnexpandedParameterPackContext UPPC) { | ||||||||
489 | |||||||||
490 | if (Template.isNull() || !Template.containsUnexpandedParameterPack()) | ||||||||
491 | return false; | ||||||||
492 | |||||||||
493 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||
494 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
495 | .TraverseTemplateName(Template); | ||||||||
496 | 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", 496, __extension__ __PRETTY_FUNCTION__)); | ||||||||
497 | return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); | ||||||||
498 | } | ||||||||
499 | |||||||||
500 | bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, | ||||||||
501 | UnexpandedParameterPackContext UPPC) { | ||||||||
502 | if (Arg.getArgument().isNull() || | ||||||||
503 | !Arg.getArgument().containsUnexpandedParameterPack()) | ||||||||
504 | return false; | ||||||||
505 | |||||||||
506 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | ||||||||
507 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
508 | .TraverseTemplateArgumentLoc(Arg); | ||||||||
509 | 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", 509, __extension__ __PRETTY_FUNCTION__)); | ||||||||
510 | return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded); | ||||||||
511 | } | ||||||||
512 | |||||||||
513 | void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg, | ||||||||
514 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||
515 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
516 | .TraverseTemplateArgument(Arg); | ||||||||
517 | } | ||||||||
518 | |||||||||
519 | void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg, | ||||||||
520 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||
521 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
522 | .TraverseTemplateArgumentLoc(Arg); | ||||||||
523 | } | ||||||||
524 | |||||||||
525 | void Sema::collectUnexpandedParameterPacks(QualType T, | ||||||||
526 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||
527 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T); | ||||||||
528 | } | ||||||||
529 | |||||||||
530 | void Sema::collectUnexpandedParameterPacks(TypeLoc TL, | ||||||||
531 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||
532 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL); | ||||||||
533 | } | ||||||||
534 | |||||||||
535 | void Sema::collectUnexpandedParameterPacks( | ||||||||
536 | NestedNameSpecifierLoc NNS, | ||||||||
537 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||
538 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
539 | .TraverseNestedNameSpecifierLoc(NNS); | ||||||||
540 | } | ||||||||
541 | |||||||||
542 | void Sema::collectUnexpandedParameterPacks( | ||||||||
543 | const DeclarationNameInfo &NameInfo, | ||||||||
544 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | ||||||||
545 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | ||||||||
546 | .TraverseDeclarationNameInfo(NameInfo); | ||||||||
547 | } | ||||||||
548 | |||||||||
549 | |||||||||
550 | ParsedTemplateArgument | ||||||||
551 | Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, | ||||||||
552 | SourceLocation EllipsisLoc) { | ||||||||
553 | if (Arg.isInvalid()) | ||||||||
554 | return Arg; | ||||||||
555 | |||||||||
556 | switch (Arg.getKind()) { | ||||||||
557 | case ParsedTemplateArgument::Type: { | ||||||||
558 | TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc); | ||||||||
559 | if (Result.isInvalid()) | ||||||||
560 | return ParsedTemplateArgument(); | ||||||||
561 | |||||||||
562 | return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), | ||||||||
563 | Arg.getLocation()); | ||||||||
564 | } | ||||||||
565 | |||||||||
566 | case ParsedTemplateArgument::NonType: { | ||||||||
567 | ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc); | ||||||||
568 | if (Result.isInvalid()) | ||||||||
569 | return ParsedTemplateArgument(); | ||||||||
570 | |||||||||
571 | return ParsedTemplateArgument(Arg.getKind(), Result.get(), | ||||||||
572 | Arg.getLocation()); | ||||||||
573 | } | ||||||||
574 | |||||||||
575 | case ParsedTemplateArgument::Template: | ||||||||
576 | if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) { | ||||||||
577 | SourceRange R(Arg.getLocation()); | ||||||||
578 | if (Arg.getScopeSpec().isValid()) | ||||||||
579 | R.setBegin(Arg.getScopeSpec().getBeginLoc()); | ||||||||
580 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | ||||||||
581 | << R; | ||||||||
582 | return ParsedTemplateArgument(); | ||||||||
583 | } | ||||||||
584 | |||||||||
585 | return Arg.getTemplatePackExpansion(EllipsisLoc); | ||||||||
586 | } | ||||||||
587 | llvm_unreachable("Unhandled template argument kind?")::llvm::llvm_unreachable_internal("Unhandled template argument kind?" , "clang/lib/Sema/SemaTemplateVariadic.cpp", 587); | ||||||||
588 | } | ||||||||
589 | |||||||||
590 | TypeResult Sema::ActOnPackExpansion(ParsedType Type, | ||||||||
591 | SourceLocation EllipsisLoc) { | ||||||||
592 | TypeSourceInfo *TSInfo; | ||||||||
593 | GetTypeFromParser(Type, &TSInfo); | ||||||||
594 | if (!TSInfo) | ||||||||
595 | return true; | ||||||||
596 | |||||||||
597 | TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, None); | ||||||||
598 | if (!TSResult) | ||||||||
599 | return true; | ||||||||
600 | |||||||||
601 | return CreateParsedType(TSResult->getType(), TSResult); | ||||||||
602 | } | ||||||||
603 | |||||||||
604 | TypeSourceInfo * | ||||||||
605 | Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, | ||||||||
606 | Optional<unsigned> NumExpansions) { | ||||||||
607 | // Create the pack expansion type and source-location information. | ||||||||
608 | QualType Result = CheckPackExpansion(Pattern->getType(), | ||||||||
609 | Pattern->getTypeLoc().getSourceRange(), | ||||||||
610 | EllipsisLoc, NumExpansions); | ||||||||
611 | if (Result.isNull()) | ||||||||
612 | return nullptr; | ||||||||
613 | |||||||||
614 | TypeLocBuilder TLB; | ||||||||
615 | TLB.pushFullCopy(Pattern->getTypeLoc()); | ||||||||
616 | PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result); | ||||||||
617 | TL.setEllipsisLoc(EllipsisLoc); | ||||||||
618 | |||||||||
619 | return TLB.getTypeSourceInfo(Context, Result); | ||||||||
620 | } | ||||||||
621 | |||||||||
622 | QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange, | ||||||||
623 | SourceLocation EllipsisLoc, | ||||||||
624 | Optional<unsigned> NumExpansions) { | ||||||||
625 | // C++11 [temp.variadic]p5: | ||||||||
626 | // The pattern of a pack expansion shall name one or more | ||||||||
627 | // parameter packs that are not expanded by a nested pack | ||||||||
628 | // expansion. | ||||||||
629 | // | ||||||||
630 | // A pattern containing a deduced type can't occur "naturally" but arises in | ||||||||
631 | // the desugaring of an init-capture pack. | ||||||||
632 | if (!Pattern->containsUnexpandedParameterPack() && | ||||||||
633 | !Pattern->getContainedDeducedType()) { | ||||||||
634 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | ||||||||
635 | << PatternRange; | ||||||||
636 | return QualType(); | ||||||||
637 | } | ||||||||
638 | |||||||||
639 | return Context.getPackExpansionType(Pattern, NumExpansions, | ||||||||
640 | /*ExpectPackInType=*/false); | ||||||||
641 | } | ||||||||
642 | |||||||||
643 | ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { | ||||||||
644 | return CheckPackExpansion(Pattern, EllipsisLoc, None); | ||||||||
645 | } | ||||||||
646 | |||||||||
647 | ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, | ||||||||
648 | Optional<unsigned> NumExpansions) { | ||||||||
649 | if (!Pattern) | ||||||||
650 | return ExprError(); | ||||||||
651 | |||||||||
652 | // C++0x [temp.variadic]p5: | ||||||||
653 | // The pattern of a pack expansion shall name one or more | ||||||||
654 | // parameter packs that are not expanded by a nested pack | ||||||||
655 | // expansion. | ||||||||
656 | if (!Pattern->containsUnexpandedParameterPack()) { | ||||||||
657 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | ||||||||
658 | << Pattern->getSourceRange(); | ||||||||
659 | CorrectDelayedTyposInExpr(Pattern); | ||||||||
660 | return ExprError(); | ||||||||
661 | } | ||||||||
662 | |||||||||
663 | // Create the pack expansion expression and source-location information. | ||||||||
664 | return new (Context) | ||||||||
665 | PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions); | ||||||||
666 | } | ||||||||
667 | |||||||||
668 | bool Sema::CheckParameterPacksForExpansion( | ||||||||
669 | SourceLocation EllipsisLoc, SourceRange PatternRange, | ||||||||
670 | ArrayRef<UnexpandedParameterPack> Unexpanded, | ||||||||
671 | const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, | ||||||||
672 | bool &RetainExpansion, Optional<unsigned> &NumExpansions) { | ||||||||
673 | ShouldExpand = true; | ||||||||
674 | RetainExpansion = false; | ||||||||
675 | std::pair<IdentifierInfo *, SourceLocation> FirstPack; | ||||||||
676 | bool HaveFirstPack = false; | ||||||||
677 | Optional<unsigned> NumPartialExpansions; | ||||||||
678 | SourceLocation PartiallySubstitutedPackLoc; | ||||||||
679 | |||||||||
680 | for (ArrayRef<UnexpandedParameterPack>::iterator i = Unexpanded.begin(), | ||||||||
681 | end = Unexpanded.end(); | ||||||||
682 | i != end; ++i) { | ||||||||
| |||||||||
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
|
18.1 | 'TTP' is null |
4.1 | 'IsVarDeclPack' is false |
21.1 | 'IsVarDeclPack' is true |
4.1 | 'IsVarDeclPack' is false |
21.1 | 'IsVarDeclPack' is true |
23 | Called C++ object pointer is null |
6.1 | 'IsVarDeclPack' is false |
6.1 | 'IsVarDeclPack' is false |
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/PointerLikeTypeTraits.h" |
22 | #include <algorithm> |
23 | #include <cassert> |
24 | #include <cstddef> |
25 | #include <cstdint> |
26 | |
27 | namespace llvm { |
28 | |
29 | namespace pointer_union_detail { |
30 | /// Determine the number of bits required to store integers with values < n. |
31 | /// This is ceil(log2(n)). |
32 | constexpr int bitsRequired(unsigned n) { |
33 | return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0; |
34 | } |
35 | |
36 | template <typename... Ts> constexpr int lowBitsAvailable() { |
37 | return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...}); |
38 | } |
39 | |
40 | /// Find the first type in a list of types. |
41 | template <typename T, typename...> struct GetFirstType { |
42 | using type = T; |
43 | }; |
44 | |
45 | /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion |
46 | /// for the template arguments. |
47 | template <typename ...PTs> class PointerUnionUIntTraits { |
48 | public: |
49 | static inline void *getAsVoidPointer(void *P) { return P; } |
50 | static inline void *getFromVoidPointer(void *P) { return P; } |
51 | static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>(); |
52 | }; |
53 | |
54 | template <typename Derived, typename ValTy, int I, typename ...Types> |
55 | class PointerUnionMembers; |
56 | |
57 | template <typename Derived, typename ValTy, int I> |
58 | class PointerUnionMembers<Derived, ValTy, I> { |
59 | protected: |
60 | ValTy Val; |
61 | PointerUnionMembers() = default; |
62 | PointerUnionMembers(ValTy Val) : Val(Val) {} |
63 | |
64 | friend struct PointerLikeTypeTraits<Derived>; |
65 | }; |
66 | |
67 | template <typename Derived, typename ValTy, int I, typename Type, |
68 | typename ...Types> |
69 | class PointerUnionMembers<Derived, ValTy, I, Type, Types...> |
70 | : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> { |
71 | using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>; |
72 | public: |
73 | using Base::Base; |
74 | PointerUnionMembers() = default; |
75 | PointerUnionMembers(Type V) |
76 | : Base(ValTy(const_cast<void *>( |
77 | PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
78 | I)) {} |
79 | |
80 | using Base::operator=; |
81 | Derived &operator=(Type V) { |
82 | this->Val = ValTy( |
83 | const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)), |
84 | I); |
85 | return static_cast<Derived &>(*this); |
86 | }; |
87 | }; |
88 | } |
89 | |
90 | /// A discriminated union of two or more pointer types, with the discriminator |
91 | /// in the low bit of the pointer. |
92 | /// |
93 | /// This implementation is extremely efficient in space due to leveraging the |
94 | /// low bits of the pointer, while exposing a natural and type-safe API. |
95 | /// |
96 | /// Common use patterns would be something like this: |
97 | /// PointerUnion<int*, float*> P; |
98 | /// P = (int*)0; |
99 | /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" |
100 | /// X = P.get<int*>(); // ok. |
101 | /// Y = P.get<float*>(); // runtime assertion failure. |
102 | /// Z = P.get<double*>(); // compile time failure. |
103 | /// P = (float*)0; |
104 | /// Y = P.get<float*>(); // ok. |
105 | /// X = P.get<int*>(); // runtime assertion failure. |
106 | /// PointerUnion<int*, int*> Q; // compile time failure. |
107 | template <typename... PTs> |
108 | class PointerUnion |
109 | : public pointer_union_detail::PointerUnionMembers< |
110 | PointerUnion<PTs...>, |
111 | PointerIntPair< |
112 | void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int, |
113 | pointer_union_detail::PointerUnionUIntTraits<PTs...>>, |
114 | 0, PTs...> { |
115 | static_assert(TypesAreDistinct<PTs...>::value, |
116 | "PointerUnion alternative types cannot be repeated"); |
117 | // The first type is special because we want to directly cast a pointer to a |
118 | // default-initialized union to a pointer to the first type. But we don't |
119 | // want PointerUnion to be a 'template <typename First, typename ...Rest>' |
120 | // because it's much more convenient to have a name for the whole pack. So |
121 | // split off the first type here. |
122 | using First = TypeAtIndex<0, PTs...>; |
123 | using Base = typename PointerUnion::PointerUnionMembers; |
124 | |
125 | public: |
126 | PointerUnion() = default; |
127 | |
128 | PointerUnion(std::nullptr_t) : PointerUnion() {} |
129 | using Base::Base; |
130 | |
131 | /// Test if the pointer held in the union is null, regardless of |
132 | /// which type it is. |
133 | bool isNull() const { return !this->Val.getPointer(); } |
134 | |
135 | explicit operator bool() const { return !isNull(); } |
136 | |
137 | /// Test if the Union currently holds the type matching T. |
138 | template <typename T> bool is() const { |
139 | return this->Val.getInt() == FirstIndexOfType<T, PTs...>::value; |
140 | } |
141 | |
142 | /// Returns the value of the specified pointer type. |
143 | /// |
144 | /// If the specified pointer type is incorrect, assert. |
145 | template <typename T> T get() const { |
146 | assert(is<T>() && "Invalid accessor called")(static_cast <bool> (is<T>() && "Invalid accessor called" ) ? void (0) : __assert_fail ("is<T>() && \"Invalid accessor called\"" , "llvm/include/llvm/ADT/PointerUnion.h", 146, __extension__ __PRETTY_FUNCTION__ )); |
147 | return PointerLikeTypeTraits<T>::getFromVoidPointer(this->Val.getPointer()); |
148 | } |
149 | |
150 | /// Returns the current pointer if it is of the specified pointer type, |
151 | /// otherwise returns null. |
152 | template <typename T> T dyn_cast() const { |
153 | if (is<T>()) |
154 | return get<T>(); |
155 | return T(); |
156 | } |
157 | |
158 | /// If the union is set to the first pointer type get an address pointing to |
159 | /// it. |
160 | First const *getAddrOfPtr1() const { |
161 | return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); |
162 | } |
163 | |
164 | /// If the union is set to the first pointer type get an address pointing to |
165 | /// it. |
166 | First *getAddrOfPtr1() { |
167 | 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", 167, __extension__ __PRETTY_FUNCTION__ )); |
168 | 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", 171, __extension__ __PRETTY_FUNCTION__ )) |
169 | 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", 171, __extension__ __PRETTY_FUNCTION__ )) |
170 | 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", 171, __extension__ __PRETTY_FUNCTION__ )) |
171 | "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", 171, __extension__ __PRETTY_FUNCTION__ )); |
172 | return const_cast<First *>( |
173 | reinterpret_cast<const First *>(this->Val.getAddrOfPointer())); |
174 | } |
175 | |
176 | /// Assignment from nullptr which just clears the union. |
177 | const PointerUnion &operator=(std::nullptr_t) { |
178 | this->Val.initWithPointer(nullptr); |
179 | return *this; |
180 | } |
181 | |
182 | /// Assignment from elements of the union. |
183 | using Base::operator=; |
184 | |
185 | void *getOpaqueValue() const { return this->Val.getOpaqueValue(); } |
186 | static inline PointerUnion getFromOpaqueValue(void *VP) { |
187 | PointerUnion V; |
188 | V.Val = decltype(V.Val)::getFromOpaqueValue(VP); |
189 | return V; |
190 | } |
191 | }; |
192 | |
193 | template <typename ...PTs> |
194 | bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
195 | return lhs.getOpaqueValue() == rhs.getOpaqueValue(); |
196 | } |
197 | |
198 | template <typename ...PTs> |
199 | bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
200 | return lhs.getOpaqueValue() != rhs.getOpaqueValue(); |
201 | } |
202 | |
203 | template <typename ...PTs> |
204 | bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { |
205 | return lhs.getOpaqueValue() < rhs.getOpaqueValue(); |
206 | } |
207 | |
208 | // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has |
209 | // # low bits available = min(PT1bits,PT2bits)-1. |
210 | template <typename ...PTs> |
211 | struct PointerLikeTypeTraits<PointerUnion<PTs...>> { |
212 | static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) { |
213 | return P.getOpaqueValue(); |
214 | } |
215 | |
216 | static inline PointerUnion<PTs...> getFromVoidPointer(void *P) { |
217 | return PointerUnion<PTs...>::getFromOpaqueValue(P); |
218 | } |
219 | |
220 | // The number of bits available are the min of the pointer types minus the |
221 | // bits needed for the discriminator. |
222 | static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype( |
223 | PointerUnion<PTs...>::Val)>::NumLowBitsAvailable; |
224 | }; |
225 | |
226 | // Teach DenseMap how to use PointerUnions as keys. |
227 | template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> { |
228 | using Union = PointerUnion<PTs...>; |
229 | using FirstInfo = |
230 | DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>; |
231 | |
232 | static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); } |
233 | |
234 | static inline Union getTombstoneKey() { |
235 | return Union(FirstInfo::getTombstoneKey()); |
236 | } |
237 | |
238 | static unsigned getHashValue(const Union &UnionVal) { |
239 | intptr_t key = (intptr_t)UnionVal.getOpaqueValue(); |
240 | return DenseMapInfo<intptr_t>::getHashValue(key); |
241 | } |
242 | |
243 | static bool isEqual(const Union &LHS, const Union &RHS) { |
244 | return LHS == RHS; |
245 | } |
246 | }; |
247 | |
248 | } // end namespace llvm |
249 | |
250 | #endif // LLVM_ADT_POINTERUNION_H |