Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -2371,6 +2371,8 @@ Decl *ParseTypeParameter(unsigned Depth, unsigned Position); Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); + void DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc, + SourceLocation CorrectLoc, Declarator *D); // C++ 14.3: Template arguments [temp.arg] typedef SmallVector TemplateArgList; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -5174,7 +5174,7 @@ void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); - Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, + Decl *ActOnTypeParameter(Scope *S, bool Typename, SourceLocation EllipsisLoc, SourceLocation KeyLoc, IdentifierInfo *ParamName, Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -4661,19 +4661,6 @@ } } -static void diagnoseMisplacedEllipsis(Parser &P, Declarator &D, - SourceLocation EllipsisLoc) { - if (EllipsisLoc.isValid()) { - FixItHint Insertion; - if (!D.getEllipsisLoc().isValid()) { - Insertion = FixItHint::CreateInsertion(D.getIdentifierLoc(), "..."); - D.setEllipsisLoc(EllipsisLoc); - } - P.Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration) - << FixItHint::CreateRemoval(EllipsisLoc) << Insertion << !D.hasName(); - } -} - /// ParseDirectDeclarator /// direct-declarator: [C99 6.7.5] /// [C99] identifier @@ -4753,7 +4740,7 @@ // The ellipsis was put in the wrong place. Recover, and explain to // the user what they should have done. ParseDeclarator(D); - diagnoseMisplacedEllipsis(*this, D, EllipsisLoc); + DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(), &D); return; } else D.setEllipsisLoc(EllipsisLoc); @@ -5003,8 +4990,7 @@ D.setGroupingParens(hadGroupingParens); // An ellipsis cannot be placed outside parentheses. - if (EllipsisLoc.isValid()) - diagnoseMisplacedEllipsis(*this, D, EllipsisLoc); + DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(), &D); return; } Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -498,6 +498,10 @@ return nullptr; } + // Recover from misplaced ellipsis. + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, nullptr); + // Grab a default argument (if available). // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before // we introduce the type parameter into the local scope. @@ -507,9 +511,9 @@ DefaultArg = ParseTypeName(/*Range=*/nullptr, Declarator::TemplateTypeArgContext).get(); - return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis, - EllipsisLoc, KeyLoc, ParamName, NameLoc, - Depth, Position, EqualLoc, DefaultArg); + return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc, + KeyLoc, ParamName, NameLoc, Depth, Position, + EqualLoc, DefaultArg); } /// ParseTemplateTemplateParameter - Handle the parsing of template @@ -579,6 +583,10 @@ return nullptr; } + // Recover from misplaced ellipsis. + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, nullptr); + TemplateParameterList *ParamList = Actions.ActOnTemplateParameterList(Depth, SourceLocation(), TemplateLoc, LAngleLoc, @@ -629,6 +637,12 @@ return nullptr; } + // Recover from misplaced ellipsis. + SourceLocation EllipsisLoc; + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsis(EllipsisLoc, ParamDecl.getIdentifierLoc(), + &ParamDecl); + // If there is a default value, parse it. // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before // we introduce the template parameter into the local scope. @@ -654,6 +668,23 @@ DefaultArg.get()); } +void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc, + SourceLocation CorrectLoc, + Declarator *D) { + if (EllipsisLoc.isValid()) { + FixItHint Insertion; + if (D && D->getEllipsisLoc().isInvalid()) { + Insertion = FixItHint::CreateInsertion(CorrectLoc, "..."); + D->setEllipsisLoc(EllipsisLoc); + } + else if (!D && CorrectLoc.isValid()) + Insertion = FixItHint::CreateInsertion(CorrectLoc, "..."); + Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration) + << FixItHint::CreateRemoval(EllipsisLoc) << Insertion + << (D && !D->hasName()); + } +} + /// \brief Parses a '>' at the end of a template list. /// /// If this function encounters '>>', '>>>', '>=', or '>>=', it tries Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -544,7 +544,7 @@ /// ParamNameLoc is the location of the parameter name (if any). /// If the type parameter has a default argument, it will be added /// later via ActOnTypeParameterDefault. -Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, +Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, SourceLocation EllipsisLoc, SourceLocation KeyLoc, IdentifierInfo *ParamName, @@ -560,10 +560,11 @@ if (!ParamName) Loc = KeyLoc; + bool IsParameterPack = EllipsisLoc.isValid(); TemplateTypeParmDecl *Param = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(), KeyLoc, Loc, Depth, Position, ParamName, - Typename, Ellipsis); + Typename, IsParameterPack); Param->setAccess(AS_public); if (Invalid) Param->setInvalidDecl(); @@ -579,7 +580,7 @@ // C++0x [temp.param]p9: // A default template-argument may be specified for any kind of // template-parameter that is not a template parameter pack. - if (DefaultArg && Ellipsis) { + if (DefaultArg && IsParameterPack) { Diag(EqualLoc, diag::err_template_param_pack_default_arg); DefaultArg = ParsedType(); } Index: test/FixIt/fixit-cxx0x.cpp =================================================================== --- test/FixIt/fixit-cxx0x.cpp +++ test/FixIt/fixit-cxx0x.cpp @@ -138,3 +138,14 @@ register int n; // expected-warning {{'register' storage class specifier is deprecated}} return n; } + +namespace MissplacedParameterPack { + template // expected-error {{'...' must immediately precede declared identifier}} + void typeParameter(Args...); + + template