PR c++/35297
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Jan 2009 20:43:01 +0000 (20:43 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Jan 2009 20:43:01 +0000 (20:43 +0000)
        PR c++/35477
        PR c++/35784
        PR c++/36846
        PR c++/38276
        * pt.c (check_default_tmpl_args): Don't complain about
        out-of-order parameter packs in the enclosing class
        or parameter packs after default args.
        (coerce_template_parms): If we have more than one
        parameter pack, don't flatten argument packs.
        (template_args_equal): Handle argument packs.
        (comp_template_args): Don't flatten argument packs.
        (check_instantiated_arg): Split out from...
        (check_instantiated_args): Here.  Handle arg packs.
        (convert_template_argument): Just check that nontype argument
        packs have the right type.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143166 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/variadic65.C
gcc/testsuite/g++.dg/cpp0x/variadic82.C
gcc/testsuite/g++.dg/cpp0x/variadic83.C
gcc/testsuite/g++.dg/cpp0x/variadic92.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic93.C [new file with mode: 0644]

index 1e85539..e1539c5 100644 (file)
@@ -1,3 +1,22 @@
+2009-01-06  Jason Merrill  <jason@redhat.com>
+
+       PR c++/35297
+       PR c++/35477
+       PR c++/35784
+       PR c++/36846
+       PR c++/38276
+       * pt.c (check_default_tmpl_args): Don't complain about
+       out-of-order parameter packs in the enclosing class
+       or parameter packs after default args.
+       (coerce_template_parms): If we have more than one
+       parameter pack, don't flatten argument packs.
+       (template_args_equal): Handle argument packs.
+       (comp_template_args): Don't flatten argument packs.
+       (check_instantiated_arg): Split out from...
+       (check_instantiated_args): Here.  Handle arg packs.
+       (convert_template_argument): Just check that nontype argument
+       packs have the right type.
+
 2009-01-05  Dodji Seketeli  <dodji@redhat.com>
 
        PR c++/38472
index 786e845..410641d 100644 (file)
@@ -3590,7 +3590,8 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
 
               if (TREE_PURPOSE (parm))
                 seen_def_arg_p = 1;
-              else if (seen_def_arg_p)
+              else if (seen_def_arg_p
+                      && !template_parameter_pack_p (TREE_VALUE (parm)))
                 {
                   error ("no default argument for %qD", TREE_VALUE (parm));
                   /* For better subsequent error-recovery, we indicate that
@@ -3601,6 +3602,9 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
              else if (is_primary
                       && !is_partial
                       && !is_friend_decl
+                      /* Don't complain about an enclosing partial
+                         specialization.  */
+                      && parm_level == parms
                       && TREE_CODE (decl) == TYPE_DECL
                       && i < ntparms - 1
                       && template_parameter_pack_p (TREE_VALUE (parm)))
@@ -5060,7 +5064,19 @@ convert_template_argument (tree parm,
       if (invalid_nontype_parm_type_p (t, complain))
        return error_mark_node;
 
-      if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
+      if (template_parameter_pack_p (parm) && ARGUMENT_PACK_P (orig_arg))
+       {
+         if (same_type_p (t, TREE_TYPE (orig_arg)))
+           val = orig_arg;
+         else
+           {
+             /* Not sure if this is reachable, but it doesn't hurt
+                to be robust.  */
+             error ("type mismatch in nontype parameter pack");
+             val = error_mark_node;
+           }
+       }
+      else if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
        /* We used to call digest_init here.  However, digest_init
           will report errors, which we don't want when complain
           is zero.  More importantly, digest_init will try too
@@ -5233,10 +5249,6 @@ coerce_template_parms (tree parms,
      parameters.  */
   int variadic_p = 0;
 
-  inner_args 
-    = expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args));
-
-  nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
   nparms = TREE_VEC_LENGTH (parms);
 
   /* Determine if there are any parameter packs.  */
@@ -5244,13 +5256,22 @@ coerce_template_parms (tree parms,
     {
       tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
       if (template_parameter_pack_p (tparm))
-        {
-          variadic_p = 1;
-          break;
-        }
+       ++variadic_p;
     }
 
-  if ((nargs > nparms - variadic_p && !variadic_p)
+  inner_args = INNERMOST_TEMPLATE_ARGS (args);
+  /* If there are 0 or 1 parameter packs, we need to expand any argument
+     packs so that we can deduce a parameter pack from some non-packed args
+     followed by an argument pack, as in variadic85.C.  If there are more
+     than that, we need to leave argument packs intact so the arguments are
+     assigned to the right parameter packs.  This should only happen when
+     dealing with a nested class inside a partial specialization of a class
+     template, as in variadic92.C.  */
+  if (variadic_p <= 1)
+    inner_args = expand_template_argument_pack (inner_args);
+
+  nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
+  if ((nargs > nparms && !variadic_p)
       || (nargs < nparms - variadic_p
          && require_all_args
          && (!use_default_args
@@ -5297,42 +5318,48 @@ coerce_template_parms (tree parms,
       }
 
       /* Calculate the next argument.  */
-      if (template_parameter_pack_p (TREE_VALUE (parm)))
+      if (arg_idx < nargs)
+       arg = TREE_VEC_ELT (inner_args, arg_idx);
+      else
+       arg = NULL_TREE;
+
+      if (template_parameter_pack_p (TREE_VALUE (parm))
+         && !(arg && ARGUMENT_PACK_P (arg)))
         {
-          /* All remaining arguments will be placed in the
-             template parameter pack PARM.  */
-          arg = coerce_template_parameter_pack (parms, parm_idx, args, 
-                                                inner_args, arg_idx,
-                                                new_args, &lost,
-                                                in_decl, complain);
-          
+         /* All remaining arguments will be placed in the
+            template parameter pack PARM.  */
+         arg = coerce_template_parameter_pack (parms, parm_idx, args, 
+                                               inner_args, arg_idx,
+                                               new_args, &lost,
+                                               in_decl, complain);
+
           /* Store this argument.  */
           if (arg == error_mark_node)
             lost++;
           TREE_VEC_ELT (new_inner_args, parm_idx) = arg;
 
-          /* We are done with all of the arguments.  */
-          arg_idx = nargs;
-
+         /* We are done with all of the arguments.  */
+         arg_idx = nargs;
+          
           continue;
         }
-      else if (arg_idx < nargs)
-        {
-          arg = TREE_VEC_ELT (inner_args, arg_idx);
-
-          if (arg && PACK_EXPANSION_P (arg))
+      else if (arg)
+       {
+          if (PACK_EXPANSION_P (arg))
             {
              if (complain & tf_error)
                {
+                 /* FIXME this restriction was removed by N2555; see
+                    bug 35722.  */
                  /* If ARG is a pack expansion, but PARM is not a
                     template parameter pack (if it were, we would have
                     handled it above), we're trying to expand into a
                     fixed-length argument list.  */
                  if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
-                   error ("cannot expand %<%E%> into a fixed-length "
+                   sorry ("cannot expand %<%E%> into a fixed-length "
                           "argument list", arg);
                  else
-                   error ("cannot expand %<%T%> into a fixed-length "
+                   sorry ("cannot expand %<%T%> into a fixed-length "
                           "argument list", arg);
                }
              return error_mark_node;
@@ -5389,6 +5416,25 @@ template_args_equal (tree ot, tree nt)
     return PACK_EXPANSION_P (nt) 
       && template_args_equal (PACK_EXPANSION_PATTERN (ot),
                               PACK_EXPANSION_PATTERN (nt));
+  else if (ARGUMENT_PACK_P (ot))
+    {
+      int i, len;
+      tree opack, npack;
+
+      if (!ARGUMENT_PACK_P (nt))
+       return 0;
+
+      opack = ARGUMENT_PACK_ARGS (ot);
+      npack = ARGUMENT_PACK_ARGS (nt);
+      len = TREE_VEC_LENGTH (opack);
+      if (TREE_VEC_LENGTH (npack) != len)
+       return 0;
+      for (i = 0; i < len; ++i)
+       if (!template_args_equal (TREE_VEC_ELT (opack, i),
+                                 TREE_VEC_ELT (npack, i)))
+         return 0;
+      return 1;
+    }
   else if (TYPE_P (nt))
     return TYPE_P (ot) && same_type_p (ot, nt);
   else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
@@ -5405,9 +5451,6 @@ comp_template_args (tree oldargs, tree newargs)
 {
   int i;
 
-  oldargs = expand_template_argument_pack (oldargs);
-  newargs = expand_template_argument_pack (newargs);
-
   if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
     return 0;
 
@@ -11707,58 +11750,76 @@ tsubst_copy_and_build (tree t,
    Emit an error under control of COMPLAIN, and return TRUE on error.  */
 
 static bool
-check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
+check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
 {
-  int ix, len = DECL_NTPARMS (tmpl);
-  bool result = false;
+  if (ARGUMENT_PACK_P (t))
+    {
+      tree vec = ARGUMENT_PACK_ARGS (t);
+      int len = TREE_VEC_LENGTH (vec);
+      bool result = false;
+      int i;
 
-  for (ix = 0; ix != len; ix++)
+      for (i = 0; i < len; ++i)
+       if (check_instantiated_arg (tmpl, TREE_VEC_ELT (vec, i), complain))
+         result = true;
+      return result;
+    }
+  else if (TYPE_P (t))
     {
-      tree t = TREE_VEC_ELT (args, ix);
+      /* [basic.link]: A name with no linkage (notably, the name
+        of a class or enumeration declared in a local scope)
+        shall not be used to declare an entity with linkage.
+        This implies that names with no linkage cannot be used as
+        template arguments.  */
+      tree nt = no_linkage_check (t, /*relaxed_p=*/false);
 
-      if (TYPE_P (t))
+      if (nt)
        {
-         /* [basic.link]: A name with no linkage (notably, the name
-            of a class or enumeration declared in a local scope)
-            shall not be used to declare an entity with linkage.
-            This implies that names with no linkage cannot be used as
-            template arguments.  */
-         tree nt = no_linkage_check (t, /*relaxed_p=*/false);
-
-         if (nt)
-           {
-             /* DR 488 makes use of a type with no linkage cause
-                type deduction to fail.  */
-             if (complain & tf_error)
-               {
-                 if (TYPE_ANONYMOUS_P (nt))
-                   error ("%qT is/uses anonymous type", t);
-                 else
-                   error ("template argument for %qD uses local type %qT",
-                          tmpl, t);
-               }
-             result = true;
-           }
-         /* In order to avoid all sorts of complications, we do not
-            allow variably-modified types as template arguments.  */
-         else if (variably_modified_type_p (t, NULL_TREE))
+         /* DR 488 makes use of a type with no linkage cause
+            type deduction to fail.  */
+         if (complain & tf_error)
            {
-             if (complain & tf_error)
-               error ("%qT is a variably modified type", t);
-             result = true;
+             if (TYPE_ANONYMOUS_P (nt))
+               error ("%qT is/uses anonymous type", t);
+             else
+               error ("template argument for %qD uses local type %qT",
+                      tmpl, t);
            }
+         return true;
        }
-      /* A non-type argument of integral or enumerated type must be a
-        constant.  */
-      else if (TREE_TYPE (t)
-              && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
-              && !TREE_CONSTANT (t))
+      /* In order to avoid all sorts of complications, we do not
+        allow variably-modified types as template arguments.  */
+      else if (variably_modified_type_p (t, NULL_TREE))
        {
          if (complain & tf_error)
-           error ("integral expression %qE is not constant", t);
-         result = true;
+           error ("%qT is a variably modified type", t);
+         return true;
        }
     }
+  /* A non-type argument of integral or enumerated type must be a
+     constant.  */
+  else if (TREE_TYPE (t)
+          && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
+          && !TREE_CONSTANT (t))
+    {
+      if (complain & tf_error)
+       error ("integral expression %qE is not constant", t);
+      return true;
+    }
+  return false;
+}
+
+static bool
+check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
+{
+  int ix, len = DECL_NTPARMS (tmpl);
+  bool result = false;
+
+  for (ix = 0; ix != len; ix++)
+    {
+      if (check_instantiated_arg (tmpl, TREE_VEC_ELT (args, ix), complain))
+       result = true;
+    }
   if (result && (complain & tf_error))
     error ("  trying to instantiate %qD", tmpl);
   return result;
index c3e22fc..0e605d0 100644 (file)
@@ -1,3 +1,8 @@
+2009-01-07  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/variadic92.C: New test.
+       * g++.dg/cpp0x/variadic93.C: New test.
+
 2009-01-07  Janis Johnson  <janis187@us.ibm.com>
 
        * lib/target-supports-dg.exp (current_compiler_flags): New.
index 6379da8..1c815d1 100644 (file)
@@ -5,4 +5,4 @@ template<typename T1 = unused, typename T2 = unused, typename T3 = unused,
 struct tuple {};
 
 template<typename... Args>
-void foo(tuple<Args...>) { } // { dg-error "cannot expand" }
+void foo(tuple<Args...>) { } // { dg-bogus "cannot expand" "" { xfail *-*-* } }
index 5acbc83..fb3ddb3 100644 (file)
@@ -3,9 +3,9 @@
 
 template<typename> struct A;
 
-template<typename... T> struct A<T*...> // { dg-error "cannot expand" }
+template<typename... T> struct A<T*...> // { dg-bogus "cannot expand" "" { xfail *-*-* } }
 {
   struct B;
 };
 
-A<void*> a; // { dg-error "incomplete type" }
+A<void*> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
index ec6cabd..2613d62 100644 (file)
@@ -3,6 +3,6 @@
 
 template<typename> struct A;
 
-template<typename... T> struct A<T...> { }; // { dg-error "cannot expand" }
+template<typename... T> struct A<T...> { }; // { dg-bogus "cannot expand" "" { xfail *-*-* } }
 
-A<int> a; // { dg-error "incomplete type" }
+A<int> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic92.C b/gcc/testsuite/g++.dg/cpp0x/variadic92.C
new file mode 100644 (file)
index 0000000..d382912
--- /dev/null
@@ -0,0 +1,70 @@
+// Various tests for variadic templates and partial specialization.
+// { dg-options "-std=c++0x" }
+
+// PR c++/36846
+template<typename A, typename B>
+struct pair;
+
+template<typename... T>
+struct pairs;
+
+template<typename... AS, typename... BS>
+struct pairs<pair<AS, BS>...> {
+  struct mismatched_packs {};
+};
+
+template class pairs<
+  pair<int, int>,
+  pair<int, int>
+>;
+
+template<int A, int B>
+struct point;
+
+template<typename... T>
+struct points;
+
+template<int... AS, int... BS>
+struct points<point<AS, BS>...> {
+  struct mismatched_packs {};
+};
+
+template class points<
+  point<0, 1>,
+  point<0, 1>
+>;
+
+// PR c++/35477
+template <class...ARGS> struct tuple {};
+template <class A, class B> struct test {};
+template <class... ARGS, class B> struct test<B, tuple<ARGS...>>
+{
+    template <class T> struct inside {};
+};
+
+// PR c++/38276
+template<typename...> struct A;
+
+template<typename, typename> struct B;
+
+template<typename... T, typename... U> struct B<A<T...>, A<U...> >
+{
+  static int i;
+};
+
+B<A<>, A<int> > b1;
+
+B<A<int>, A<> > b2;
+
+// PR c++/35784
+template <typename...> struct p;
+
+template <typename, typename> struct d;
+
+template <typename... A, typename... B>
+struct d<p<A...>, p<B...> > { typedef int t; };
+
+typedef d<p<>, p<int, float> >::t q;
+typedef d<q, d<p<int>, p<float> >::t> r; // *
+
+typedef d<d<p<>, p<int, float> >::t, d<p<>, p<> >::t> s;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic93.C b/gcc/testsuite/g++.dg/cpp0x/variadic93.C
new file mode 100644 (file)
index 0000000..7d8c329
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/35297
+// { dg-options "-std=c++0x" }
+
+template <class T=int, class... ARGS> 
+struct test2 {};
+
+int main()
+{
+        test2<> a;
+        return 0;
+}