DR 1430 PR c++/51239
authorJason Merrill <jason@redhat.com>
Sat, 3 Aug 2013 20:32:00 +0000 (16:32 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 3 Aug 2013 20:32:00 +0000 (16:32 -0400)
DR 1430
PR c++/51239
* pt.c (pack_expansion_args_count): Rename from
any_pack_expanson_args_p.
(coerce_template_parms): Reject pack expansion to
non-pack template parameter of alias template.

From-SVN: r201469

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/alias-decl-33.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/alias-decl-37.C [new file with mode: 0644]

index 74e5f83..8b9b997 100644 (file)
@@ -1,3 +1,12 @@
+2013-08-03  Jason Merrill  <jason@redhat.com>
+
+       DR 1430
+       PR c++/51239
+       * pt.c (pack_expansion_args_count): Rename from
+       any_pack_expanson_args_p.
+       (coerce_template_parms): Reject pack expansion to
+       non-pack template parameter of alias template.
+
 2013-08-03  Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
        * error.c (dump_aggr_type): Use specialized pretty printer
index 82c72dd..bbaeb7d 100644 (file)
@@ -6542,18 +6542,22 @@ coerce_template_parameter_pack (tree parms,
   return argument_pack;
 }
 
-/* Returns true if the template argument vector ARGS contains
-   any pack expansions, false otherwise.  */
+/* Returns the number of pack expansions in the template argument vector
+   ARGS.  */
 
-static bool
-any_pack_expanson_args_p (tree args)
+static int
+pack_expansion_args_count (tree args)
 {
   int i;
+  int count = 0;
   if (args)
     for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
-      if (PACK_EXPANSION_P (TREE_VEC_ELT (args, i)))
-       return true;
-  return false;
+      {
+       tree elt = TREE_VEC_ELT (args, i);
+       if (elt && PACK_EXPANSION_P (elt))
+         ++count;
+      }
+  return count;
 }
 
 /* Convert all template arguments to their appropriate types, and
@@ -6588,6 +6592,7 @@ coerce_template_parms (tree parms,
      subtract it from nparms to get the number of non-variadic
      parameters.  */
   int variadic_p = 0;
+  int variadic_args_p = 0;
   int post_variadic_parms = 0;
 
   if (args == error_mark_node)
@@ -6617,11 +6622,14 @@ coerce_template_parms (tree parms,
   if (!post_variadic_parms)
     inner_args = expand_template_argument_pack (inner_args);
 
+  /* Count any pack expansion args.  */
+  variadic_args_p = pack_expansion_args_count (inner_args);
+
   nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
   if ((nargs > nparms && !variadic_p)
       || (nargs < nparms - variadic_p
          && require_all_args
-         && !any_pack_expanson_args_p (inner_args)
+         && !variadic_args_p
          && (!use_default_args
              || (TREE_VEC_ELT (parms, nargs) != error_mark_node
                   && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
@@ -6644,6 +6652,33 @@ coerce_template_parms (tree parms,
 
       return error_mark_node;
     }
+  /* We can't pass a pack expansion to a non-pack parameter of an alias
+     template (DR 1430).  */
+  else if (in_decl && DECL_ALIAS_TEMPLATE_P (in_decl)
+          && variadic_args_p
+          && nargs - variadic_args_p < nparms - variadic_p)
+    {
+      if (complain & tf_error)
+       {
+         for (int i = 0; i < TREE_VEC_LENGTH (inner_args); ++i)
+           {
+             tree arg = TREE_VEC_ELT (inner_args, i);
+             tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+
+             if (PACK_EXPANSION_P (arg)
+                 && !template_parameter_pack_p (parm))
+               {
+                 error ("pack expansion argument for non-pack parameter "
+                        "%qD of alias template %qD", parm, in_decl);
+                 inform (DECL_SOURCE_LOCATION (parm), "declared here");
+                 goto found;
+               }
+           }
+         gcc_unreachable ();
+       found:;
+       }
+      return error_mark_node;
+    }
 
   /* We need to evaluate the template arguments, even though this
      template-id may be nested within a "sizeof".  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-33.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-33.C
new file mode 100644 (file)
index 0000000..25781a4
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/51239
+// { dg-require-effective-target c++11 }
+
+template<class... x>
+class list{};
+template<class a, class... b>
+using tail=list<b...>;
+template <class...T>
+void f(tail<T...>);            // { dg-error "alias" }
+
+int main()
+{
+  f<int,int>({});
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-37.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-37.C
new file mode 100644 (file)
index 0000000..d6a3e12
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/57138
+// { dg-do compile { target c++11 } }
+
+template <template <typename ... X> class T, typename ... Y>
+struct D
+{
+  template <typename ... Z>
+  using type = T <Y..., Z...>; // { dg-error "pack expansion" }
+};
+template <typename T>
+class A {};
+template <typename X, typename Y>
+struct B;
+template <typename T>
+struct B <int, T>
+{
+  typedef A <T> type;
+};
+template <typename X, typename Y>
+using C = typename B <X, Y>::type;
+struct E : public D <C> {};