Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -712,6 +712,8 @@ def err_expected_parameter_pack : Error< "expected the name of a parameter pack">; +def err_misplaced_ellipsis_in_parameter_pack : Error< + "ellipsis comes before the name of template parameter pack">; def err_paren_sizeof_parameter_pack : Error< "missing parentheses around the size of parameter pack %0">; def err_sizeof_parameter_pack : Error< Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -355,7 +355,15 @@ // Somebody probably forgot to close the template. Skip ahead and // try to get out of the expression. This error is currently // subsumed by whatever goes on in ParseTemplateParameter. - Diag(Tok.getLocation(), diag::err_expected_comma_greater); + if (Tok.is(tok::ellipsis)) { + FixItHint FixIt; + if (!TemplateParams.back()->isParameterPack()) + FixIt = FixItHint::CreateInsertion(PrevTokLocation, "... "); + Diag(Tok.getLocation(), diag::err_misplaced_ellipsis_in_parameter_pack) + << FixItHint::CreateRemoval(Tok.getLocation()) << FixIt; + } + else + Diag(Tok.getLocation(), diag::err_expected_comma_greater); SkipUntil(tok::comma, tok::greater, tok::greatergreater, StopAtSemi | StopBeforeMatch); return false; Index: lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -14,6 +14,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/ScopeInfo.h" @@ -247,8 +248,10 @@ : Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more) << (int)UPPC << Names[0] << Names[1]; - for (unsigned I = 0, N = Locations.size(); I != N; ++I) - DB << SourceRange(Locations[I]); + for (auto Location : Locations) + DB << SourceRange(Location); + for (auto Location : Locations) + DB << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Location), "..."); return true; } Index: test/FixIt/fixit-parameter-pack.cpp =================================================================== --- /dev/null +++ test/FixIt/fixit-parameter-pack.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify -x c++ -std=c++11 %s +// RUN: %clang_cc1 -fdiagnostics-parseable-fixits -x c++ -std=c++11 %s 2>&1 | FileCheck %s + +// CHECK: fix-it:"{{.*}}":{10:6-10:8}:"{}" +// CHECK: fix-it:"{{.*}}":{10:6-10:8}:"{}" +template // expected-error {{ellipsis comes before the name of template parameter pack}} +void foo(Args...); + +// CHECK: fix-it:"{{.*}}":{10:6-10:8}:"{}" +template // expected-error {{ellipsis comes before the name of template parameter pack}} +void bar(Args...); + +// CHECK: fix-it:"{{.*}}":{10:6-10:8}:"{}" +template +void baz(Args args...); // expected-error {{unexpanded parameter pack}} +