Hi rsmith,
See reddit post for some additional context:
http://www.reddit.com/r/cpp/comments/2nkcvi/generic_lambda_inconsistency/
An ellipsis following an auto should always be parsed as a parameter pack, not
as a c-variadic.
[](auto ...) { }(); // OK.
http://reviews.llvm.org/D6520
Files:
lib/Parse/ParseDecl.cpp
test/SemaCXX/cxx1y-generic-lambdas.cpp
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -4873,19 +4873,43 @@
}
// C++0x [dcl.fct]p14:
- // There is a syntactic ambiguity when an ellipsis occurs at the end
- // of a parameter-declaration-clause without a preceding comma. In
- // this case, the ellipsis is parsed as part of the
- // abstract-declarator if the type of the parameter names a template
- // parameter pack that has not been expanded; otherwise, it is parsed
- // as part of the parameter-declaration-clause.
- if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
- !((D.getContext() == Declarator::PrototypeContext ||
- D.getContext() == Declarator::LambdaExprParameterContext ||
- D.getContext() == Declarator::BlockLiteralContext) &&
- NextToken().is(tok::r_paren) &&
- !D.hasGroupingParens() &&
- !Actions.containsUnexpandedParameterPacks(D))) {
+ // There is a syntactic ambiguity when an ellipsis occurs at the end of a
+ // parameter-declaration-clause without a preceding comma. In this case,
+ // the ellipsis is parsed as part of the abstract-declarator if the type
+ // of the parameter either names a template parameter pack that has not
+ // been expanded or contains auto; otherwise, it is parsed as part of the
+ // parameter-declaration-clause.
+ auto IsEllipsisThatShouldBeParsedAsAbstractDeclarator =
+ [this](const Token &CurTok, Declarator &D) {
+ if (!CurTok.is(tok::ellipsis))
+ return false;
+ // Any scope specifier prevents integrating the ellipsis into the
+ // Declarator.
+ if (!D.getCXXScopeSpec().isEmpty())
+ return false;
+
+ const Declarator::TheContext DCtx = D.getContext();
+ const bool IsParameterDeclarationContext =
+ DCtx == Declarator::PrototypeContext ||
+ DCtx == Declarator::LambdaExprParameterContext ||
+ DCtx == Declarator::BlockLiteralContext;
+
+ // If not in a parameter declaration context; it's a parameter pack.
+ if (!IsParameterDeclarationContext)
+ return true;
+ // Or if the next token is not a right paren; it's a parameter pack.
+ if (!this->NextToken().is(tok::r_paren))
+ return true;
+ // Or if the decl-specifier is 'auto'; it's a parameter pack.
+ if (D.getDeclSpec().getTypeSpecType() == TST_auto)
+ return true;
+ // Or if there are grouping parens; it's a parameter pack.
+ if (D.hasGroupingParens())
+ return true;
+ // Or if the declarator contains an unexpanded parameter pack
+ return this->Actions.containsUnexpandedParameterPacks(D);
+ };
+ if (IsEllipsisThatShouldBeParsedAsAbstractDeclarator(Tok, D)) {
SourceLocation EllipsisLoc = ConsumeToken();
if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) {
// The ellipsis was put in the wrong place. Recover, and explain to
Index: test/SemaCXX/cxx1y-generic-lambdas.cpp
===================================================================
--- test/SemaCXX/cxx1y-generic-lambdas.cpp
+++ test/SemaCXX/cxx1y-generic-lambdas.cpp
@@ -918,3 +918,7 @@
} //end ns inclass_lambdas_within_nested_classes
+
+namespace pr21684_disambiguate_auto_followed_by_ellipsis_no_id {
+int a = [](auto ...) { return 0; }();
+}
\ No newline at end of file
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits