diff mbox

C++ PATCH for c++/60374 (ICE with missing typename and variadics)

Message ID 533B2E93.6030507@redhat.com
State New
Headers show

Commit Message

Jason Merrill April 1, 2014, 9:24 p.m. UTC
For a normal template argument, we notice missing typename and adjust 
the argument appropriately, but we weren't doing that for a pack 
expansion, leading to confusion later on when we tried to treat a 
SCOPE_REF as a type.  But since the standard requires that any variadic 
template must be well-formed for non-zero pack length, we can go ahead 
and compare the pack expansion pattern to the first template parameter 
to see if they match.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit a6e5d2436bf09049eba9d2f04d12e33621760947
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Apr 1 16:22:01 2014 -0400

    	PR c++/60374
    	* pt.c (coerce_template_parms): Check that the pack expansion
    	pattern works with the first matching parameter.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bfb49d7..9de00d5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6933,6 +6933,26 @@  coerce_template_parms (tree parms,
 	{
           if (PACK_EXPANSION_P (arg))
             {
+	      /* "If every valid specialization of a variadic template
+		 requires an empty template parameter pack, the template is
+		 ill-formed, no diagnostic required."  So check that the
+		 pattern works with this parameter.  */
+	      tree pattern = PACK_EXPANSION_PATTERN (arg);
+	      tree conv = convert_template_argument (TREE_VALUE (parm),
+						     pattern, new_args,
+						     complain, parm_idx,
+						     in_decl);
+	      if (conv == error_mark_node)
+		{
+		  inform (input_location, "so any instantiation with a "
+			 "non-empty parameter pack would be ill-formed");
+		  ++lost;
+		}
+	      else if (TYPE_P (conv) && !TYPE_P (pattern))
+		/* Recover from missing typename.  */
+		TREE_VEC_ELT (inner_args, arg_idx)
+		  = make_pack_expansion (conv);
+
               /* We don't know how many args we have yet, just
                  use the unconverted ones for now.  */
               new_inner_args = inner_args;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic154.C b/gcc/testsuite/g++.dg/cpp0x/variadic154.C
new file mode 100644
index 0000000..198f9c5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic154.C
@@ -0,0 +1,8 @@ 
+// PR c++/60374
+// { dg-do compile { target c++11 } }
+
+template<typename> struct A {};
+
+template<typename...T> struct A<T::T...> {}; // { dg-error "typename|partial|T" }
+
+A<int> a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic155.C b/gcc/testsuite/g++.dg/cpp0x/variadic155.C
new file mode 100644
index 0000000..d912317
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic155.C
@@ -0,0 +1,4 @@ 
+// { dg-do compile { target c++11 } }
+
+template <typename T> struct A {};
+template <int... I> struct B: A<I...> {}; // { dg-error "type" }

commit 522f1b1012384a1d96608690fa79079585038e55
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Apr 1 15:31:59 2014 -0400

    	* pt.c (process_partial_specialization): Say "not deducible"
    	rather than "not used".  Use inform.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9de00d5..7f4ef8b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4139,15 +4139,17 @@  process_partial_specialization (tree decl)
   for (i = 0; i < ntparms; ++i)
     if (tpd.parms[i] == 0)
       {
-	/* One of the template parms was not used in the
+	/* One of the template parms was not used in a deduced context in the
 	   specialization.  */
 	if (!did_error_intro)
 	  {
-	    error ("template parameters not used in partial specialization:");
+	    error ("template parameters not deducible in "
+		   "partial specialization:");
 	    did_error_intro = true;
 	  }
 
-	error ("        %qD", TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
+	inform (input_location, "        %qD",
+		TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
       }
 
   if (did_error_intro)
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31439.C b/gcc/testsuite/g++.dg/cpp0x/pr31439.C
index f753735..df50e41 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31439.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31439.C
@@ -1,7 +1,7 @@ 
 // { dg-do compile { target c++11 } }
 template<typename...> struct A;
 
-template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous|declaration" }
+template<char> struct A<> {}; // { dg-error "not deducible|anonymous|declaration" }
 
 template<typename T, typename... U> struct A<T, U...> : A<U...> {}; // { dg-error "incomplete type" }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-33964.C b/gcc/testsuite/g++.dg/cpp0x/vt-33964.C
index 9e40737..8cbc0d6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-33964.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-33964.C
@@ -6,7 +6,7 @@  struct foo
 };
 
 template<typename ... Args>
-struct foo< typename Args::is_applied... > // { dg-error "not used|Args" }
+struct foo< typename Args::is_applied... > // { dg-error "not deducible|Args" }
 {
     static bool const value = false;
 };
diff --git a/gcc/testsuite/g++.dg/template/crash97.C b/gcc/testsuite/g++.dg/template/crash97.C
index 3d177f4..7d2161f 100644
--- a/gcc/testsuite/g++.dg/template/crash97.C
+++ b/gcc/testsuite/g++.dg/template/crash97.C
@@ -2,7 +2,7 @@ 
 
 template<typename> struct A {};
 
-template<typename> struct A<int> // { dg-error "not used|template\\-parameter" }
+template<typename> struct A<int> // { dg-error "not deducible|template\\-parameter" }
 {
   template<int> void foo();
 };
diff --git a/gcc/testsuite/g++.dg/template/crash98.C b/gcc/testsuite/g++.dg/template/crash98.C
index a79ab02..9d7d2ec 100644
--- a/gcc/testsuite/g++.dg/template/crash98.C
+++ b/gcc/testsuite/g++.dg/template/crash98.C
@@ -2,7 +2,7 @@ 
 
 template < typename > struct A;
 
-template < typename > struct A < int > // { dg-error "not used|template\\-parameter|declaration" }
+template < typename > struct A < int > // { dg-error "not deducible|template\\-parameter|declaration" }
 {
   int i;
   int f ();
diff --git a/gcc/testsuite/g++.dg/template/partial5.C b/gcc/testsuite/g++.dg/template/partial5.C
index aa32e3b..979e4c6 100644
--- a/gcc/testsuite/g++.dg/template/partial5.C
+++ b/gcc/testsuite/g++.dg/template/partial5.C
@@ -4,7 +4,7 @@  template<typename T>
 struct X { };
 
 template<typename T>
-struct X<typename T::foo> { }; // { dg-error "not used|T" }
+struct X<typename T::foo> { }; // { dg-error "not deducible|T" }
 
 template<int N>
 struct X<int[N]> {}; // okay
@@ -14,7 +14,7 @@  template<typename T, typename T::foo V>
 struct Y { };
 
 template<typename T, typename U, U v>
-struct Y<T, v> { }; // { dg-error "not used|U" }
+struct Y<T, v> { }; // { dg-error "not deducible|U" }
 
 
 template<typename T, T V>