diff mbox

C++ PATCH for c++/66405 (ICE with variadic alias template)

Message ID 5571F4A9.60007@redhat.com
State New
Headers show

Commit Message

Jason Merrill June 5, 2015, 7:12 p.m. UTC
When substituting one pack expansion into another, we try to simplify 
the expansion by substituting one pattern into the other, but this 
doesn't work in this case, because the argument expansion is partially 
instantiated (the enclosing class template's parms are bound, but not 
the member template's) and therefore the expansion has extra args 
attached that we can't throw away.  It would probably be possible to 
propagate the extra args to the resulting substituted expansion, but 
it's simpler not to try to do the expansion.

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

Patch

commit 39ee96b66659979cfdfa54117343b69903d210b0
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jun 5 14:28:34 2015 -0400

    	PR c++/66405
    	* pt.c (argument_pack_element_is_expansion_p): Return 2 if
    	the expansion has extra args.
    	(use_pack_expansion_extra_args_p): Return true in that case.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 87b35fa..4a9fff0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9740,16 +9740,22 @@  make_fnparm_pack (tree spec_parm)
   return extract_fnparm_pack (NULL_TREE, &spec_parm);
 }
 
-/* Return true iff the Ith element of the argument pack ARG_PACK is a
-   pack expansion.  */
+/* Return 1 if the Ith element of the argument pack ARG_PACK is a
+   pack expansion with no extra args, 2 if it has extra args, or 0
+   if it is not a pack expansion.  */
 
-static bool
+static int
 argument_pack_element_is_expansion_p (tree arg_pack, int i)
 {
   tree vec = ARGUMENT_PACK_ARGS (arg_pack);
   if (i >= TREE_VEC_LENGTH (vec))
-    return false;
-  return PACK_EXPANSION_P (TREE_VEC_ELT (vec, i));
+    return 0;
+  tree elt = TREE_VEC_ELT (vec, i);
+  if (!PACK_EXPANSION_P (elt))
+    return 0;
+  if (PACK_EXPANSION_EXTRA_ARGS (elt))
+    return 2;
+  return 1;
 }
 
 
@@ -9799,7 +9805,12 @@  use_pack_expansion_extra_args_p (tree parm_packs,
 	{
 	  tree arg = TREE_VALUE (parm_pack);
 
-	  if (argument_pack_element_is_expansion_p (arg, i))
+	  int exp = argument_pack_element_is_expansion_p (arg, i);
+	  if (exp == 2)
+	    /* We can't substitute a pack expansion with extra args into
+	       our pattern.  */
+	    return true;
+	  else if (exp)
 	    has_expansion_arg = true;
 	  else
 	    has_non_expansion_arg = true;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-alias1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-alias1.C
new file mode 100644
index 0000000..e931bc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-alias1.C
@@ -0,0 +1,13 @@ 
+// PR c++/66405
+// { dg-do compile { target c++11 } }
+
+template <typename T, T...> struct B;
+template <bool... Bools> using and_c = B<bool, +Bools...>;
+template <typename T, typename U> using Constructible = int;
+template <typename... Ts> struct common_tuple {
+  template <typename... Us,
+	    typename = and_c<Constructible<Ts, Us>{}...> >
+    common_tuple();
+  void foo();
+};
+template <> void common_tuple<>::foo(){}