This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for template template parameter bugs c++/30897 and c++/29236


A couple of problems with template template parameters. In 30897, the previously added code for dealing with default arguments in a template template parameter didn't handle uses of the parameter in a member template. In 29236, substitution of a friend template to reduce its template parameter levels failed to handle the parameters of a template template parameter.

Tested x86_64-pc-linux-gnu, applied to trunk.
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.

Index: cp/pt.c
===================================================================
*** cp/pt.c	(revision 129843)
--- cp/pt.c	(working copy)
*************** static bool inline_needs_template_parms 
*** 132,138 ****
  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 int mark_template_parm (tree, void *);
  static int template_parm_this_level_p (tree, void *);
  static tree tsubst_friend_function (tree, tree);
--- 132,138 ----
  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, 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);
*************** canonical_type_parameter (tree type)
*** 2878,2884 ****
     new one is created.  */
  
  static tree
! reduce_template_parm_level (tree index, tree type, int levels)
  {
    if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
        || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
--- 2878,2885 ----
     new one is created.  */
  
  static tree
! 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))
*************** reduce_template_parm_level (tree index, 
*** 2903,2911 ****
  	= 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));
      }
  
    return TEMPLATE_PARM_DESCENDANTS (index);
--- 2904,2913 ----
  	= TEMPLATE_PARM_PARAMETER_PACK (index);
  
  	/* Template template parameters need this.  */
!       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);
*************** template arguments to %qD do not match o
*** 4000,4009 ****
  
    if (primary)
      {
        DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
        if (DECL_CONV_FN_P (tmpl))
  	{
! 	  int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
  
  	  /* It is a conversion operator. See if the type converted to
  	     depends on innermost template operands.  */
--- 4002,4014 ----
  
    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 (parms);
  
  	  /* It is a conversion operator. See if the type converted to
  	     depends on innermost template operands.  */
*************** template arguments to %qD do not match o
*** 4012,4017 ****
--- 4017,4032 ----
  					 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
*************** lookup_template_class (tree d1,
*** 5392,5397 ****
--- 5407,5413 ----
  
        tree parm;
        tree arglist2;
+       tree outer;
  
        parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
  
*************** lookup_template_class (tree d1,
*** 5404,5418 ****
  	 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 ()'.
  
  	 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);
  
        arglist2 = coerce_template_parms (parmlist, arglist, template,
  					complain,
--- 5420,5442 ----
  	 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 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}.  */
  
!       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,
*************** tsubst (tree t, tree args, tsubst_flags_
*** 8829,8835 ****
  		r = copy_type (t);
  		TEMPLATE_TYPE_PARM_INDEX (r)
  		  = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
! 						r, levels);
  		TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
  		TYPE_MAIN_VARIANT (r) = r;
  		TYPE_POINTER_TO (r) = NULL_TREE;
--- 8853,8859 ----
  		r = copy_type (t);
  		TEMPLATE_TYPE_PARM_INDEX (r)
  		  = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
! 						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;
*************** tsubst (tree t, tree args, tsubst_flags_
*** 8863,8869 ****
  	    break;
  
  	  case TEMPLATE_PARM_INDEX:
! 	    r = reduce_template_parm_level (t, type, levels);
  	    break;
  
  	  default:
--- 8887,8893 ----
  	    break;
  
  	  case TEMPLATE_PARM_INDEX:
! 	    r = reduce_template_parm_level (t, type, levels, args, complain);
  	    break;
  
  	  default:
Index: testsuite/g++.dg/template/ttp23.C
===================================================================
*** testsuite/g++.dg/template/ttp23.C	(revision 0)
--- testsuite/g++.dg/template/ttp23.C	(revision 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);
+ }
Index: testsuite/g++.dg/template/ttp24.C
===================================================================
*** testsuite/g++.dg/template/ttp24.C	(revision 0)
--- testsuite/g++.dg/template/ttp24.C	(revision 0)
***************
*** 0 ****
--- 1,6 ----
+ // PR c++/30897
+ 
+ template<template <typename T, typename = T > class U> struct A
+ {
+   template<int> U<int> foo();
+ };

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]