re PR c++/30897 (ICE with default argument in template template parameter)
authorJason Merrill <jason@gcc.gnu.org>
Fri, 2 Nov 2007 05:50:06 +0000 (01:50 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 2 Nov 2007 05:50:06 +0000 (01:50 -0400)
        PR c++/30897
        * pt.c (push_template_decl_real): Set DECL_CONTEXT on template
        template parms.
        (lookup_template_class): Use it to get the outer template args
        for instantiating one.

        PR c++/29236
        * pt.c (reduce_template_parm_level): tsubst the parameters
        of a template template parm.

From-SVN: r129844

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/ttp23.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/ttp24.C [new file with mode: 0644]

index c784c31f0661c3f95c282629b27324cc77ec030e..90bea18d704c6c825f9faae4e54786a1e81149b8 100644 (file)
@@ -1,3 +1,15 @@
+2007-11-01  Jason Merrill  <jason@redhat.com>
+
+       PR c++/30897
+       * pt.c (push_template_decl_real): Set DECL_CONTEXT on template
+       template parms.
+       (lookup_template_class): Use it to get the outer template args
+       for instantiating one.
+
+       PR c++/29236
+       * pt.c (reduce_template_parm_level): tsubst the parameters
+       of a template template parm.
+
 2007-11-01  Douglas Gregor  <doug.gregor@gmail.com>
 
        PR c++/33955
@@ -33,7 +45,7 @@
            Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/19531
-       * cp/typeck.c (check_return_expr): Don't set named_return_value_okay_p
+       * typeck.c (check_return_expr): Don't set named_return_value_okay_p
        if retval is volatile. 
        
 2007-10-30  Jakub Jelinek  <jakub@redhat.com>
index 8f72ba90ec71583c37df85e2bf58655523096f9d..e9e7789688111b1ed0a84fa0dfe53d79d147d344 100644 (file)
@@ -132,7 +132,7 @@ static bool inline_needs_template_parms (tree);
 static void push_inline_template_parms_recursive (tree, int);
 static tree retrieve_local_specialization (tree);
 static void register_local_specialization (tree, tree);
-static tree reduce_template_parm_level (tree, tree, int);
+static tree reduce_template_parm_level (tree, tree, int, tree, tsubst_flags_t);
 static int mark_template_parm (tree, void *);
 static int template_parm_this_level_p (tree, void *);
 static tree tsubst_friend_function (tree, tree);
@@ -2878,7 +2878,8 @@ canonical_type_parameter (tree type)
    new one is created.  */
 
 static tree
-reduce_template_parm_level (tree index, tree type, int levels)
+reduce_template_parm_level (tree index, tree type, int levels, tree args,
+                           tsubst_flags_t complain)
 {
   if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
       || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
@@ -2903,9 +2904,10 @@ reduce_template_parm_level (tree index, tree type, int levels)
        = TEMPLATE_PARM_PARAMETER_PACK (index);
 
        /* Template template parameters need this.  */
-      if (TREE_CODE (decl) != CONST_DECL)
-       DECL_TEMPLATE_PARMS (decl)
-         = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
+      if (TREE_CODE (decl) == TEMPLATE_DECL)
+       DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
+         (DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index)),
+          args, complain);
     }
 
   return TEMPLATE_PARM_DESCENDANTS (index);
@@ -4000,10 +4002,13 @@ template arguments to %qD do not match original template %qD",
 
   if (primary)
     {
+      tree parms = DECL_TEMPLATE_PARMS (tmpl);
+      int i;
+
       DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
       if (DECL_CONV_FN_P (tmpl))
        {
-         int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+         int depth = TMPL_PARMS_DEPTH (parms);
 
          /* It is a conversion operator. See if the type converted to
             depends on innermost template operands.  */
@@ -4012,6 +4017,16 @@ template arguments to %qD do not match original template %qD",
                                         depth))
            DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
        }
+
+      /* Give template template parms a DECL_CONTEXT of the template
+        for which they are a parameter.  */
+      parms = INNERMOST_TEMPLATE_PARMS (parms);
+      for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
+       {
+         tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+         if (TREE_CODE (parm) == TEMPLATE_DECL)
+           DECL_CONTEXT (parm) = tmpl;
+       }
     }
 
   /* The DECL_TI_ARGS of DECL contains full set of arguments referring
@@ -5392,6 +5407,7 @@ lookup_template_class (tree d1,
 
       tree parm;
       tree arglist2;
+      tree outer;
 
       parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
 
@@ -5404,15 +5420,23 @@ lookup_template_class (tree d1,
         instantiation `TT<int>' is seen, we need to build the full
         arguments containing {int} as the innermost level.  Outer levels,
         available when not appearing as default template argument, can be
-        obtained from `current_template_args ()'.
+        obtained from the arguments of the enclosing template.
 
         Suppose that TT is later substituted with std::vector.  The above
         instantiation is `TT<int, std::allocator<T> >' with TT at
         level 1, and T at level 2, while the template arguments at level 1
         becomes {std::vector} and the inner level 2 is {int}.  */
 
-      if (current_template_parms)
-       arglist = add_to_template_args (current_template_args (), arglist);
+      outer = DECL_CONTEXT (template);
+      if (outer)
+       outer = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (outer)));
+      else if (current_template_parms)
+       /* This is an argument of the current template, so we haven't set
+          DECL_CONTEXT yet.  */
+       outer = current_template_args ();
+
+      if (outer)
+       arglist = add_to_template_args (outer, arglist);
 
       arglist2 = coerce_template_parms (parmlist, arglist, template,
                                        complain,
@@ -8829,7 +8853,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                r = copy_type (t);
                TEMPLATE_TYPE_PARM_INDEX (r)
                  = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
-                                               r, levels);
+                                               r, levels, args, complain);
                TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
                TYPE_MAIN_VARIANT (r) = r;
                TYPE_POINTER_TO (r) = NULL_TREE;
@@ -8863,7 +8887,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            break;
 
          case TEMPLATE_PARM_INDEX:
-           r = reduce_template_parm_level (t, type, levels);
+           r = reduce_template_parm_level (t, type, levels, args, complain);
            break;
 
          default:
diff --git a/gcc/testsuite/g++.dg/template/ttp23.C b/gcc/testsuite/g++.dg/template/ttp23.C
new file mode 100644 (file)
index 0000000..1210f04
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/29236
+
+template <typename T> struct A {};
+
+template <template <typename> class P>
+struct B {
+    template <template <typename> class Q>
+    friend bool foo (const B<Q>& a);
+};
+
+template <template <typename> class Q>
+bool foo (const B<Q>& a);
+
+void bar () {
+  B<A> a;
+  foo (a);
+}
diff --git a/gcc/testsuite/g++.dg/template/ttp24.C b/gcc/testsuite/g++.dg/template/ttp24.C
new file mode 100644 (file)
index 0000000..2b8e285
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/30897
+
+template<template <typename T, typename = T > class U> struct A
+{
+  template<int> U<int> foo();
+};