File: | tools/clang/lib/Sema/SemaTemplateVariadic.cpp |
Warning: | line 204, column 25 Potential leak of memory pointed to by field 'DiagStorage' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/ | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | //===----------------------------------------------------------------------===/ | |||
8 | // | |||
9 | // This file implements semantic analysis for C++0x variadic templates. | |||
10 | //===----------------------------------------------------------------------===/ | |||
11 | ||||
12 | #include "clang/Sema/Sema.h" | |||
13 | #include "TypeLocBuilder.h" | |||
14 | #include "clang/AST/Expr.h" | |||
15 | #include "clang/AST/RecursiveASTVisitor.h" | |||
16 | #include "clang/AST/TypeLoc.h" | |||
17 | #include "clang/Sema/Lookup.h" | |||
18 | #include "clang/Sema/ParsedTemplate.h" | |||
19 | #include "clang/Sema/ScopeInfo.h" | |||
20 | #include "clang/Sema/SemaInternal.h" | |||
21 | #include "clang/Sema/Template.h" | |||
22 | ||||
23 | using namespace clang; | |||
24 | ||||
25 | //---------------------------------------------------------------------------- | |||
26 | // Visitor that collects unexpanded parameter packs | |||
27 | //---------------------------------------------------------------------------- | |||
28 | ||||
29 | /// \brief Retrieve the depth and index of a parameter pack. | |||
30 | static std::pair<unsigned, unsigned> | |||
31 | getDepthAndIndex(NamedDecl *ND) { | |||
32 | if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) | |||
33 | return std::make_pair(TTP->getDepth(), TTP->getIndex()); | |||
34 | ||||
35 | if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND)) | |||
36 | return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); | |||
37 | ||||
38 | TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND); | |||
39 | return std::make_pair(TTP->getDepth(), TTP->getIndex()); | |||
40 | } | |||
41 | ||||
42 | namespace { | |||
43 | /// \brief A class that collects unexpanded parameter packs. | |||
44 | class CollectUnexpandedParameterPacksVisitor : | |||
45 | public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> | |||
46 | { | |||
47 | typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> | |||
48 | inherited; | |||
49 | ||||
50 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded; | |||
51 | ||||
52 | bool InLambda = false; | |||
53 | unsigned DepthLimit = (unsigned)-1; | |||
54 | ||||
55 | void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) { | |||
56 | if (auto *PVD = dyn_cast<ParmVarDecl>(ND)) { | |||
57 | // For now, the only problematic case is a generic lambda's templated | |||
58 | // call operator, so we don't need to look for all the other ways we | |||
59 | // could have reached a dependent parameter pack. | |||
60 | auto *FD = dyn_cast<FunctionDecl>(PVD->getDeclContext()); | |||
61 | auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr; | |||
62 | if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit) | |||
63 | return; | |||
64 | } else if (getDepthAndIndex(ND).first >= DepthLimit) | |||
65 | return; | |||
66 | ||||
67 | Unexpanded.push_back({ND, Loc}); | |||
68 | } | |||
69 | void addUnexpanded(const TemplateTypeParmType *T, | |||
70 | SourceLocation Loc = SourceLocation()) { | |||
71 | if (T->getDepth() < DepthLimit) | |||
72 | Unexpanded.push_back({T, Loc}); | |||
73 | } | |||
74 | ||||
75 | public: | |||
76 | explicit CollectUnexpandedParameterPacksVisitor( | |||
77 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) | |||
78 | : Unexpanded(Unexpanded) {} | |||
79 | ||||
80 | bool shouldWalkTypesOfTypeLocs() const { return false; } | |||
81 | ||||
82 | //------------------------------------------------------------------------ | |||
83 | // Recording occurrences of (unexpanded) parameter packs. | |||
84 | //------------------------------------------------------------------------ | |||
85 | ||||
86 | /// \brief Record occurrences of template type parameter packs. | |||
87 | bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { | |||
88 | if (TL.getTypePtr()->isParameterPack()) | |||
89 | addUnexpanded(TL.getTypePtr(), TL.getNameLoc()); | |||
90 | return true; | |||
91 | } | |||
92 | ||||
93 | /// \brief Record occurrences of template type parameter packs | |||
94 | /// when we don't have proper source-location information for | |||
95 | /// them. | |||
96 | /// | |||
97 | /// Ideally, this routine would never be used. | |||
98 | bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { | |||
99 | if (T->isParameterPack()) | |||
100 | addUnexpanded(T); | |||
101 | ||||
102 | return true; | |||
103 | } | |||
104 | ||||
105 | /// \brief Record occurrences of function and non-type template | |||
106 | /// parameter packs in an expression. | |||
107 | bool VisitDeclRefExpr(DeclRefExpr *E) { | |||
108 | if (E->getDecl()->isParameterPack()) | |||
109 | addUnexpanded(E->getDecl(), E->getLocation()); | |||
110 | ||||
111 | return true; | |||
112 | } | |||
113 | ||||
114 | /// \brief Record occurrences of template template parameter packs. | |||
115 | bool TraverseTemplateName(TemplateName Template) { | |||
116 | if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>( | |||
117 | Template.getAsTemplateDecl())) { | |||
118 | if (TTP->isParameterPack()) | |||
119 | addUnexpanded(TTP); | |||
120 | } | |||
121 | ||||
122 | return inherited::TraverseTemplateName(Template); | |||
123 | } | |||
124 | ||||
125 | /// \brief Suppress traversal into Objective-C container literal | |||
126 | /// elements that are pack expansions. | |||
127 | bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { | |||
128 | if (!E->containsUnexpandedParameterPack()) | |||
129 | return true; | |||
130 | ||||
131 | for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { | |||
132 | ObjCDictionaryElement Element = E->getKeyValueElement(I); | |||
133 | if (Element.isPackExpansion()) | |||
134 | continue; | |||
135 | ||||
136 | TraverseStmt(Element.Key); | |||
137 | TraverseStmt(Element.Value); | |||
138 | } | |||
139 | return true; | |||
140 | } | |||
141 | //------------------------------------------------------------------------ | |||
142 | // Pruning the search for unexpanded parameter packs. | |||
143 | //------------------------------------------------------------------------ | |||
144 | ||||
145 | /// \brief Suppress traversal into statements and expressions that | |||
146 | /// do not contain unexpanded parameter packs. | |||
147 | bool TraverseStmt(Stmt *S) { | |||
148 | Expr *E = dyn_cast_or_null<Expr>(S); | |||
149 | if ((E && E->containsUnexpandedParameterPack()) || InLambda) | |||
150 | return inherited::TraverseStmt(S); | |||
151 | ||||
152 | return true; | |||
153 | } | |||
154 | ||||
155 | /// \brief Suppress traversal into types that do not contain | |||
156 | /// unexpanded parameter packs. | |||
157 | bool TraverseType(QualType T) { | |||
158 | if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda) | |||
159 | return inherited::TraverseType(T); | |||
160 | ||||
161 | return true; | |||
162 | } | |||
163 | ||||
164 | /// \brief Suppress traversal into types with location information | |||
165 | /// that do not contain unexpanded parameter packs. | |||
166 | bool TraverseTypeLoc(TypeLoc TL) { | |||
167 | if ((!TL.getType().isNull() && | |||
168 | TL.getType()->containsUnexpandedParameterPack()) || | |||
169 | InLambda) | |||
170 | return inherited::TraverseTypeLoc(TL); | |||
171 | ||||
172 | return true; | |||
173 | } | |||
174 | ||||
175 | /// \brief Suppress traversal of parameter packs. | |||
176 | bool TraverseDecl(Decl *D) { | |||
177 | // A function parameter pack is a pack expansion, so cannot contain | |||
178 | // an unexpanded parameter pack. Likewise for a template parameter | |||
179 | // pack that contains any references to other packs. | |||
180 | if (D->isParameterPack()) | |||
181 | return true; | |||
182 | ||||
183 | return inherited::TraverseDecl(D); | |||
184 | } | |||
185 | ||||
186 | /// \brief Suppress traversal of pack-expanded attributes. | |||
187 | bool TraverseAttr(Attr *A) { | |||
188 | if (A->isPackExpansion()) | |||
189 | return true; | |||
190 | ||||
191 | return inherited::TraverseAttr(A); | |||
192 | } | |||
193 | ||||
194 | /// \brief Suppress traversal of pack expansion expressions and types. | |||
195 | ///@{ | |||
196 | bool TraversePackExpansionType(PackExpansionType *T) { return true; } | |||
197 | bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; } | |||
198 | bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; } | |||
199 | bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; } | |||
200 | ||||
201 | ///@} | |||
202 | ||||
203 | /// \brief Suppress traversal of using-declaration pack expansion. | |||
204 | bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { | |||
205 | if (D->isPackExpansion()) | |||
206 | return true; | |||
207 | ||||
208 | return inherited::TraverseUnresolvedUsingValueDecl(D); | |||
209 | } | |||
210 | ||||
211 | /// \brief Suppress traversal of using-declaration pack expansion. | |||
212 | bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { | |||
213 | if (D->isPackExpansion()) | |||
214 | return true; | |||
215 | ||||
216 | return inherited::TraverseUnresolvedUsingTypenameDecl(D); | |||
217 | } | |||
218 | ||||
219 | /// \brief Suppress traversal of template argument pack expansions. | |||
220 | bool TraverseTemplateArgument(const TemplateArgument &Arg) { | |||
221 | if (Arg.isPackExpansion()) | |||
222 | return true; | |||
223 | ||||
224 | return inherited::TraverseTemplateArgument(Arg); | |||
225 | } | |||
226 | ||||
227 | /// \brief Suppress traversal of template argument pack expansions. | |||
228 | bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { | |||
229 | if (ArgLoc.getArgument().isPackExpansion()) | |||
230 | return true; | |||
231 | ||||
232 | return inherited::TraverseTemplateArgumentLoc(ArgLoc); | |||
233 | } | |||
234 | ||||
235 | /// \brief Suppress traversal of base specifier pack expansions. | |||
236 | bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) { | |||
237 | if (Base.isPackExpansion()) | |||
238 | return true; | |||
239 | ||||
240 | return inherited::TraverseCXXBaseSpecifier(Base); | |||
241 | } | |||
242 | ||||
243 | /// \brief Suppress traversal of mem-initializer pack expansions. | |||
244 | bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { | |||
245 | if (Init->isPackExpansion()) | |||
246 | return true; | |||
247 | ||||
248 | return inherited::TraverseConstructorInitializer(Init); | |||
249 | } | |||
250 | ||||
251 | /// \brief Note whether we're traversing a lambda containing an unexpanded | |||
252 | /// parameter pack. In this case, the unexpanded pack can occur anywhere, | |||
253 | /// including all the places where we normally wouldn't look. Within a | |||
254 | /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit | |||
255 | /// outside an expression. | |||
256 | bool TraverseLambdaExpr(LambdaExpr *Lambda) { | |||
257 | // The ContainsUnexpandedParameterPack bit on a lambda is always correct, | |||
258 | // even if it's contained within another lambda. | |||
259 | if (!Lambda->containsUnexpandedParameterPack()) | |||
260 | return true; | |||
261 | ||||
262 | bool WasInLambda = InLambda; | |||
263 | unsigned OldDepthLimit = DepthLimit; | |||
264 | ||||
265 | InLambda = true; | |||
266 | if (auto *TPL = Lambda->getTemplateParameterList()) | |||
267 | DepthLimit = TPL->getDepth(); | |||
268 | ||||
269 | inherited::TraverseLambdaExpr(Lambda); | |||
270 | ||||
271 | InLambda = WasInLambda; | |||
272 | DepthLimit = OldDepthLimit; | |||
273 | return true; | |||
274 | } | |||
275 | ||||
276 | /// Suppress traversal within pack expansions in lambda captures. | |||
277 | bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C, | |||
278 | Expr *Init) { | |||
279 | if (C->isPackExpansion()) | |||
280 | return true; | |||
281 | ||||
282 | return inherited::TraverseLambdaCapture(Lambda, C, Init); | |||
283 | } | |||
284 | }; | |||
285 | } | |||
286 | ||||
287 | /// \brief Determine whether it's possible for an unexpanded parameter pack to | |||
288 | /// be valid in this location. This only happens when we're in a declaration | |||
289 | /// that is nested within an expression that could be expanded, such as a | |||
290 | /// lambda-expression within a function call. | |||
291 | /// | |||
292 | /// This is conservatively correct, but may claim that some unexpanded packs are | |||
293 | /// permitted when they are not. | |||
294 | bool Sema::isUnexpandedParameterPackPermitted() { | |||
295 | for (auto *SI : FunctionScopes) | |||
296 | if (isa<sema::LambdaScopeInfo>(SI)) | |||
297 | return true; | |||
298 | return false; | |||
299 | } | |||
300 | ||||
301 | /// \brief Diagnose all of the unexpanded parameter packs in the given | |||
302 | /// vector. | |||
303 | bool | |||
304 | Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, | |||
305 | UnexpandedParameterPackContext UPPC, | |||
306 | ArrayRef<UnexpandedParameterPack> Unexpanded) { | |||
307 | if (Unexpanded.empty()) | |||
308 | return false; | |||
309 | ||||
310 | // If we are within a lambda expression and referencing a pack that is not | |||
311 | // a parameter of the lambda itself, that lambda contains an unexpanded | |||
312 | // parameter pack, and we are done. | |||
313 | // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it | |||
314 | // later. | |||
315 | SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences; | |||
316 | for (unsigned N = FunctionScopes.size(); N; --N) { | |||
317 | sema::FunctionScopeInfo *Func = FunctionScopes[N-1]; | |||
318 | // We do not permit pack expansion that would duplicate a statement | |||
319 | // expression, not even within a lambda. | |||
320 | // FIXME: We could probably support this for statement expressions that do | |||
321 | // not contain labels, and for pack expansions that expand both the stmt | |||
322 | // expr and the enclosing lambda. | |||
323 | if (std::any_of( | |||
324 | Func->CompoundScopes.begin(), Func->CompoundScopes.end(), | |||
325 | [](sema::CompoundScopeInfo &CSI) { return CSI.IsStmtExpr; })) | |||
326 | break; | |||
327 | ||||
328 | if (auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Func)) { | |||
329 | if (N == FunctionScopes.size()) { | |||
330 | for (auto &Param : Unexpanded) { | |||
331 | auto *PD = dyn_cast_or_null<ParmVarDecl>( | |||
332 | Param.first.dyn_cast<NamedDecl *>()); | |||
333 | if (PD && PD->getDeclContext() == LSI->CallOperator) | |||
334 | LambdaParamPackReferences.push_back(Param); | |||
335 | } | |||
336 | } | |||
337 | ||||
338 | // If we have references to a parameter pack of the innermost enclosing | |||
339 | // lambda, only diagnose those ones. We don't know whether any other | |||
340 | // unexpanded parameters referenced herein are actually unexpanded; | |||
341 | // they might be expanded at an outer level. | |||
342 | if (!LambdaParamPackReferences.empty()) { | |||
343 | Unexpanded = LambdaParamPackReferences; | |||
344 | break; | |||
345 | } | |||
346 | ||||
347 | LSI->ContainsUnexpandedParameterPack = true; | |||
348 | return false; | |||
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 | DiagnosticBuilder 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 407, __extension__ __PRETTY_FUNCTION__)); | |||
408 | return DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded); | |||
409 | } | |||
410 | ||||
411 | bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, | |||
412 | UnexpandedParameterPackContext UPPC) { | |||
413 | // C++0x [temp.variadic]p5: | |||
414 | // An appearance of a name of a parameter pack that is not expanded is | |||
415 | // ill-formed. | |||
416 | if (!SS.getScopeRep() || | |||
417 | !SS.getScopeRep()->containsUnexpandedParameterPack()) | |||
418 | return false; | |||
419 | ||||
420 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | |||
421 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
422 | .TraverseNestedNameSpecifier(SS.getScopeRep()); | |||
423 | 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 423, __extension__ __PRETTY_FUNCTION__)); | |||
424 | return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), | |||
425 | UPPC, Unexpanded); | |||
426 | } | |||
427 | ||||
428 | bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, | |||
429 | UnexpandedParameterPackContext UPPC) { | |||
430 | // C++0x [temp.variadic]p5: | |||
431 | // An appearance of a name of a parameter pack that is not expanded is | |||
432 | // ill-formed. | |||
433 | switch (NameInfo.getName().getNameKind()) { | |||
434 | case DeclarationName::Identifier: | |||
435 | case DeclarationName::ObjCZeroArgSelector: | |||
436 | case DeclarationName::ObjCOneArgSelector: | |||
437 | case DeclarationName::ObjCMultiArgSelector: | |||
438 | case DeclarationName::CXXOperatorName: | |||
439 | case DeclarationName::CXXLiteralOperatorName: | |||
440 | case DeclarationName::CXXUsingDirective: | |||
441 | case DeclarationName::CXXDeductionGuideName: | |||
442 | return false; | |||
443 | ||||
444 | case DeclarationName::CXXConstructorName: | |||
445 | case DeclarationName::CXXDestructorName: | |||
446 | case DeclarationName::CXXConversionFunctionName: | |||
447 | // FIXME: We shouldn't need this null check! | |||
448 | if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) | |||
449 | return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC); | |||
450 | ||||
451 | if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack()) | |||
452 | return false; | |||
453 | ||||
454 | break; | |||
455 | } | |||
456 | ||||
457 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | |||
458 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
459 | .TraverseType(NameInfo.getName().getCXXNameType()); | |||
460 | 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 460, __extension__ __PRETTY_FUNCTION__)); | |||
461 | return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded); | |||
462 | } | |||
463 | ||||
464 | bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, | |||
465 | TemplateName Template, | |||
466 | UnexpandedParameterPackContext UPPC) { | |||
467 | ||||
468 | if (Template.isNull() || !Template.containsUnexpandedParameterPack()) | |||
469 | return false; | |||
470 | ||||
471 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | |||
472 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
473 | .TraverseTemplateName(Template); | |||
474 | 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 474, __extension__ __PRETTY_FUNCTION__)); | |||
475 | return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); | |||
476 | } | |||
477 | ||||
478 | bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, | |||
479 | UnexpandedParameterPackContext UPPC) { | |||
480 | if (Arg.getArgument().isNull() || | |||
481 | !Arg.getArgument().containsUnexpandedParameterPack()) | |||
482 | return false; | |||
483 | ||||
484 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | |||
485 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
486 | .TraverseTemplateArgumentLoc(Arg); | |||
487 | 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 487, __extension__ __PRETTY_FUNCTION__)); | |||
488 | return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded); | |||
489 | } | |||
490 | ||||
491 | void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg, | |||
492 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | |||
493 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
494 | .TraverseTemplateArgument(Arg); | |||
495 | } | |||
496 | ||||
497 | void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg, | |||
498 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | |||
499 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
500 | .TraverseTemplateArgumentLoc(Arg); | |||
501 | } | |||
502 | ||||
503 | void Sema::collectUnexpandedParameterPacks(QualType T, | |||
504 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | |||
505 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T); | |||
506 | } | |||
507 | ||||
508 | void Sema::collectUnexpandedParameterPacks(TypeLoc TL, | |||
509 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | |||
510 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL); | |||
511 | } | |||
512 | ||||
513 | void Sema::collectUnexpandedParameterPacks( | |||
514 | NestedNameSpecifierLoc NNS, | |||
515 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | |||
516 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
517 | .TraverseNestedNameSpecifierLoc(NNS); | |||
518 | } | |||
519 | ||||
520 | void Sema::collectUnexpandedParameterPacks( | |||
521 | const DeclarationNameInfo &NameInfo, | |||
522 | SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { | |||
523 | CollectUnexpandedParameterPacksVisitor(Unexpanded) | |||
524 | .TraverseDeclarationNameInfo(NameInfo); | |||
525 | } | |||
526 | ||||
527 | ||||
528 | ParsedTemplateArgument | |||
529 | Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, | |||
530 | SourceLocation EllipsisLoc) { | |||
531 | if (Arg.isInvalid()) | |||
532 | return Arg; | |||
533 | ||||
534 | switch (Arg.getKind()) { | |||
535 | case ParsedTemplateArgument::Type: { | |||
536 | TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc); | |||
537 | if (Result.isInvalid()) | |||
538 | return ParsedTemplateArgument(); | |||
539 | ||||
540 | return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), | |||
541 | Arg.getLocation()); | |||
542 | } | |||
543 | ||||
544 | case ParsedTemplateArgument::NonType: { | |||
545 | ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc); | |||
546 | if (Result.isInvalid()) | |||
547 | return ParsedTemplateArgument(); | |||
548 | ||||
549 | return ParsedTemplateArgument(Arg.getKind(), Result.get(), | |||
550 | Arg.getLocation()); | |||
551 | } | |||
552 | ||||
553 | case ParsedTemplateArgument::Template: | |||
554 | if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) { | |||
555 | SourceRange R(Arg.getLocation()); | |||
556 | if (Arg.getScopeSpec().isValid()) | |||
557 | R.setBegin(Arg.getScopeSpec().getBeginLoc()); | |||
558 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | |||
559 | << R; | |||
560 | return ParsedTemplateArgument(); | |||
561 | } | |||
562 | ||||
563 | return Arg.getTemplatePackExpansion(EllipsisLoc); | |||
564 | } | |||
565 | llvm_unreachable("Unhandled template argument kind?")::llvm::llvm_unreachable_internal("Unhandled template argument kind?" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 565); | |||
566 | } | |||
567 | ||||
568 | TypeResult Sema::ActOnPackExpansion(ParsedType Type, | |||
569 | SourceLocation EllipsisLoc) { | |||
570 | TypeSourceInfo *TSInfo; | |||
571 | GetTypeFromParser(Type, &TSInfo); | |||
572 | if (!TSInfo) | |||
573 | return true; | |||
574 | ||||
575 | TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, None); | |||
576 | if (!TSResult) | |||
577 | return true; | |||
578 | ||||
579 | return CreateParsedType(TSResult->getType(), TSResult); | |||
580 | } | |||
581 | ||||
582 | TypeSourceInfo * | |||
583 | Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, | |||
584 | Optional<unsigned> NumExpansions) { | |||
585 | // Create the pack expansion type and source-location information. | |||
586 | QualType Result = CheckPackExpansion(Pattern->getType(), | |||
587 | Pattern->getTypeLoc().getSourceRange(), | |||
588 | EllipsisLoc, NumExpansions); | |||
589 | if (Result.isNull()) | |||
590 | return nullptr; | |||
591 | ||||
592 | TypeLocBuilder TLB; | |||
593 | TLB.pushFullCopy(Pattern->getTypeLoc()); | |||
594 | PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result); | |||
595 | TL.setEllipsisLoc(EllipsisLoc); | |||
596 | ||||
597 | return TLB.getTypeSourceInfo(Context, Result); | |||
598 | } | |||
599 | ||||
600 | QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange, | |||
601 | SourceLocation EllipsisLoc, | |||
602 | Optional<unsigned> NumExpansions) { | |||
603 | // C++0x [temp.variadic]p5: | |||
604 | // The pattern of a pack expansion shall name one or more | |||
605 | // parameter packs that are not expanded by a nested pack | |||
606 | // expansion. | |||
607 | if (!Pattern->containsUnexpandedParameterPack()) { | |||
608 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | |||
609 | << PatternRange; | |||
610 | return QualType(); | |||
611 | } | |||
612 | ||||
613 | return Context.getPackExpansionType(Pattern, NumExpansions); | |||
614 | } | |||
615 | ||||
616 | ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { | |||
617 | return CheckPackExpansion(Pattern, EllipsisLoc, None); | |||
618 | } | |||
619 | ||||
620 | ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, | |||
621 | Optional<unsigned> NumExpansions) { | |||
622 | if (!Pattern) | |||
623 | return ExprError(); | |||
624 | ||||
625 | // C++0x [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 | if (!Pattern->containsUnexpandedParameterPack()) { | |||
630 | Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | |||
631 | << Pattern->getSourceRange(); | |||
632 | return ExprError(); | |||
633 | } | |||
634 | ||||
635 | // Create the pack expansion expression and source-location information. | |||
636 | return new (Context) | |||
637 | PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions); | |||
638 | } | |||
639 | ||||
640 | bool Sema::CheckParameterPacksForExpansion( | |||
641 | SourceLocation EllipsisLoc, SourceRange PatternRange, | |||
642 | ArrayRef<UnexpandedParameterPack> Unexpanded, | |||
643 | const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, | |||
644 | bool &RetainExpansion, Optional<unsigned> &NumExpansions) { | |||
645 | ShouldExpand = true; | |||
646 | RetainExpansion = false; | |||
647 | std::pair<IdentifierInfo *, SourceLocation> FirstPack; | |||
648 | bool HaveFirstPack = false; | |||
649 | ||||
650 | for (ArrayRef<UnexpandedParameterPack>::iterator i = Unexpanded.begin(), | |||
651 | end = Unexpanded.end(); | |||
652 | i != end; ++i) { | |||
653 | // Compute the depth and index for this parameter pack. | |||
654 | unsigned Depth = 0, Index = 0; | |||
655 | IdentifierInfo *Name; | |||
656 | bool IsFunctionParameterPack = false; | |||
657 | ||||
658 | if (const TemplateTypeParmType *TTP | |||
659 | = i->first.dyn_cast<const TemplateTypeParmType *>()) { | |||
660 | Depth = TTP->getDepth(); | |||
661 | Index = TTP->getIndex(); | |||
662 | Name = TTP->getIdentifier(); | |||
663 | } else { | |||
664 | NamedDecl *ND = i->first.get<NamedDecl *>(); | |||
665 | if (isa<ParmVarDecl>(ND)) | |||
666 | IsFunctionParameterPack = true; | |||
667 | else | |||
668 | std::tie(Depth, Index) = getDepthAndIndex(ND); | |||
669 | ||||
670 | Name = ND->getIdentifier(); | |||
671 | } | |||
672 | ||||
673 | // Determine the size of this argument pack. | |||
674 | unsigned NewPackSize; | |||
675 | if (IsFunctionParameterPack) { | |||
676 | // Figure out whether we're instantiating to an argument pack or not. | |||
677 | typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; | |||
678 | ||||
679 | llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation | |||
680 | = CurrentInstantiationScope->findInstantiationOf( | |||
681 | i->first.get<NamedDecl *>()); | |||
682 | if (Instantiation->is<DeclArgumentPack *>()) { | |||
683 | // We could expand this function parameter pack. | |||
684 | NewPackSize = Instantiation->get<DeclArgumentPack *>()->size(); | |||
685 | } else { | |||
686 | // We can't expand this function parameter pack, so we can't expand | |||
687 | // the pack expansion. | |||
688 | ShouldExpand = false; | |||
689 | continue; | |||
690 | } | |||
691 | } else { | |||
692 | // If we don't have a template argument at this depth/index, then we | |||
693 | // cannot expand the pack expansion. Make a note of this, but we still | |||
694 | // want to check any parameter packs we *do* have arguments for. | |||
695 | if (Depth >= TemplateArgs.getNumLevels() || | |||
696 | !TemplateArgs.hasTemplateArgument(Depth, Index)) { | |||
697 | ShouldExpand = false; | |||
698 | continue; | |||
699 | } | |||
700 | ||||
701 | // Determine the size of the argument pack. | |||
702 | NewPackSize = TemplateArgs(Depth, Index).pack_size(); | |||
703 | } | |||
704 | ||||
705 | // C++0x [temp.arg.explicit]p9: | |||
706 | // Template argument deduction can extend the sequence of template | |||
707 | // arguments corresponding to a template parameter pack, even when the | |||
708 | // sequence contains explicitly specified template arguments. | |||
709 | if (!IsFunctionParameterPack && CurrentInstantiationScope) { | |||
710 | if (NamedDecl *PartialPack | |||
711 | = CurrentInstantiationScope->getPartiallySubstitutedPack()){ | |||
712 | unsigned PartialDepth, PartialIndex; | |||
713 | std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); | |||
714 | if (PartialDepth == Depth && PartialIndex == Index) | |||
715 | RetainExpansion = true; | |||
716 | } | |||
717 | } | |||
718 | ||||
719 | if (!NumExpansions) { | |||
720 | // The is the first pack we've seen for which we have an argument. | |||
721 | // Record it. | |||
722 | NumExpansions = NewPackSize; | |||
723 | FirstPack.first = Name; | |||
724 | FirstPack.second = i->second; | |||
725 | HaveFirstPack = true; | |||
726 | continue; | |||
727 | } | |||
728 | ||||
729 | if (NewPackSize != *NumExpansions) { | |||
730 | // C++0x [temp.variadic]p5: | |||
731 | // All of the parameter packs expanded by a pack expansion shall have | |||
732 | // the same number of arguments specified. | |||
733 | if (HaveFirstPack) | |||
734 | Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) | |||
735 | << FirstPack.first << Name << *NumExpansions << NewPackSize | |||
736 | << SourceRange(FirstPack.second) << SourceRange(i->second); | |||
737 | else | |||
738 | Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) | |||
739 | << Name << *NumExpansions << NewPackSize | |||
740 | << SourceRange(i->second); | |||
741 | return true; | |||
742 | } | |||
743 | } | |||
744 | ||||
745 | return false; | |||
746 | } | |||
747 | ||||
748 | Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T, | |||
749 | const MultiLevelTemplateArgumentList &TemplateArgs) { | |||
750 | QualType Pattern = cast<PackExpansionType>(T)->getPattern(); | |||
751 | SmallVector<UnexpandedParameterPack, 2> Unexpanded; | |||
752 | CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); | |||
753 | ||||
754 | Optional<unsigned> Result; | |||
755 | for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { | |||
756 | // Compute the depth and index for this parameter pack. | |||
757 | unsigned Depth; | |||
758 | unsigned Index; | |||
759 | ||||
760 | if (const TemplateTypeParmType *TTP | |||
761 | = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) { | |||
762 | Depth = TTP->getDepth(); | |||
763 | Index = TTP->getIndex(); | |||
764 | } else { | |||
765 | NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>(); | |||
766 | if (isa<ParmVarDecl>(ND)) { | |||
767 | // Function parameter pack. | |||
768 | typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; | |||
769 | ||||
770 | llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation | |||
771 | = CurrentInstantiationScope->findInstantiationOf( | |||
772 | Unexpanded[I].first.get<NamedDecl *>()); | |||
773 | if (Instantiation->is<Decl*>()) | |||
774 | // The pattern refers to an unexpanded pack. We're not ready to expand | |||
775 | // this pack yet. | |||
776 | return None; | |||
777 | ||||
778 | unsigned Size = Instantiation->get<DeclArgumentPack *>()->size(); | |||
779 | 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 779, __extension__ __PRETTY_FUNCTION__)); | |||
780 | Result = Size; | |||
781 | continue; | |||
782 | } | |||
783 | ||||
784 | std::tie(Depth, Index) = getDepthAndIndex(ND); | |||
785 | } | |||
786 | if (Depth >= TemplateArgs.getNumLevels() || | |||
787 | !TemplateArgs.hasTemplateArgument(Depth, Index)) | |||
788 | // The pattern refers to an unknown template argument. We're not ready to | |||
789 | // expand this pack yet. | |||
790 | return None; | |||
791 | ||||
792 | // Determine the size of the argument pack. | |||
793 | unsigned Size = TemplateArgs(Depth, Index).pack_size(); | |||
794 | 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 794, __extension__ __PRETTY_FUNCTION__)); | |||
795 | Result = Size; | |||
796 | } | |||
797 | ||||
798 | return Result; | |||
799 | } | |||
800 | ||||
801 | bool Sema::containsUnexpandedParameterPacks(Declarator &D) { | |||
802 | const DeclSpec &DS = D.getDeclSpec(); | |||
803 | switch (DS.getTypeSpecType()) { | |||
804 | case TST_typename: | |||
805 | case TST_typeofType: | |||
806 | case TST_underlyingType: | |||
807 | case TST_atomic: { | |||
808 | QualType T = DS.getRepAsType().get(); | |||
809 | if (!T.isNull() && T->containsUnexpandedParameterPack()) | |||
810 | return true; | |||
811 | break; | |||
812 | } | |||
813 | ||||
814 | case TST_typeofExpr: | |||
815 | case TST_decltype: | |||
816 | if (DS.getRepAsExpr() && | |||
817 | DS.getRepAsExpr()->containsUnexpandedParameterPack()) | |||
818 | return true; | |||
819 | break; | |||
820 | ||||
821 | case TST_unspecified: | |||
822 | case TST_void: | |||
823 | case TST_char: | |||
824 | case TST_wchar: | |||
825 | case TST_char16: | |||
826 | case TST_char32: | |||
827 | case TST_int: | |||
828 | case TST_int128: | |||
829 | case TST_half: | |||
830 | case TST_float: | |||
831 | case TST_double: | |||
832 | case TST_Float16: | |||
833 | case TST_float128: | |||
834 | case TST_bool: | |||
835 | case TST_decimal32: | |||
836 | case TST_decimal64: | |||
837 | case TST_decimal128: | |||
838 | case TST_enum: | |||
839 | case TST_union: | |||
840 | case TST_struct: | |||
841 | case TST_interface: | |||
842 | case TST_class: | |||
843 | case TST_auto: | |||
844 | case TST_auto_type: | |||
845 | case TST_decltype_auto: | |||
846 | #define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: | |||
847 | #include "clang/Basic/OpenCLImageTypes.def" | |||
848 | case TST_unknown_anytype: | |||
849 | case TST_error: | |||
850 | break; | |||
851 | } | |||
852 | ||||
853 | for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) { | |||
854 | const DeclaratorChunk &Chunk = D.getTypeObject(I); | |||
855 | switch (Chunk.Kind) { | |||
856 | case DeclaratorChunk::Pointer: | |||
857 | case DeclaratorChunk::Reference: | |||
858 | case DeclaratorChunk::Paren: | |||
859 | case DeclaratorChunk::Pipe: | |||
860 | case DeclaratorChunk::BlockPointer: | |||
861 | // These declarator chunks cannot contain any parameter packs. | |||
862 | break; | |||
863 | ||||
864 | case DeclaratorChunk::Array: | |||
865 | if (Chunk.Arr.NumElts && | |||
866 | Chunk.Arr.NumElts->containsUnexpandedParameterPack()) | |||
867 | return true; | |||
868 | break; | |||
869 | case DeclaratorChunk::Function: | |||
870 | for (unsigned i = 0, e = Chunk.Fun.NumParams; i != e; ++i) { | |||
871 | ParmVarDecl *Param = cast<ParmVarDecl>(Chunk.Fun.Params[i].Param); | |||
872 | QualType ParamTy = Param->getType(); | |||
873 | 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?\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 873, __extension__ __PRETTY_FUNCTION__)); | |||
874 | if (ParamTy->containsUnexpandedParameterPack()) return true; | |||
875 | } | |||
876 | ||||
877 | if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) { | |||
878 | for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) { | |||
879 | if (Chunk.Fun.Exceptions[i] | |||
880 | .Ty.get() | |||
881 | ->containsUnexpandedParameterPack()) | |||
882 | return true; | |||
883 | } | |||
884 | } else if (Chunk.Fun.getExceptionSpecType() == EST_ComputedNoexcept && | |||
885 | Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack()) | |||
886 | return true; | |||
887 | ||||
888 | if (Chunk.Fun.hasTrailingReturnType()) { | |||
889 | QualType T = Chunk.Fun.getTrailingReturnType().get(); | |||
890 | if (!T.isNull() && T->containsUnexpandedParameterPack()) | |||
891 | return true; | |||
892 | } | |||
893 | break; | |||
894 | ||||
895 | case DeclaratorChunk::MemberPointer: | |||
896 | if (Chunk.Mem.Scope().getScopeRep() && | |||
897 | Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack()) | |||
898 | return true; | |||
899 | break; | |||
900 | } | |||
901 | } | |||
902 | ||||
903 | return false; | |||
904 | } | |||
905 | ||||
906 | namespace { | |||
907 | ||||
908 | // Callback to only accept typo corrections that refer to parameter packs. | |||
909 | class ParameterPackValidatorCCC : public CorrectionCandidateCallback { | |||
910 | public: | |||
911 | bool ValidateCandidate(const TypoCorrection &candidate) override { | |||
912 | NamedDecl *ND = candidate.getCorrectionDecl(); | |||
913 | return ND && ND->isParameterPack(); | |||
914 | } | |||
915 | }; | |||
916 | ||||
917 | } | |||
918 | ||||
919 | /// \brief Called when an expression computing the size of a parameter pack | |||
920 | /// is parsed. | |||
921 | /// | |||
922 | /// \code | |||
923 | /// template<typename ...Types> struct count { | |||
924 | /// static const unsigned value = sizeof...(Types); | |||
925 | /// }; | |||
926 | /// \endcode | |||
927 | /// | |||
928 | // | |||
929 | /// \param OpLoc The location of the "sizeof" keyword. | |||
930 | /// \param Name The name of the parameter pack whose size will be determined. | |||
931 | /// \param NameLoc The source location of the name of the parameter pack. | |||
932 | /// \param RParenLoc The location of the closing parentheses. | |||
933 | ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, | |||
934 | SourceLocation OpLoc, | |||
935 | IdentifierInfo &Name, | |||
936 | SourceLocation NameLoc, | |||
937 | SourceLocation RParenLoc) { | |||
938 | // C++0x [expr.sizeof]p5: | |||
939 | // The identifier in a sizeof... expression shall name a parameter pack. | |||
940 | LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName); | |||
941 | LookupName(R, S); | |||
942 | ||||
943 | NamedDecl *ParameterPack = nullptr; | |||
944 | switch (R.getResultKind()) { | |||
| ||||
945 | case LookupResult::Found: | |||
946 | ParameterPack = R.getFoundDecl(); | |||
947 | break; | |||
948 | ||||
949 | case LookupResult::NotFound: | |||
950 | case LookupResult::NotFoundInCurrentInstantiation: | |||
951 | if (TypoCorrection Corrected = | |||
952 | CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr, | |||
953 | llvm::make_unique<ParameterPackValidatorCCC>(), | |||
954 | CTK_ErrorRecovery)) { | |||
955 | diagnoseTypo(Corrected, | |||
956 | PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name, | |||
957 | PDiag(diag::note_parameter_pack_here)); | |||
958 | ParameterPack = Corrected.getCorrectionDecl(); | |||
959 | } | |||
960 | ||||
961 | case LookupResult::FoundOverloaded: | |||
962 | case LookupResult::FoundUnresolvedValue: | |||
963 | break; | |||
964 | ||||
965 | case LookupResult::Ambiguous: | |||
966 | DiagnoseAmbiguousLookup(R); | |||
967 | return ExprError(); | |||
968 | } | |||
969 | ||||
970 | if (!ParameterPack || !ParameterPack->isParameterPack()) { | |||
971 | Diag(NameLoc, diag::err_sizeof_pack_no_pack_name) | |||
972 | << &Name; | |||
973 | return ExprError(); | |||
974 | } | |||
975 | ||||
976 | MarkAnyDeclReferenced(OpLoc, ParameterPack, true); | |||
977 | ||||
978 | return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc, | |||
979 | RParenLoc); | |||
980 | } | |||
981 | ||||
982 | TemplateArgumentLoc | |||
983 | Sema::getTemplateArgumentPackExpansionPattern( | |||
984 | TemplateArgumentLoc OrigLoc, | |||
985 | SourceLocation &Ellipsis, Optional<unsigned> &NumExpansions) const { | |||
986 | const TemplateArgument &Argument = OrigLoc.getArgument(); | |||
987 | assert(Argument.isPackExpansion())(static_cast <bool> (Argument.isPackExpansion()) ? void (0) : __assert_fail ("Argument.isPackExpansion()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 987, __extension__ __PRETTY_FUNCTION__)); | |||
988 | switch (Argument.getKind()) { | |||
989 | case TemplateArgument::Type: { | |||
990 | // FIXME: We shouldn't ever have to worry about missing | |||
991 | // type-source info! | |||
992 | TypeSourceInfo *ExpansionTSInfo = OrigLoc.getTypeSourceInfo(); | |||
993 | if (!ExpansionTSInfo) | |||
994 | ExpansionTSInfo = Context.getTrivialTypeSourceInfo(Argument.getAsType(), | |||
995 | Ellipsis); | |||
996 | PackExpansionTypeLoc Expansion = | |||
997 | ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>(); | |||
998 | Ellipsis = Expansion.getEllipsisLoc(); | |||
999 | ||||
1000 | TypeLoc Pattern = Expansion.getPatternLoc(); | |||
1001 | NumExpansions = Expansion.getTypePtr()->getNumExpansions(); | |||
1002 | ||||
1003 | // We need to copy the TypeLoc because TemplateArgumentLocs store a | |||
1004 | // TypeSourceInfo. | |||
1005 | // FIXME: Find some way to avoid the copy? | |||
1006 | TypeLocBuilder TLB; | |||
1007 | TLB.pushFullCopy(Pattern); | |||
1008 | TypeSourceInfo *PatternTSInfo = | |||
1009 | TLB.getTypeSourceInfo(Context, Pattern.getType()); | |||
1010 | return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), | |||
1011 | PatternTSInfo); | |||
1012 | } | |||
1013 | ||||
1014 | case TemplateArgument::Expression: { | |||
1015 | PackExpansionExpr *Expansion | |||
1016 | = cast<PackExpansionExpr>(Argument.getAsExpr()); | |||
1017 | Expr *Pattern = Expansion->getPattern(); | |||
1018 | Ellipsis = Expansion->getEllipsisLoc(); | |||
1019 | NumExpansions = Expansion->getNumExpansions(); | |||
1020 | return TemplateArgumentLoc(Pattern, Pattern); | |||
1021 | } | |||
1022 | ||||
1023 | case TemplateArgument::TemplateExpansion: | |||
1024 | Ellipsis = OrigLoc.getTemplateEllipsisLoc(); | |||
1025 | NumExpansions = Argument.getNumTemplateExpansions(); | |||
1026 | return TemplateArgumentLoc(Argument.getPackExpansionPattern(), | |||
1027 | OrigLoc.getTemplateQualifierLoc(), | |||
1028 | OrigLoc.getTemplateNameLoc()); | |||
1029 | ||||
1030 | case TemplateArgument::Declaration: | |||
1031 | case TemplateArgument::NullPtr: | |||
1032 | case TemplateArgument::Template: | |||
1033 | case TemplateArgument::Integral: | |||
1034 | case TemplateArgument::Pack: | |||
1035 | case TemplateArgument::Null: | |||
1036 | return TemplateArgumentLoc(); | |||
1037 | } | |||
1038 | ||||
1039 | llvm_unreachable("Invalid TemplateArgument Kind!")::llvm::llvm_unreachable_internal("Invalid TemplateArgument Kind!" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 1039); | |||
1040 | } | |||
1041 | ||||
1042 | Optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) { | |||
1043 | assert(Arg.containsUnexpandedParameterPack())(static_cast <bool> (Arg.containsUnexpandedParameterPack ()) ? void (0) : __assert_fail ("Arg.containsUnexpandedParameterPack()" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 1043, __extension__ __PRETTY_FUNCTION__)); | |||
1044 | ||||
1045 | // If this is a substituted pack, grab that pack. If not, we don't know | |||
1046 | // the size yet. | |||
1047 | // FIXME: We could find a size in more cases by looking for a substituted | |||
1048 | // pack anywhere within this argument, but that's not necessary in the common | |||
1049 | // case for 'sizeof...(A)' handling. | |||
1050 | TemplateArgument Pack; | |||
1051 | switch (Arg.getKind()) { | |||
1052 | case TemplateArgument::Type: | |||
1053 | if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>()) | |||
1054 | Pack = Subst->getArgumentPack(); | |||
1055 | else | |||
1056 | return None; | |||
1057 | break; | |||
1058 | ||||
1059 | case TemplateArgument::Expression: | |||
1060 | if (auto *Subst = | |||
1061 | dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr())) | |||
1062 | Pack = Subst->getArgumentPack(); | |||
1063 | else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) { | |||
1064 | for (ParmVarDecl *PD : *Subst) | |||
1065 | if (PD->isParameterPack()) | |||
1066 | return None; | |||
1067 | return Subst->getNumExpansions(); | |||
1068 | } else | |||
1069 | return None; | |||
1070 | break; | |||
1071 | ||||
1072 | case TemplateArgument::Template: | |||
1073 | if (SubstTemplateTemplateParmPackStorage *Subst = | |||
1074 | Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack()) | |||
1075 | Pack = Subst->getArgumentPack(); | |||
1076 | else | |||
1077 | return None; | |||
1078 | break; | |||
1079 | ||||
1080 | case TemplateArgument::Declaration: | |||
1081 | case TemplateArgument::NullPtr: | |||
1082 | case TemplateArgument::TemplateExpansion: | |||
1083 | case TemplateArgument::Integral: | |||
1084 | case TemplateArgument::Pack: | |||
1085 | case TemplateArgument::Null: | |||
1086 | return None; | |||
1087 | } | |||
1088 | ||||
1089 | // Check that no argument in the pack is itself a pack expansion. | |||
1090 | for (TemplateArgument Elem : Pack.pack_elements()) { | |||
1091 | // There's no point recursing in this case; we would have already | |||
1092 | // expanded this pack expansion into the enclosing pack if we could. | |||
1093 | if (Elem.isPackExpansion()) | |||
1094 | return None; | |||
1095 | } | |||
1096 | return Pack.pack_size(); | |||
1097 | } | |||
1098 | ||||
1099 | static void CheckFoldOperand(Sema &S, Expr *E) { | |||
1100 | if (!E) | |||
1101 | return; | |||
1102 | ||||
1103 | E = E->IgnoreImpCasts(); | |||
1104 | auto *OCE = dyn_cast<CXXOperatorCallExpr>(E); | |||
1105 | if ((OCE && OCE->isInfixBinaryOp()) || isa<BinaryOperator>(E) || | |||
1106 | isa<AbstractConditionalOperator>(E)) { | |||
1107 | S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand) | |||
1108 | << E->getSourceRange() | |||
1109 | << FixItHint::CreateInsertion(E->getLocStart(), "(") | |||
1110 | << FixItHint::CreateInsertion(E->getLocEnd(), ")"); | |||
1111 | } | |||
1112 | } | |||
1113 | ||||
1114 | ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, | |||
1115 | tok::TokenKind Operator, | |||
1116 | SourceLocation EllipsisLoc, Expr *RHS, | |||
1117 | SourceLocation RParenLoc) { | |||
1118 | // LHS and RHS must be cast-expressions. We allow an arbitrary expression | |||
1119 | // in the parser and reduce down to just cast-expressions here. | |||
1120 | CheckFoldOperand(*this, LHS); | |||
1121 | CheckFoldOperand(*this, RHS); | |||
1122 | ||||
1123 | auto DiscardOperands = [&] { | |||
1124 | CorrectDelayedTyposInExpr(LHS); | |||
1125 | CorrectDelayedTyposInExpr(RHS); | |||
1126 | }; | |||
1127 | ||||
1128 | // [expr.prim.fold]p3: | |||
1129 | // In a binary fold, op1 and op2 shall be the same fold-operator, and | |||
1130 | // either e1 shall contain an unexpanded parameter pack or e2 shall contain | |||
1131 | // an unexpanded parameter pack, but not both. | |||
1132 | if (LHS && RHS && | |||
1133 | LHS->containsUnexpandedParameterPack() == | |||
1134 | RHS->containsUnexpandedParameterPack()) { | |||
1135 | DiscardOperands(); | |||
1136 | return Diag(EllipsisLoc, | |||
1137 | LHS->containsUnexpandedParameterPack() | |||
1138 | ? diag::err_fold_expression_packs_both_sides | |||
1139 | : diag::err_pack_expansion_without_parameter_packs) | |||
1140 | << LHS->getSourceRange() << RHS->getSourceRange(); | |||
1141 | } | |||
1142 | ||||
1143 | // [expr.prim.fold]p2: | |||
1144 | // In a unary fold, the cast-expression shall contain an unexpanded | |||
1145 | // parameter pack. | |||
1146 | if (!LHS || !RHS) { | |||
1147 | Expr *Pack = LHS ? LHS : RHS; | |||
1148 | 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\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Sema/SemaTemplateVariadic.cpp" , 1148, __extension__ __PRETTY_FUNCTION__)); | |||
1149 | DiscardOperands(); | |||
1150 | if (!Pack->containsUnexpandedParameterPack()) | |||
1151 | return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) | |||
1152 | << Pack->getSourceRange(); | |||
1153 | } | |||
1154 | ||||
1155 | BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator); | |||
1156 | return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc); | |||
1157 | } | |||
1158 | ||||
1159 | ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, | |||
1160 | BinaryOperatorKind Operator, | |||
1161 | SourceLocation EllipsisLoc, Expr *RHS, | |||
1162 | SourceLocation RParenLoc) { | |||
1163 | return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS, | |||
1164 | Operator, EllipsisLoc, RHS, RParenLoc); | |||
1165 | } | |||
1166 | ||||
1167 | ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, | |||
1168 | BinaryOperatorKind Operator) { | |||
1169 | // [temp.variadic]p9: | |||
1170 | // If N is zero for a unary fold-expression, the value of the expression is | |||
1171 | // && -> true | |||
1172 | // || -> false | |||
1173 | // , -> void() | |||
1174 | // if the operator is not listed [above], the instantiation is ill-formed. | |||
1175 | // | |||
1176 | // Note that we need to use something like int() here, not merely 0, to | |||
1177 | // prevent the result from being a null pointer constant. | |||
1178 | QualType ScalarType; | |||
1179 | switch (Operator) { | |||
1180 | case BO_LOr: | |||
1181 | return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_false); | |||
1182 | case BO_LAnd: | |||
1183 | return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_true); | |||
1184 | case BO_Comma: | |||
1185 | ScalarType = Context.VoidTy; | |||
1186 | break; | |||
1187 | ||||
1188 | default: | |||
1189 | return Diag(EllipsisLoc, diag::err_fold_expression_empty) | |||
1190 | << BinaryOperator::getOpcodeStr(Operator); | |||
1191 | } | |||
1192 | ||||
1193 | return new (Context) CXXScalarValueInitExpr( | |||
1194 | ScalarType, Context.getTrivialTypeSourceInfo(ScalarType, EllipsisLoc), | |||
1195 | EllipsisLoc); | |||
1196 | } |
1 | //===- PartialDiagnostic.h - Diagnostic "closures" --------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | /// \file | |||
11 | /// \brief Implements a partial diagnostic that can be emitted anwyhere | |||
12 | /// in a DiagnosticBuilder stream. | |||
13 | // | |||
14 | //===----------------------------------------------------------------------===// | |||
15 | ||||
16 | #ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H | |||
17 | #define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H | |||
18 | ||||
19 | #include "clang/Basic/Diagnostic.h" | |||
20 | #include "clang/Basic/LLVM.h" | |||
21 | #include "clang/Basic/SourceLocation.h" | |||
22 | #include "llvm/ADT/SmallVector.h" | |||
23 | #include "llvm/ADT/StringRef.h" | |||
24 | #include <cassert> | |||
25 | #include <cstdint> | |||
26 | #include <string> | |||
27 | #include <type_traits> | |||
28 | #include <utility> | |||
29 | ||||
30 | namespace clang { | |||
31 | ||||
32 | class DeclContext; | |||
33 | class IdentifierInfo; | |||
34 | ||||
35 | class PartialDiagnostic { | |||
36 | public: | |||
37 | enum { | |||
38 | // The MaxArguments and MaxFixItHints member enum values from | |||
39 | // DiagnosticsEngine are private but DiagnosticsEngine declares | |||
40 | // PartialDiagnostic a friend. These enum values are redeclared | |||
41 | // here so that the nested Storage class below can access them. | |||
42 | MaxArguments = DiagnosticsEngine::MaxArguments | |||
43 | }; | |||
44 | ||||
45 | struct Storage { | |||
46 | enum { | |||
47 | /// \brief The maximum number of arguments we can hold. We | |||
48 | /// currently only support up to 10 arguments (%0-%9). | |||
49 | /// | |||
50 | /// A single diagnostic with more than that almost certainly has to | |||
51 | /// be simplified anyway. | |||
52 | MaxArguments = PartialDiagnostic::MaxArguments | |||
53 | }; | |||
54 | ||||
55 | /// \brief The number of entries in Arguments. | |||
56 | unsigned char NumDiagArgs = 0; | |||
57 | ||||
58 | /// \brief Specifies for each argument whether it is in DiagArgumentsStr | |||
59 | /// or in DiagArguments. | |||
60 | unsigned char DiagArgumentsKind[MaxArguments]; | |||
61 | ||||
62 | /// \brief The values for the various substitution positions. | |||
63 | /// | |||
64 | /// This is used when the argument is not an std::string. The specific value | |||
65 | /// is mangled into an intptr_t and the interpretation depends on exactly | |||
66 | /// what sort of argument kind it is. | |||
67 | intptr_t DiagArgumentsVal[MaxArguments]; | |||
68 | ||||
69 | /// \brief The values for the various substitution positions that have | |||
70 | /// string arguments. | |||
71 | std::string DiagArgumentsStr[MaxArguments]; | |||
72 | ||||
73 | /// \brief The list of ranges added to this diagnostic. | |||
74 | SmallVector<CharSourceRange, 8> DiagRanges; | |||
75 | ||||
76 | /// \brief If valid, provides a hint with some code to insert, remove, or | |||
77 | /// modify at a particular position. | |||
78 | SmallVector<FixItHint, 6> FixItHints; | |||
79 | ||||
80 | Storage() = default; | |||
81 | }; | |||
82 | ||||
83 | /// \brief An allocator for Storage objects, which uses a small cache to | |||
84 | /// objects, used to reduce malloc()/free() traffic for partial diagnostics. | |||
85 | class StorageAllocator { | |||
86 | static const unsigned NumCached = 16; | |||
87 | Storage Cached[NumCached]; | |||
88 | Storage *FreeList[NumCached]; | |||
89 | unsigned NumFreeListEntries; | |||
90 | ||||
91 | public: | |||
92 | StorageAllocator(); | |||
93 | ~StorageAllocator(); | |||
94 | ||||
95 | /// \brief Allocate new storage. | |||
96 | Storage *Allocate() { | |||
97 | if (NumFreeListEntries == 0) | |||
98 | return new Storage; | |||
99 | ||||
100 | Storage *Result = FreeList[--NumFreeListEntries]; | |||
101 | Result->NumDiagArgs = 0; | |||
102 | Result->DiagRanges.clear(); | |||
103 | Result->FixItHints.clear(); | |||
104 | return Result; | |||
105 | } | |||
106 | ||||
107 | /// \brief Free the given storage object. | |||
108 | void Deallocate(Storage *S) { | |||
109 | if (S >= Cached && S <= Cached + NumCached) { | |||
110 | FreeList[NumFreeListEntries++] = S; | |||
111 | return; | |||
112 | } | |||
113 | ||||
114 | delete S; | |||
115 | } | |||
116 | }; | |||
117 | ||||
118 | private: | |||
119 | // NOTE: Sema assumes that PartialDiagnostic is location-invariant | |||
120 | // in the sense that its bits can be safely memcpy'ed and destructed | |||
121 | // in the new location. | |||
122 | ||||
123 | /// \brief The diagnostic ID. | |||
124 | mutable unsigned DiagID = 0; | |||
125 | ||||
126 | /// \brief Storage for args and ranges. | |||
127 | mutable Storage *DiagStorage = nullptr; | |||
128 | ||||
129 | /// \brief Allocator used to allocate storage for this diagnostic. | |||
130 | StorageAllocator *Allocator = nullptr; | |||
131 | ||||
132 | /// \brief Retrieve storage for this particular diagnostic. | |||
133 | Storage *getStorage() const { | |||
134 | if (DiagStorage) | |||
135 | return DiagStorage; | |||
136 | ||||
137 | if (Allocator) | |||
138 | DiagStorage = Allocator->Allocate(); | |||
139 | else { | |||
140 | assert(Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))(static_cast <bool> (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) ? void (0) : __assert_fail ("Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 140, __extension__ __PRETTY_FUNCTION__)); | |||
141 | DiagStorage = new Storage; | |||
142 | } | |||
143 | return DiagStorage; | |||
144 | } | |||
145 | ||||
146 | void freeStorage() { | |||
147 | if (!DiagStorage) | |||
148 | return; | |||
149 | ||||
150 | // The hot path for PartialDiagnostic is when we just used it to wrap an ID | |||
151 | // (typically so we have the flexibility of passing a more complex | |||
152 | // diagnostic into the callee, but that does not commonly occur). | |||
153 | // | |||
154 | // Split this out into a slow function for silly compilers (*cough*) which | |||
155 | // can't do decent partial inlining. | |||
156 | freeStorageSlow(); | |||
157 | } | |||
158 | ||||
159 | void freeStorageSlow() { | |||
160 | if (Allocator) | |||
161 | Allocator->Deallocate(DiagStorage); | |||
162 | else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) | |||
163 | delete DiagStorage; | |||
164 | DiagStorage = nullptr; | |||
165 | } | |||
166 | ||||
167 | void AddSourceRange(const CharSourceRange &R) const { | |||
168 | if (!DiagStorage) | |||
169 | DiagStorage = getStorage(); | |||
170 | ||||
171 | DiagStorage->DiagRanges.push_back(R); | |||
172 | } | |||
173 | ||||
174 | void AddFixItHint(const FixItHint &Hint) const { | |||
175 | if (Hint.isNull()) | |||
176 | return; | |||
177 | ||||
178 | if (!DiagStorage) | |||
179 | DiagStorage = getStorage(); | |||
180 | ||||
181 | DiagStorage->FixItHints.push_back(Hint); | |||
182 | } | |||
183 | ||||
184 | public: | |||
185 | struct NullDiagnostic {}; | |||
186 | ||||
187 | /// \brief Create a null partial diagnostic, which cannot carry a payload, | |||
188 | /// and only exists to be swapped with a real partial diagnostic. | |||
189 | PartialDiagnostic(NullDiagnostic) {} | |||
190 | ||||
191 | PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) | |||
192 | : DiagID(DiagID), Allocator(&Allocator) {} | |||
193 | ||||
194 | PartialDiagnostic(const PartialDiagnostic &Other) | |||
195 | : DiagID(Other.DiagID), Allocator(Other.Allocator) { | |||
196 | if (Other.DiagStorage) { | |||
197 | DiagStorage = getStorage(); | |||
198 | *DiagStorage = *Other.DiagStorage; | |||
199 | } | |||
200 | } | |||
201 | ||||
202 | PartialDiagnostic(PartialDiagnostic &&Other) | |||
203 | : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage), | |||
204 | Allocator(Other.Allocator) { | |||
| ||||
205 | Other.DiagStorage = nullptr; | |||
206 | } | |||
207 | ||||
208 | PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) | |||
209 | : DiagID(Other.DiagID), DiagStorage(DiagStorage), | |||
210 | Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) { | |||
211 | if (Other.DiagStorage) | |||
212 | *this->DiagStorage = *Other.DiagStorage; | |||
213 | } | |||
214 | ||||
215 | PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator) | |||
216 | : DiagID(Other.getID()), Allocator(&Allocator) { | |||
217 | // Copy arguments. | |||
218 | for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) { | |||
219 | if (Other.getArgKind(I) == DiagnosticsEngine::ak_std_string) | |||
220 | AddString(Other.getArgStdStr(I)); | |||
221 | else | |||
222 | AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I)); | |||
223 | } | |||
224 | ||||
225 | // Copy source ranges. | |||
226 | for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I) | |||
227 | AddSourceRange(Other.getRange(I)); | |||
228 | ||||
229 | // Copy fix-its. | |||
230 | for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I) | |||
231 | AddFixItHint(Other.getFixItHint(I)); | |||
232 | } | |||
233 | ||||
234 | PartialDiagnostic &operator=(const PartialDiagnostic &Other) { | |||
235 | DiagID = Other.DiagID; | |||
236 | if (Other.DiagStorage) { | |||
237 | if (!DiagStorage) | |||
238 | DiagStorage = getStorage(); | |||
239 | ||||
240 | *DiagStorage = *Other.DiagStorage; | |||
241 | } else { | |||
242 | freeStorage(); | |||
243 | } | |||
244 | ||||
245 | return *this; | |||
246 | } | |||
247 | ||||
248 | PartialDiagnostic &operator=(PartialDiagnostic &&Other) { | |||
249 | freeStorage(); | |||
250 | ||||
251 | DiagID = Other.DiagID; | |||
252 | DiagStorage = Other.DiagStorage; | |||
253 | Allocator = Other.Allocator; | |||
254 | ||||
255 | Other.DiagStorage = nullptr; | |||
256 | return *this; | |||
257 | } | |||
258 | ||||
259 | ~PartialDiagnostic() { | |||
260 | freeStorage(); | |||
261 | } | |||
262 | ||||
263 | void swap(PartialDiagnostic &PD) { | |||
264 | std::swap(DiagID, PD.DiagID); | |||
265 | std::swap(DiagStorage, PD.DiagStorage); | |||
266 | std::swap(Allocator, PD.Allocator); | |||
267 | } | |||
268 | ||||
269 | unsigned getDiagID() const { return DiagID; } | |||
270 | ||||
271 | void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { | |||
272 | if (!DiagStorage) | |||
273 | DiagStorage = getStorage(); | |||
274 | ||||
275 | assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&(static_cast <bool> (DiagStorage->NumDiagArgs < Storage ::MaxArguments && "Too many arguments to diagnostic!" ) ? void (0) : __assert_fail ("DiagStorage->NumDiagArgs < Storage::MaxArguments && \"Too many arguments to diagnostic!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 276, __extension__ __PRETTY_FUNCTION__)) | |||
276 | "Too many arguments to diagnostic!")(static_cast <bool> (DiagStorage->NumDiagArgs < Storage ::MaxArguments && "Too many arguments to diagnostic!" ) ? void (0) : __assert_fail ("DiagStorage->NumDiagArgs < Storage::MaxArguments && \"Too many arguments to diagnostic!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 276, __extension__ __PRETTY_FUNCTION__)); | |||
277 | DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; | |||
278 | DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; | |||
279 | } | |||
280 | ||||
281 | void AddString(StringRef V) const { | |||
282 | if (!DiagStorage) | |||
283 | DiagStorage = getStorage(); | |||
284 | ||||
285 | assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&(static_cast <bool> (DiagStorage->NumDiagArgs < Storage ::MaxArguments && "Too many arguments to diagnostic!" ) ? void (0) : __assert_fail ("DiagStorage->NumDiagArgs < Storage::MaxArguments && \"Too many arguments to diagnostic!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 286, __extension__ __PRETTY_FUNCTION__)) | |||
286 | "Too many arguments to diagnostic!")(static_cast <bool> (DiagStorage->NumDiagArgs < Storage ::MaxArguments && "Too many arguments to diagnostic!" ) ? void (0) : __assert_fail ("DiagStorage->NumDiagArgs < Storage::MaxArguments && \"Too many arguments to diagnostic!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 286, __extension__ __PRETTY_FUNCTION__)); | |||
287 | DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] | |||
288 | = DiagnosticsEngine::ak_std_string; | |||
289 | DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = V; | |||
290 | } | |||
291 | ||||
292 | void Emit(const DiagnosticBuilder &DB) const { | |||
293 | if (!DiagStorage) | |||
294 | return; | |||
295 | ||||
296 | // Add all arguments. | |||
297 | for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) { | |||
298 | if ((DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i] | |||
299 | == DiagnosticsEngine::ak_std_string) | |||
300 | DB.AddString(DiagStorage->DiagArgumentsStr[i]); | |||
301 | else | |||
302 | DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i], | |||
303 | (DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); | |||
304 | } | |||
305 | ||||
306 | // Add all ranges. | |||
307 | for (const CharSourceRange &Range : DiagStorage->DiagRanges) | |||
308 | DB.AddSourceRange(Range); | |||
309 | ||||
310 | // Add all fix-its. | |||
311 | for (const FixItHint &Fix : DiagStorage->FixItHints) | |||
312 | DB.AddFixItHint(Fix); | |||
313 | } | |||
314 | ||||
315 | void EmitToString(DiagnosticsEngine &Diags, | |||
316 | SmallVectorImpl<char> &Buf) const { | |||
317 | // FIXME: It should be possible to render a diagnostic to a string without | |||
318 | // messing with the state of the diagnostics engine. | |||
319 | DiagnosticBuilder DB(Diags.Report(getDiagID())); | |||
320 | Emit(DB); | |||
321 | DB.FlushCounts(); | |||
322 | Diagnostic(&Diags).FormatDiagnostic(Buf); | |||
323 | DB.Clear(); | |||
324 | Diags.Clear(); | |||
325 | } | |||
326 | ||||
327 | /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID | |||
328 | /// and removing all of its arguments, ranges, and fix-it hints. | |||
329 | void Reset(unsigned DiagID = 0) { | |||
330 | this->DiagID = DiagID; | |||
331 | freeStorage(); | |||
332 | } | |||
333 | ||||
334 | bool hasStorage() const { return DiagStorage != nullptr; } | |||
335 | ||||
336 | /// Retrieve the string argument at the given index. | |||
337 | StringRef getStringArg(unsigned I) { | |||
338 | assert(DiagStorage && "No diagnostic storage?")(static_cast <bool> (DiagStorage && "No diagnostic storage?" ) ? void (0) : __assert_fail ("DiagStorage && \"No diagnostic storage?\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 338, __extension__ __PRETTY_FUNCTION__)); | |||
339 | assert(I < DiagStorage->NumDiagArgs && "Not enough diagnostic args")(static_cast <bool> (I < DiagStorage->NumDiagArgs && "Not enough diagnostic args") ? void (0) : __assert_fail ("I < DiagStorage->NumDiagArgs && \"Not enough diagnostic args\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 339, __extension__ __PRETTY_FUNCTION__)); | |||
340 | assert(DiagStorage->DiagArgumentsKind[I](static_cast <bool> (DiagStorage->DiagArgumentsKind[ I] == DiagnosticsEngine::ak_std_string && "Not a string arg" ) ? void (0) : __assert_fail ("DiagStorage->DiagArgumentsKind[I] == DiagnosticsEngine::ak_std_string && \"Not a string arg\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 341, __extension__ __PRETTY_FUNCTION__)) | |||
341 | == DiagnosticsEngine::ak_std_string && "Not a string arg")(static_cast <bool> (DiagStorage->DiagArgumentsKind[ I] == DiagnosticsEngine::ak_std_string && "Not a string arg" ) ? void (0) : __assert_fail ("DiagStorage->DiagArgumentsKind[I] == DiagnosticsEngine::ak_std_string && \"Not a string arg\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Basic/PartialDiagnostic.h" , 341, __extension__ __PRETTY_FUNCTION__)); | |||
342 | return DiagStorage->DiagArgumentsStr[I]; | |||
343 | } | |||
344 | ||||
345 | friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
346 | unsigned I) { | |||
347 | PD.AddTaggedVal(I, DiagnosticsEngine::ak_uint); | |||
348 | return PD; | |||
349 | } | |||
350 | ||||
351 | friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
352 | int I) { | |||
353 | PD.AddTaggedVal(I, DiagnosticsEngine::ak_sint); | |||
354 | return PD; | |||
355 | } | |||
356 | ||||
357 | friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
358 | const char *S) { | |||
359 | PD.AddTaggedVal(reinterpret_cast<intptr_t>(S), | |||
360 | DiagnosticsEngine::ak_c_string); | |||
361 | return PD; | |||
362 | } | |||
363 | ||||
364 | friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
365 | StringRef S) { | |||
366 | ||||
367 | PD.AddString(S); | |||
368 | return PD; | |||
369 | } | |||
370 | ||||
371 | friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
372 | const IdentifierInfo *II) { | |||
373 | PD.AddTaggedVal(reinterpret_cast<intptr_t>(II), | |||
374 | DiagnosticsEngine::ak_identifierinfo); | |||
375 | return PD; | |||
376 | } | |||
377 | ||||
378 | // Adds a DeclContext to the diagnostic. The enable_if template magic is here | |||
379 | // so that we only match those arguments that are (statically) DeclContexts; | |||
380 | // other arguments that derive from DeclContext (e.g., RecordDecls) will not | |||
381 | // match. | |||
382 | template<typename T> | |||
383 | friend inline | |||
384 | typename std::enable_if<std::is_same<T, DeclContext>::value, | |||
385 | const PartialDiagnostic &>::type | |||
386 | operator<<(const PartialDiagnostic &PD, T *DC) { | |||
387 | PD.AddTaggedVal(reinterpret_cast<intptr_t>(DC), | |||
388 | DiagnosticsEngine::ak_declcontext); | |||
389 | return PD; | |||
390 | } | |||
391 | ||||
392 | friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
393 | SourceRange R) { | |||
394 | PD.AddSourceRange(CharSourceRange::getTokenRange(R)); | |||
395 | return PD; | |||
396 | } | |||
397 | ||||
398 | friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
399 | const CharSourceRange &R) { | |||
400 | PD.AddSourceRange(R); | |||
401 | return PD; | |||
402 | } | |||
403 | ||||
404 | friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, | |||
405 | const FixItHint &Hint) { | |||
406 | PD.AddFixItHint(Hint); | |||
407 | return PD; | |||
408 | } | |||
409 | }; | |||
410 | ||||
411 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, | |||
412 | const PartialDiagnostic &PD) { | |||
413 | PD.Emit(DB); | |||
414 | return DB; | |||
415 | } | |||
416 | ||||
417 | /// \brief A partial diagnostic along with the source location where this | |||
418 | /// diagnostic occurs. | |||
419 | using PartialDiagnosticAt = std::pair<SourceLocation, PartialDiagnostic>; | |||
420 | ||||
421 | } // namespace clang | |||
422 | ||||
423 | #endif // LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H |
1 | //===--- SemaInternal.h - Internal Sema Interfaces --------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file provides common API and #includes for the internal |
11 | // implementation of Sema. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_SEMA_SEMAINTERNAL_H |
16 | #define LLVM_CLANG_SEMA_SEMAINTERNAL_H |
17 | |
18 | #include "clang/AST/ASTContext.h" |
19 | #include "clang/Sema/Lookup.h" |
20 | #include "clang/Sema/Sema.h" |
21 | #include "clang/Sema/SemaDiagnostic.h" |
22 | |
23 | namespace clang { |
24 | |
25 | inline PartialDiagnostic Sema::PDiag(unsigned DiagID) { |
26 | return PartialDiagnostic(DiagID, Context.getDiagAllocator()); |
27 | } |
28 | |
29 | inline bool |
30 | FTIHasSingleVoidParameter(const DeclaratorChunk::FunctionTypeInfo &FTI) { |
31 | return FTI.NumParams == 1 && !FTI.isVariadic && |
32 | FTI.Params[0].Ident == nullptr && FTI.Params[0].Param && |
33 | cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType(); |
34 | } |
35 | |
36 | inline bool |
37 | FTIHasNonVoidParameters(const DeclaratorChunk::FunctionTypeInfo &FTI) { |
38 | // Assume FTI is well-formed. |
39 | return FTI.NumParams && !FTIHasSingleVoidParameter(FTI); |
40 | } |
41 | |
42 | // This requires the variable to be non-dependent and the initializer |
43 | // to not be value dependent. |
44 | inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) { |
45 | const VarDecl *DefVD = nullptr; |
46 | return !isa<ParmVarDecl>(Var) && |
47 | Var->isUsableInConstantExpressions(Context) && |
48 | Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE(); |
49 | } |
50 | |
51 | // Helper function to check whether D's attributes match current CUDA mode. |
52 | // Decls with mismatched attributes and related diagnostics may have to be |
53 | // ignored during this CUDA compilation pass. |
54 | inline bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D) { |
55 | if (!LangOpts.CUDA || !D) |
56 | return true; |
57 | bool isDeviceSideDecl = D->hasAttr<CUDADeviceAttr>() || |
58 | D->hasAttr<CUDASharedAttr>() || |
59 | D->hasAttr<CUDAGlobalAttr>(); |
60 | return isDeviceSideDecl == LangOpts.CUDAIsDevice; |
61 | } |
62 | |
63 | // Directly mark a variable odr-used. Given a choice, prefer to use |
64 | // MarkVariableReferenced since it does additional checks and then |
65 | // calls MarkVarDeclODRUsed. |
66 | // If the variable must be captured: |
67 | // - if FunctionScopeIndexToStopAt is null, capture it in the CurContext |
68 | // - else capture it in the DeclContext that maps to the |
69 | // *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack. |
70 | inline void MarkVarDeclODRUsed(VarDecl *Var, |
71 | SourceLocation Loc, Sema &SemaRef, |
72 | const unsigned *const FunctionScopeIndexToStopAt) { |
73 | // Keep track of used but undefined variables. |
74 | // FIXME: We shouldn't suppress this warning for static data members. |
75 | if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && |
76 | (!Var->isExternallyVisible() || Var->isInline() || |
77 | SemaRef.isExternalWithNoLinkageType(Var)) && |
78 | !(Var->isStaticDataMember() && Var->hasInit())) { |
79 | SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()]; |
80 | if (old.isInvalid()) |
81 | old = Loc; |
82 | } |
83 | QualType CaptureType, DeclRefType; |
84 | SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit, |
85 | /*EllipsisLoc*/ SourceLocation(), |
86 | /*BuildAndDiagnose*/ true, |
87 | CaptureType, DeclRefType, |
88 | FunctionScopeIndexToStopAt); |
89 | |
90 | Var->markUsed(SemaRef.Context); |
91 | } |
92 | |
93 | /// Return a DLL attribute from the declaration. |
94 | inline InheritableAttr *getDLLAttr(Decl *D) { |
95 | assert(!(D->hasAttr<DLLImportAttr>() && D->hasAttr<DLLExportAttr>()) &&(static_cast <bool> (!(D->hasAttr<DLLImportAttr> () && D->hasAttr<DLLExportAttr>()) && "A declaration cannot be both dllimport and dllexport.") ? void (0) : __assert_fail ("!(D->hasAttr<DLLImportAttr>() && D->hasAttr<DLLExportAttr>()) && \"A declaration cannot be both dllimport and dllexport.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Sema/SemaInternal.h" , 96, __extension__ __PRETTY_FUNCTION__)) |
96 | "A declaration cannot be both dllimport and dllexport.")(static_cast <bool> (!(D->hasAttr<DLLImportAttr> () && D->hasAttr<DLLExportAttr>()) && "A declaration cannot be both dllimport and dllexport.") ? void (0) : __assert_fail ("!(D->hasAttr<DLLImportAttr>() && D->hasAttr<DLLExportAttr>()) && \"A declaration cannot be both dllimport and dllexport.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Sema/SemaInternal.h" , 96, __extension__ __PRETTY_FUNCTION__)); |
97 | if (auto *Import = D->getAttr<DLLImportAttr>()) |
98 | return Import; |
99 | if (auto *Export = D->getAttr<DLLExportAttr>()) |
100 | return Export; |
101 | return nullptr; |
102 | } |
103 | |
104 | class TypoCorrectionConsumer : public VisibleDeclConsumer { |
105 | typedef SmallVector<TypoCorrection, 1> TypoResultList; |
106 | typedef llvm::StringMap<TypoResultList> TypoResultsMap; |
107 | typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap; |
108 | |
109 | public: |
110 | TypoCorrectionConsumer(Sema &SemaRef, |
111 | const DeclarationNameInfo &TypoName, |
112 | Sema::LookupNameKind LookupKind, |
113 | Scope *S, CXXScopeSpec *SS, |
114 | std::unique_ptr<CorrectionCandidateCallback> CCC, |
115 | DeclContext *MemberContext, |
116 | bool EnteringContext) |
117 | : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0), |
118 | SavedTCIndex(0), SemaRef(SemaRef), S(S), |
119 | SS(SS ? llvm::make_unique<CXXScopeSpec>(*SS) : nullptr), |
120 | CorrectionValidator(std::move(CCC)), MemberContext(MemberContext), |
121 | Result(SemaRef, TypoName, LookupKind), |
122 | Namespaces(SemaRef.Context, SemaRef.CurContext, SS), |
123 | EnteringContext(EnteringContext), SearchNamespaces(false) { |
124 | Result.suppressDiagnostics(); |
125 | // Arrange for ValidatedCorrections[0] to always be an empty correction. |
126 | ValidatedCorrections.push_back(TypoCorrection()); |
127 | } |
128 | |
129 | bool includeHiddenDecls() const override { return true; } |
130 | |
131 | // Methods for adding potential corrections to the consumer. |
132 | void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, |
133 | bool InBaseClass) override; |
134 | void FoundName(StringRef Name); |
135 | void addKeywordResult(StringRef Keyword); |
136 | void addCorrection(TypoCorrection Correction); |
137 | |
138 | bool empty() const { |
139 | return CorrectionResults.empty() && ValidatedCorrections.size() == 1; |
140 | } |
141 | |
142 | /// \brief Return the list of TypoCorrections for the given identifier from |
143 | /// the set of corrections that have the closest edit distance, if any. |
144 | TypoResultList &operator[](StringRef Name) { |
145 | return CorrectionResults.begin()->second[Name]; |
146 | } |
147 | |
148 | /// \brief Return the edit distance of the corrections that have the |
149 | /// closest/best edit distance from the original typop. |
150 | unsigned getBestEditDistance(bool Normalized) { |
151 | if (CorrectionResults.empty()) |
152 | return (std::numeric_limits<unsigned>::max)(); |
153 | |
154 | unsigned BestED = CorrectionResults.begin()->first; |
155 | return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED; |
156 | } |
157 | |
158 | /// \brief Set-up method to add to the consumer the set of namespaces to use |
159 | /// in performing corrections to nested name specifiers. This method also |
160 | /// implicitly adds all of the known classes in the current AST context to the |
161 | /// to the consumer for correcting nested name specifiers. |
162 | void |
163 | addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces); |
164 | |
165 | /// \brief Return the next typo correction that passes all internal filters |
166 | /// and is deemed valid by the consumer's CorrectionCandidateCallback, |
167 | /// starting with the corrections that have the closest edit distance. An |
168 | /// empty TypoCorrection is returned once no more viable corrections remain |
169 | /// in the consumer. |
170 | const TypoCorrection &getNextCorrection(); |
171 | |
172 | /// \brief Get the last correction returned by getNextCorrection(). |
173 | const TypoCorrection &getCurrentCorrection() { |
174 | return CurrentTCIndex < ValidatedCorrections.size() |
175 | ? ValidatedCorrections[CurrentTCIndex] |
176 | : ValidatedCorrections[0]; // The empty correction. |
177 | } |
178 | |
179 | /// \brief Return the next typo correction like getNextCorrection, but keep |
180 | /// the internal state pointed to the current correction (i.e. the next time |
181 | /// getNextCorrection is called, it will return the same correction returned |
182 | /// by peekNextcorrection). |
183 | const TypoCorrection &peekNextCorrection() { |
184 | auto Current = CurrentTCIndex; |
185 | const TypoCorrection &TC = getNextCorrection(); |
186 | CurrentTCIndex = Current; |
187 | return TC; |
188 | } |
189 | |
190 | /// \brief Reset the consumer's position in the stream of viable corrections |
191 | /// (i.e. getNextCorrection() will return each of the previously returned |
192 | /// corrections in order before returning any new corrections). |
193 | void resetCorrectionStream() { |
194 | CurrentTCIndex = 0; |
195 | } |
196 | |
197 | /// \brief Return whether the end of the stream of corrections has been |
198 | /// reached. |
199 | bool finished() { |
200 | return CorrectionResults.empty() && |
201 | CurrentTCIndex >= ValidatedCorrections.size(); |
202 | } |
203 | |
204 | /// \brief Save the current position in the correction stream (overwriting any |
205 | /// previously saved position). |
206 | void saveCurrentPosition() { |
207 | SavedTCIndex = CurrentTCIndex; |
208 | } |
209 | |
210 | /// \brief Restore the saved position in the correction stream. |
211 | void restoreSavedPosition() { |
212 | CurrentTCIndex = SavedTCIndex; |
213 | } |
214 | |
215 | ASTContext &getContext() const { return SemaRef.Context; } |
216 | const LookupResult &getLookupResult() const { return Result; } |
217 | |
218 | bool isAddressOfOperand() const { return CorrectionValidator->IsAddressOfOperand; } |
219 | const CXXScopeSpec *getSS() const { return SS.get(); } |
220 | Scope *getScope() const { return S; } |
221 | CorrectionCandidateCallback *getCorrectionValidator() const { |
222 | return CorrectionValidator.get(); |
223 | } |
224 | |
225 | private: |
226 | class NamespaceSpecifierSet { |
227 | struct SpecifierInfo { |
228 | DeclContext* DeclCtx; |
229 | NestedNameSpecifier* NameSpecifier; |
230 | unsigned EditDistance; |
231 | }; |
232 | |
233 | typedef SmallVector<DeclContext*, 4> DeclContextList; |
234 | typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList; |
235 | |
236 | ASTContext &Context; |
237 | DeclContextList CurContextChain; |
238 | std::string CurNameSpecifier; |
239 | SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers; |
240 | SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers; |
241 | |
242 | std::map<unsigned, SpecifierInfoList> DistanceMap; |
243 | |
244 | /// \brief Helper for building the list of DeclContexts between the current |
245 | /// context and the top of the translation unit |
246 | static DeclContextList buildContextChain(DeclContext *Start); |
247 | |
248 | unsigned buildNestedNameSpecifier(DeclContextList &DeclChain, |
249 | NestedNameSpecifier *&NNS); |
250 | |
251 | public: |
252 | NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, |
253 | CXXScopeSpec *CurScopeSpec); |
254 | |
255 | /// \brief Add the DeclContext (a namespace or record) to the set, computing |
256 | /// the corresponding NestedNameSpecifier and its distance in the process. |
257 | void addNameSpecifier(DeclContext *Ctx); |
258 | |
259 | /// \brief Provides flat iteration over specifiers, sorted by distance. |
260 | class iterator |
261 | : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag, |
262 | SpecifierInfo> { |
263 | /// Always points to the last element in the distance map. |
264 | const std::map<unsigned, SpecifierInfoList>::iterator OuterBack; |
265 | /// Iterator on the distance map. |
266 | std::map<unsigned, SpecifierInfoList>::iterator Outer; |
267 | /// Iterator on an element in the distance map. |
268 | SpecifierInfoList::iterator Inner; |
269 | |
270 | public: |
271 | iterator(NamespaceSpecifierSet &Set, bool IsAtEnd) |
272 | : OuterBack(std::prev(Set.DistanceMap.end())), |
273 | Outer(Set.DistanceMap.begin()), |
274 | Inner(!IsAtEnd ? Outer->second.begin() : OuterBack->second.end()) { |
275 | assert(!Set.DistanceMap.empty())(static_cast <bool> (!Set.DistanceMap.empty()) ? void ( 0) : __assert_fail ("!Set.DistanceMap.empty()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include/clang/Sema/SemaInternal.h" , 275, __extension__ __PRETTY_FUNCTION__)); |
276 | } |
277 | |
278 | iterator &operator++() { |
279 | ++Inner; |
280 | if (Inner == Outer->second.end() && Outer != OuterBack) { |
281 | ++Outer; |
282 | Inner = Outer->second.begin(); |
283 | } |
284 | return *this; |
285 | } |
286 | |
287 | SpecifierInfo &operator*() { return *Inner; } |
288 | bool operator==(const iterator &RHS) const { return Inner == RHS.Inner; } |
289 | }; |
290 | |
291 | iterator begin() { return iterator(*this, /*IsAtEnd=*/false); } |
292 | iterator end() { return iterator(*this, /*IsAtEnd=*/true); } |
293 | }; |
294 | |
295 | void addName(StringRef Name, NamedDecl *ND, |
296 | NestedNameSpecifier *NNS = nullptr, bool isKeyword = false); |
297 | |
298 | /// \brief Find any visible decls for the given typo correction candidate. |
299 | /// If none are found, it to the set of candidates for which qualified lookups |
300 | /// will be performed to find possible nested name specifier changes. |
301 | bool resolveCorrection(TypoCorrection &Candidate); |
302 | |
303 | /// \brief Perform qualified lookups on the queued set of typo correction |
304 | /// candidates and add the nested name specifier changes to each candidate if |
305 | /// a lookup succeeds (at which point the candidate will be returned to the |
306 | /// main pool of potential corrections). |
307 | void performQualifiedLookups(); |
308 | |
309 | /// \brief The name written that is a typo in the source. |
310 | IdentifierInfo *Typo; |
311 | |
312 | /// \brief The results found that have the smallest edit distance |
313 | /// found (so far) with the typo name. |
314 | /// |
315 | /// The pointer value being set to the current DeclContext indicates |
316 | /// whether there is a keyword with this name. |
317 | TypoEditDistanceMap CorrectionResults; |
318 | |
319 | SmallVector<TypoCorrection, 4> ValidatedCorrections; |
320 | size_t CurrentTCIndex; |
321 | size_t SavedTCIndex; |
322 | |
323 | Sema &SemaRef; |
324 | Scope *S; |
325 | std::unique_ptr<CXXScopeSpec> SS; |
326 | std::unique_ptr<CorrectionCandidateCallback> CorrectionValidator; |
327 | DeclContext *MemberContext; |
328 | LookupResult Result; |
329 | NamespaceSpecifierSet Namespaces; |
330 | SmallVector<TypoCorrection, 2> QualifiedResults; |
331 | bool EnteringContext; |
332 | bool SearchNamespaces; |
333 | }; |
334 | |
335 | inline Sema::TypoExprState::TypoExprState() {} |
336 | |
337 | inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) noexcept { |
338 | *this = std::move(other); |
339 | } |
340 | |
341 | inline Sema::TypoExprState &Sema::TypoExprState:: |
342 | operator=(Sema::TypoExprState &&other) noexcept { |
343 | Consumer = std::move(other.Consumer); |
344 | DiagHandler = std::move(other.DiagHandler); |
345 | RecoveryHandler = std::move(other.RecoveryHandler); |
346 | return *this; |
347 | } |
348 | |
349 | } // end namespace clang |
350 | |
351 | #endif |