pt.c (coerce_template_template_parm): Moved the body of the loop of coerce_template_t...
authorDouglas Gregor <doug.gregor@gmail.com>
Wed, 26 Mar 2008 04:17:57 +0000 (04:17 +0000)
committerDoug Gregor <dgregor@gcc.gnu.org>
Wed, 26 Mar 2008 04:17:57 +0000 (04:17 +0000)
2008-03-26  Douglas Gregor  <doug.gregor@gmail.com>

       * pt.c (coerce_template_template_parm): Moved the body of the loop
       of coerce_template_template_parms here, to make iteration over a
       template argument pack simpler.
       Also, allow matching of a template parameter pack in the template
       template parameter to a template parameter in the template
       template argument.
       (coerce_template_template_parms): Deal with variadic template
       template parameters. Use coerce_template_template_parm.
       (unify): Make sure we coerce the template template argument's
       template arguments to the template template parameter's template
       parameters, not the other way around.

2008-03-26  Douglas Gregor  <doug.gregor@gmail.com>

       * g++.dg/cpp0x/variadic84.C: Update to reflect the change in
       variadic template template parameter binding semantics.
       * g++.dg/cpp0x/variadic85.C: Ditto.
       * g++.dg/cpp0x/variadic88.C: New.
       * g++.dg/cpp0x/variadic89.C: New.
       * g++.dg/cpp0x/variadic90.C: New.
       * g++.dg/cpp0x/variadic-ex14.C: Update to reflect the change in
       variadic template template parameter binding semantics.
       * g++.dg/cpp0x/variadic-lambda.C: New.

From-SVN: r133543

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic84.C
gcc/testsuite/g++.dg/cpp0x/variadic85.C
gcc/testsuite/g++.dg/cpp0x/variadic88.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic89.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic90.C [new file with mode: 0644]

index 5ddc8b555b7824f04a01ec0178751464039334e5..87e8c05ef1d8aeadf548bb332fa5c1dde512292d 100644 (file)
@@ -1,3 +1,17 @@
+2008-03-26  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * pt.c (coerce_template_template_parm): Moved the body of the loop
+       of coerce_template_template_parms here, to make iteration over a
+       template argument pack simpler.
+       Also, allow matching of a template parameter pack in the template
+       template parameter to a template parameter in the template
+       template argument.
+       (coerce_template_template_parms): Deal with variadic template
+       template parameters. Use coerce_template_template_parm.
+       (unify): Make sure we coerce the template template argument's
+       template arguments to the template template parameter's template
+       parameters, not the other way around.
+
 2008-03-25  Tom Tromey  <tromey@redhat.com>
 
        * Make-lang.in: Remove .o targets.
index bc33efc7fbdc30e742a5786fe976e94f0e734090..67d392da456f778d5d80a951a45891bc67789b75 100644 (file)
@@ -4630,6 +4630,77 @@ convert_nontype_argument (tree type, tree expr)
   return expr;
 }
 
+/* Subroutine of coerce_template_template_parms, which returns 1 if
+   PARM_PARM and ARG_PARM match using the rule for the template
+   parameters of template template parameters. Both PARM and ARG are
+   template parameters; the rest of the arguments are the same as for
+   coerce_template_template_parms.
+ */
+static int
+coerce_template_template_parm (tree parm,
+                              tree arg,
+                              tsubst_flags_t complain,
+                              tree in_decl,
+                              tree outer_args)
+{
+  if (arg == NULL_TREE || arg == error_mark_node
+      || parm == NULL_TREE || parm == error_mark_node)
+    return 0;
+  
+  if (TREE_CODE (arg) != TREE_CODE (parm))
+    return 0;
+  
+  switch (TREE_CODE (parm))
+    {
+    case TEMPLATE_DECL:
+      /* We encounter instantiations of templates like
+        template <template <template <class> class> class TT>
+        class C;  */
+      {
+       tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+       tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+       
+       if (!coerce_template_template_parms
+           (parmparm, argparm, complain, in_decl, outer_args))
+         return 0;
+      }
+      /* Fall through.  */
+      
+    case TYPE_DECL:
+      if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg))
+         && !TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+       /* Argument is a parameter pack but parameter is not.  */
+       return 0;
+      break;
+      
+    case PARM_DECL:
+      /* The tsubst call is used to handle cases such as
+        
+           template <int> class C {};
+          template <class T, template <T> class TT> class D {};
+          D<int, C> d;
+
+        i.e. the parameter list of TT depends on earlier parameters.  */
+      if (!dependent_type_p (TREE_TYPE (arg))
+         && !same_type_p
+               (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
+                TREE_TYPE (arg)))
+       return 0;
+      
+      if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg))
+         && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+       /* Argument is a parameter pack but parameter is not.  */
+       return 0;
+      
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return 1;
+}
+
 
 /* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
    template template parameters.  Both PARM_PARMS and ARG_PARMS are
@@ -4652,6 +4723,7 @@ coerce_template_template_parms (tree parm_parms,
 {
   int nparms, nargs, i;
   tree parm, arg;
+  int variadic_p = 0;
 
   gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
   gcc_assert (TREE_CODE (arg_parms) == TREE_VEC);
@@ -4659,10 +4731,37 @@ coerce_template_template_parms (tree parm_parms,
   nparms = TREE_VEC_LENGTH (parm_parms);
   nargs = TREE_VEC_LENGTH (arg_parms);
 
-  if (nargs != nparms)
+  /* Determine whether we have a parameter pack at the end of the
+     template template parameter's template parameter list.  */
+  if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
+    {
+      parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
+      
+      switch (TREE_CODE (parm))
+        {
+        case TEMPLATE_DECL:
+        case TYPE_DECL:
+          if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+            variadic_p = 1;
+          break;
+         
+        case PARM_DECL:
+          if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+            variadic_p = 1;
+          break;
+         
+        default:
+          gcc_unreachable ();
+        }
+    }
+  if (nargs != nparms
+      && !(variadic_p && nargs >= nparms - 1))
     return 0;
 
-  for (i = 0; i < nparms; ++i)
+  /* Check all of the template parameters except the parameter pack at
+     the end (if any).  */
+  for (i = 0; i < nparms - variadic_p; ++i)
     {
       if (TREE_VEC_ELT (parm_parms, i) == error_mark_node
           || TREE_VEC_ELT (arg_parms, i) == error_mark_node)
@@ -4671,60 +4770,35 @@ coerce_template_template_parms (tree parm_parms,
       parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
       arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
 
-      if (arg == NULL_TREE || arg == error_mark_node
-         || parm == NULL_TREE || parm == error_mark_node)
+      if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+                                          outer_args))
        return 0;
 
-      if (TREE_CODE (arg) != TREE_CODE (parm))
-       return 0;
-
-      switch (TREE_CODE (parm))
-       {
-       case TEMPLATE_DECL:
-         /* We encounter instantiations of templates like
-              template <template <template <class> class> class TT>
-              class C;  */
-         {
-           tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
-           tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
-           if (!coerce_template_template_parms
-               (parmparm, argparm, complain, in_decl, outer_args))
-             return 0;
-         }
-         /* Fall through.  */
-
-       case TYPE_DECL:
-         if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))
-             != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg)))
-           /* One is a parameter pack, the other is not.  */
-           return 0;
-         break;
-
-       case PARM_DECL:
-         /* The tsubst call is used to handle cases such as
-
-              template <int> class C {};
-              template <class T, template <T> class TT> class D {};
-              D<int, C> d;
+    }
 
-            i.e. the parameter list of TT depends on earlier parameters.  */
-         if (!dependent_type_p (TREE_TYPE (arg))
-             && !same_type_p
-                   (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
-                            TREE_TYPE (arg)))
-           return 0;
+  if (variadic_p)
+    {
+      /* Check each of the template parameters in the template
+        argument against the template parameter pack at the end of
+        the template template parameter.  */
+      if (TREE_VEC_ELT (parm_parms, i) == error_mark_node)
+       return 0;
 
-         if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
-             != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg)))
-           /* One is a parameter pack, the other is not.  */
-           return 0;
-         break;
+      parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
 
-       default:
-         gcc_unreachable ();
-       }
+      for (; i < nargs; ++i)
+        {
+          if (TREE_VEC_ELT (arg_parms, i) == error_mark_node)
+            continue;
+          arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
+          if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+                                              outer_args))
+            return 0;
+        }
     }
+
   return 1;
 }
 
@@ -12825,8 +12899,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          {
            tree parmvec = TYPE_TI_ARGS (parm);
            tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
-           tree argtmplvec
-             = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
+           tree parm_parms 
+             = DECL_INNERMOST_TEMPLATE_PARMS 
+                 (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
            int i, len;
             int parm_variadic_p = 0;
 
@@ -12857,7 +12932,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
              Here, if Lvalue_proxy is permitted to bind to View, then
              the global operator+ will be used; if they are not, the
              Lvalue_proxy will be converted to float.  */
-           if (coerce_template_parms (argtmplvec, parmvec,
+           if (coerce_template_parms (parm_parms,
+                                       argvec,
                                       TYPE_TI_TEMPLATE (parm),
                                       tf_none,
                                       /*require_all_args=*/true,
index b22d21b3e30d7793e1eaec1563a5c148634a6f74..e3499ad5ea9f53e2585987b3da7e1e9f3ad90d9c 100644 (file)
@@ -1,3 +1,15 @@
+2008-03-26  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * g++.dg/cpp0x/variadic84.C: Update to reflect the change in
+       variadic template template parameter binding semantics.
+       * g++.dg/cpp0x/variadic85.C: Ditto.
+       * g++.dg/cpp0x/variadic88.C: New.
+       * g++.dg/cpp0x/variadic89.C: New.
+       * g++.dg/cpp0x/variadic90.C: New.
+       * g++.dg/cpp0x/variadic-ex14.C: Update to reflect the change in
+       variadic template template parameter binding semantics.
+       * g++.dg/cpp0x/variadic-lambda.C: New.
+
 2008-03-25  Andrew Pinski  <andrew_pinski@playstation.sony.com>
 
        PR target/31558
index 7050256d437630dcdcd1441360e718cf049ddb7f..f33ca0e8618ae8ff4621c4a3e2ec41a77278249c 100644 (file)
@@ -14,10 +14,6 @@ X<B> xB; // { dg-error "mismatch" }
 X<C> xC; // { dg-error "mismatch" }
 // { dg-error "expected a template" "" { target *-*-* } 14 }
 // { dg-error "invalid type" "" { target *-*-* } 14 }
-Y<A> yA; // { dg-error "mismatch" }
-// { dg-error "expected a template" "" { target *-*-* } 17 }
-// { dg-error "invalid type" "" { target *-*-* } 17 }
-Y<B> yB; // { dg-error "mismatch" }
-// { dg-error "expected a template" "" { target *-*-* } 20 }
-// { dg-error "invalid type" "" { target *-*-* } 20 }
+Y<A> yA;
+Y<B> yB;
 Y<C> yC; // okay
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C b/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C
new file mode 100644 (file)
index 0000000..705d441
--- /dev/null
@@ -0,0 +1,79 @@
+// { dg-options "-std=c++0x" }
+
+struct int_placeholder;
+
+template<typename T>
+struct do_replace
+{
+  typedef T type;
+};
+
+template<>
+struct do_replace<int_placeholder>
+{
+  typedef int type;
+};
+
+template<typename T> struct lambdalike
+{
+  typedef T type;
+};
+
+template<template<typename...> class TT, typename... Args>
+struct lambdalike<TT<Args...> > {
+  typedef TT<typename do_replace<Args>::type...> type;
+};
+
+
+template<typename T, typename U>
+struct is_same
+{
+  static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T>
+{
+  static const bool value = true;
+};
+
+template<typename... Elements> struct tuple;
+template<typename T1, typename T2> struct pair;
+
+static_assert(is_same<lambdalike<tuple<float, int_placeholder, double>>::type,
+                     tuple<float, int, double>>::value,
+             "MPL lambda-like replacement on tuple");
+static_assert(is_same<lambdalike<pair<float, int_placeholder>>::type,
+                     pair<float, int>>::value,
+             "MPL lambda-like replacement on pair");
+
+
+struct _1 {};
+
+template<typename Arg0, typename Lambda>
+struct eval
+{
+    typedef Lambda type;
+};
+
+template<typename Arg0>
+struct eval<Arg0, _1>
+{
+    typedef Arg0 type;
+};
+
+template<typename Arg0, template<typename...> class T, typename... Pack>
+struct eval<Arg0, T<Pack...> >
+{
+    typedef T< typename eval<Arg0, Pack>::type... > type;
+};
+
+static_assert(is_same<eval<int, tuple<float, _1, double>>::type,
+                     tuple<float, int, double>>::value, "eval tuple");
+static_assert(is_same<eval<int, pair<_1, double>>::type,
+                     pair<int, double>>::value, "eval pair");
+static_assert(is_same<eval<int, 
+                          tuple<pair<_1, _1>, pair<float, float>,
+                                pair<double, _1>>>::type,
+             tuple<pair<int, int>, pair<float, float>, pair<double, int>>>::value,
+             "recursive eval");
index d5be7646156b33132651cdab44f2d6090afd44be..ce31267954f55ca23ddca24fec07d3bed51d6b03 100644 (file)
@@ -18,9 +18,9 @@ template<int> struct B1 {};
 template<int, int> struct B2 {};
 template<typename> struct B3 {};
 template<typename, typename> struct B4 {};
-A1<B1<0> > a1; // { dg-error "incomplete type" }
-A2<B2<0, 1> > a2; // { dg-error "incomplete type" }
-A3<B2<0, 1> > a3; // { dg-error "incomplete type" }
-A4<B3<int> > a4; // { dg-error "incomplete type" }
-A5<B4<int, long> > a5; // { dg-error "incomplete type" }
-A6<B4<int, long> > a6; // { dg-error "incomplete type" }
+A1<B1<0> > a1;
+A2<B2<0, 1> > a2;
+A3<B2<0, 1> > a3;
+A4<B3<int> > a4;
+A5<B4<int, long> > a5;
+A6<B4<int, long> > a6;
index 7004d086a0f648c4d1eb98ed3aaa8ebe3e253263..facb263910f0c7b2bd866716ea1327ad757d8cd9 100644 (file)
@@ -5,6 +5,6 @@
 template<typename...> struct A1;
 template<template<int, int...> class T> struct A1<T<0, 1> > {};
 template<int, int, int...> struct B1 {};
-A1<B1<0, 1> > a1; // { dg-error "incomplete type" }
+A1<B1<0, 1> > a1;
 template<int...> struct B2 {};
 A1<B2<0, 1> > a2; // { dg-error "incomplete type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic88.C b/gcc/testsuite/g++.dg/cpp0x/variadic88.C
new file mode 100644 (file)
index 0000000..b14cabe
--- /dev/null
@@ -0,0 +1,23 @@
+// { dg-options "-std=c++0x" }
+
+template<template<typename...> class TT>
+TT<int, float, double> foo(TT<int, float>)
+{
+  return TT<int, float, double>();
+}
+
+template<typename T>
+int& foo(T) 
+{ 
+  static int i = 0; return i; 
+}
+
+template<typename T, typename U>
+struct pair {};
+
+void bar()
+{
+  pair<int, float> p;
+  int& i = foo(p);
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic89.C b/gcc/testsuite/g++.dg/cpp0x/variadic89.C
new file mode 100644 (file)
index 0000000..b943771
--- /dev/null
@@ -0,0 +1,14 @@
+// { dg-options "-std=c++0x" }
+// Contributed by Eric Niebler
+template<typename T, typename U>
+struct pair
+{};
+
+template<typename T>
+struct test;
+
+template<template<typename...> class T, typename... Args>
+struct test<T<Args...> >
+{};
+
+test<pair<int, double> > t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic90.C b/gcc/testsuite/g++.dg/cpp0x/variadic90.C
new file mode 100644 (file)
index 0000000..632e166
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+
+template<template<typename...> class TT>
+struct X { };
+
+template<typename T, typename U> struct pair { };
+
+X<pair> x;