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