diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-08-15 22:58:45 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-08-15 22:58:45 +0000 |
commit | f26d551387f032e05e5e6551605b150f38c3f5b2 (patch) | |
tree | 16b6afd2a4b23c671315e79621a2cd17cd79938b /clang/lib/Sema/SemaTemplateVariadic.cpp | |
parent | 769124dc5e7ca6ff763eafbddf98fb4ce3bed257 (diff) | |
download | bcm5719-llvm-f26d551387f032e05e5e6551605b150f38c3f5b2.tar.gz bcm5719-llvm-f26d551387f032e05e5e6551605b150f38c3f5b2.zip |
Do not look through pack expansions when looking for unexpanded parameter packs.
Fixes a selection of rejects-valids when pack-expanding a lambda that itself
contains a pack expansion.
llvm-svn: 310972
Diffstat (limited to 'clang/lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 82 |
1 files changed, 64 insertions, 18 deletions
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index e3925e812ac..14b8981f799 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -161,7 +161,7 @@ namespace { return true; } - /// \brief Suppress traversel into types with location information + /// \brief Suppress traversal into types with location information /// that do not contain unexpanded parameter packs. bool TraverseTypeLoc(TypeLoc TL) { if ((!TL.getType().isNull() && @@ -172,19 +172,48 @@ namespace { return true; } - /// \brief Suppress traversal of non-parameter declarations, since - /// they cannot contain unexpanded parameter packs. + /// \brief Suppress traversal of parameter packs. bool TraverseDecl(Decl *D) { - auto *PVD = dyn_cast_or_null<ParmVarDecl>(D); // A function parameter pack is a pack expansion, so cannot contain - // an unexpanded parameter pack. - if (PVD && PVD->isParameterPack()) + // an unexpanded parameter pack. Likewise for a template parameter + // pack that contains any references to other packs. + if (D->isParameterPack()) return true; - if (PVD || InLambda) - return inherited::TraverseDecl(D); + return inherited::TraverseDecl(D); + } - return true; + /// \brief Suppress traversal of pack-expanded attributes. + bool TraverseAttr(Attr *A) { + if (A->isPackExpansion()) + return true; + + return inherited::TraverseAttr(A); + } + + /// \brief Suppress traversal of pack expansion expressions and types. + ///@{ + bool TraversePackExpansionType(PackExpansionType *T) { return true; } + bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; } + bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; } + bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; } + + ///@} + + /// \brief Suppress traversal of using-declaration pack expansion. + bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { + if (D->isPackExpansion()) + return true; + + return inherited::TraverseUnresolvedUsingValueDecl(D); + } + + /// \brief Suppress traversal of using-declaration pack expansion. + bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { + if (D->isPackExpansion()) + return true; + + return inherited::TraverseUnresolvedUsingTypenameDecl(D); } /// \brief Suppress traversal of template argument pack expansions. @@ -203,6 +232,22 @@ namespace { return inherited::TraverseTemplateArgumentLoc(ArgLoc); } + /// \brief Suppress traversal of base specifier pack expansions. + bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) { + if (Base.isPackExpansion()) + return true; + + return inherited::TraverseCXXBaseSpecifier(Base); + } + + /// \brief Suppress traversal of mem-initializer pack expansions. + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + if (Init->isPackExpansion()) + return true; + + return inherited::TraverseConstructorInitializer(Init); + } + /// \brief Note whether we're traversing a lambda containing an unexpanded /// parameter pack. In this case, the unexpanded pack can occur anywhere, /// including all the places where we normally wouldn't look. Within a @@ -233,6 +278,7 @@ namespace { Expr *Init) { if (C->isPackExpansion()) return true; + return inherited::TraverseLambdaCapture(Lambda, C, Init); } }; @@ -266,25 +312,25 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, // parameter pack, and we are done. // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it // later. - SmallVector<UnexpandedParameterPack, 4> GenericLambdaParamReferences; + SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences; for (unsigned N = FunctionScopes.size(); N; --N) { if (sema::LambdaScopeInfo *LSI = dyn_cast<sema::LambdaScopeInfo>(FunctionScopes[N-1])) { - if (LSI->isGenericLambda()) { + if (N == FunctionScopes.size()) { for (auto &Param : Unexpanded) { auto *PD = dyn_cast_or_null<ParmVarDecl>( Param.first.dyn_cast<NamedDecl *>()); if (PD && PD->getDeclContext() == LSI->CallOperator) - GenericLambdaParamReferences.push_back(Param); + LambdaParamPackReferences.push_back(Param); } } - // If we have references to a parameter of a generic lambda, only - // diagnose those ones. We don't know whether any other unexpanded - // parameters referenced herein are actually unexpanded; they might - // be expanded at an outer level. - if (!GenericLambdaParamReferences.empty()) { - Unexpanded = GenericLambdaParamReferences; + // If we have references to a parameter pack of the innermost enclosing + // lambda, only diagnose those ones. We don't know whether any other + // unexpanded parameters referenced herein are actually unexpanded; + // they might be expanded at an outer level. + if (!LambdaParamPackReferences.empty()) { + Unexpanded = LambdaParamPackReferences; break; } |