Things later in compilation were getting confused because we didn't catch the unexpanded parameter pack soon enough.

While looking at this I also fixed a location issue with the error about a parameter pack before the end of a class template parameter list, and avoided some follow-on errors when a template parameter is erroneous.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 93c26661038b76775f56a4a277ee78aa03b23578
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Dec 22 21:41:40 2014 -0500

    	PR c++/63522
    	* parser.c (cp_parser_type_parameter): Call
    	check_for_bare_parameter_packs on default argument.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e57a5bd..2af1576 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13499,6 +13499,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 			    "default arguments");
                 default_argument = NULL_TREE;
               }
+	    else if (check_for_bare_parameter_packs (default_argument))
+	      default_argument = error_mark_node;
 	    pop_deferring_access_checks ();
 	  }
 	else
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic164.C b/gcc/testsuite/g++.dg/cpp0x/variadic164.C
new file mode 100644
index 0000000..8f9cdb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic164.C
@@ -0,0 +1,12 @@
+// PR c++/63522
+// { dg-do compile { target c++11 } }
+
+template <typename...> struct tuple;
+template <typename...> void slice();
+template <int Index, typename...> using slice_result = decltype(slice<Index>);
+template <typename Tuple, typename... Tuples, int... ElementIndices,
+          typename =
+              typename tuple<slice_result<ElementIndices, Tuples...>,
+                             slice_result<ElementIndices, Tuples...>...>::type> // { dg-error "parameter pack" }
+void zip_with(Tuple...);
+decltype(zip_with(0)) d;	// { dg-error "no match" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34052.C b/gcc/testsuite/g++.dg/cpp0x/vt-34052.C
index 1036537..31d2831 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34052.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34052.C
@@ -1,8 +1,8 @@
 // { dg-do compile { target c++11 } }
-template<typename... T, typename = T> struct A {}; // { dg-error "must be at the end" }
+template<typename... T, typename = T> struct A {}; // { dg-error "parameter pack" }
 
 
-template<template<typename... T, typename = T> class U> struct B // { dg-error "must be at the end" }
+template<template<typename... T, typename = T> class U> struct B // { dg-error "parameter pack" }
 {
-  template<int> U<int> foo(); // { dg-error "mismatch|constant|invalid|invalid" }
+  template<int> U<int> foo(); // { dg-error "mismatch|constant|wrong|invalid" }
 };

commit 9fede37842c061ad13cf7ee82d9d94befc68463d
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Dec 23 13:50:27 2014 -0500

    	* pt.c (check_default_tmpl_args): Uses the parameter source
    	location in the diagnostic.
    	(convert_template_argument): Just return if parm is error_mark_node.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f5bd842..21d0d3a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4578,13 +4578,8 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
 		     parameter pack, at the end of the template
 		     parameter list.  */
 
-		  if (TREE_CODE (TREE_VALUE (parm)) == PARM_DECL)
-		    error ("parameter pack %qE must be at the end of the"
-			   " template parameter list", TREE_VALUE (parm));
-		  else
-		    error ("parameter pack %qT must be at the end of the"
-			   " template parameter list", 
-			   TREE_TYPE (TREE_VALUE (parm)));
+		  error ("parameter pack %q+D must be at the end of the"
+			 " template parameter list", TREE_VALUE (parm));
 
 		  TREE_VALUE (TREE_VEC_ELT (inner_parms, i)) 
 		    = error_mark_node;
@@ -6524,6 +6519,9 @@ convert_template_argument (tree parm,
   tree val;
   int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
 
+  if (parm == error_mark_node)
+    return error_mark_node;
+
   if (TREE_CODE (arg) == TREE_LIST
       && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
     {
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31432.C b/gcc/testsuite/g++.dg/cpp0x/pr31432.C
index 1f2ea50..2048077 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31432.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31432.C
@@ -4,5 +4,5 @@ template<typename..., typename> struct A // { dg-error "parameter pack" }
  static int i;
 };
 
-A<int, int> a; // { dg-error "mismatch|expected|invalid type" }
-A<char,int> b; // { dg-error "mismatch|expected|invalid type" }
+A<int, int> a;
+A<char,int> b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31442.C b/gcc/testsuite/g++.dg/cpp0x/pr31442.C
index 7fd20e7..b4c737c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31442.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31442.C
@@ -6,4 +6,4 @@ struct B
   template <template <typename...> class C> B(C<int>);
 };
 
-B b = A<int>(); // { dg-error "mismatch|expected" }
+B b = A<int>();
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32115.C b/gcc/testsuite/g++.dg/cpp0x/pr32115.C
index 5722aa3..fafa4ee 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32115.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32115.C
@@ -1,4 +1,4 @@
 // { dg-do compile { target c++11 } }
 template<typename ...T, int = 0> struct A {}; // { dg-error "end of" }
 
-A<int> a; // { dg-error "mismatch|expected|invalid" }
+A<int> a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic40.C b/gcc/testsuite/g++.dg/cpp0x/variadic40.C
index e4df9b8..e62d62c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic40.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic40.C
@@ -1,3 +1,3 @@
 // { dg-do compile { target c++11 } }
-template<typename... Values, typename T>
-struct backward_tuple {}; // { dg-error "end" }
+template<typename... Values, typename T> // { dg-error "end" }
+struct backward_tuple {};
diff --git a/gcc/testsuite/g++.dg/template/crash55.C b/gcc/testsuite/g++.dg/template/crash55.C
index 7cf9f1e..9b80fd1 100644
--- a/gcc/testsuite/g++.dg/template/crash55.C
+++ b/gcc/testsuite/g++.dg/template/crash55.C
@@ -3,4 +3,4 @@
 template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|valid type" }
 struct A {};
 
-template<int> void foo(A<int>);     // { dg-error "mismatch|constant|template argument" }
+template<int> void foo(A<int>);	// { dg-error "cast|argument" "" { target c++98_only } }
diff --git a/gcc/testsuite/g++.dg/template/crash57.C b/gcc/testsuite/g++.dg/template/crash57.C
index cf1c3c2..ad05e6a 100644
--- a/gcc/testsuite/g++.dg/template/crash57.C
+++ b/gcc/testsuite/g++.dg/template/crash57.C
@@ -7,4 +7,4 @@ template<typename> struct B
     template<int(> struct C;    // { dg-error "token" }
 };
 
-A<char> a;                      // { dg-error "type/value mismatch|constant|declaration" }
+A<char> a;

Reply via email to