C++ PATCH for member class templates

Mark Mitchell mark@codesourcery.com
Sat Apr 10 10:50:00 GMT 1999


This patch fixes a situation where we could get confused by member
class templates in a specialization of a template class.

-- 
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-04-10  Mark Mitchell  <mark@codesourcery.com>

	* error.c (dump_type_real): If a typename is a template-id, put
	out the template arguments.
	(dump_expr): Handle TEMPLATE_ID_EXPR.
	* pt.c (lookup_template_class): Now that full arguments are
	available everywhere, remove code that tried to guess them.

Index: testsuite/g++.old-deja/g++.pt/memclass20.C
===================================================================
RCS file: memclass20.C
diff -N memclass20.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- memclass20.C	Sat Apr 10 10:44:48 1999
***************
*** 0 ****
--- 1,18 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ template <class X, class Y>
+ struct S{};
+ 
+ template <class X> 
+ struct S<int, X> {
+   template <class W>
+   struct I {};
+ };
+ 
+ template <class T>
+ void f() {
+   typename S<T, T>::I<T> si;
+ }
+ 
+ template void f<int>();
Index: testsuite/g++.old-deja/cp/error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.72
diff -c -p -r1.72 error.c
*** error.c	1999/04/08 20:16:51	1.72
--- error.c	1999/04/10 17:44:58
*************** dump_type_real (t, v, canonical_name)
*** 321,327 ****
        OB_PUTS ("typename ");
        dump_type_real (TYPE_CONTEXT (t), 0, canonical_name);
        OB_PUTS ("::");
!       OB_PUTID (TYPE_IDENTIFIER (t));
        break;
  
      case TYPEOF_TYPE:
--- 321,327 ----
        OB_PUTS ("typename ");
        dump_type_real (TYPE_CONTEXT (t), 0, canonical_name);
        OB_PUTS ("::");
!       dump_decl (TYPENAME_TYPE_FULLNAME (t), v);
        break;
  
      case TYPEOF_TYPE:
*************** dump_expr (t, nop)
*** 1764,1769 ****
--- 1764,1773 ----
      case WITH_CLEANUP_EXPR:
      case CLEANUP_POINT_EXPR:
        dump_expr (TREE_OPERAND (t, 0), nop);
+       break;
+ 
+     case TEMPLATE_ID_EXPR:
+       dump_decl (t, 0);
        break;
  
      case TREE_LIST:
Index: testsuite/g++.old-deja/cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.280
diff -c -p -r1.280 pt.c
*** pt.c	1999/04/05 01:34:46	1.280
--- pt.c	1999/04/10 17:45:04
*************** lookup_template_class (d1, arglist, in_d
*** 3650,3663 ****
    else 
      {
        tree template_type = TREE_TYPE (template);
        tree type_decl;
        tree found = NULL_TREE;
        int arg_depth;
        int parm_depth;
        int is_partial_instantiation;
  
!       template = most_general_template (template);
!       parmlist = DECL_TEMPLATE_PARMS (template);
        parm_depth = TMPL_PARMS_DEPTH (parmlist);
        arg_depth = TMPL_ARGS_DEPTH (arglist);
  
--- 3650,3664 ----
    else 
      {
        tree template_type = TREE_TYPE (template);
+       tree gen_tmpl;
        tree type_decl;
        tree found = NULL_TREE;
        int arg_depth;
        int parm_depth;
        int is_partial_instantiation;
  
!       gen_tmpl = most_general_template (template);
!       parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
        parm_depth = TMPL_PARMS_DEPTH (parmlist);
        arg_depth = TMPL_ARGS_DEPTH (arglist);
  
*************** lookup_template_class (d1, arglist, in_d
*** 3679,3714 ****
  	     TEMPLATE will be `template <class T> template
  	     <class U> struct S1<T>::S2'.  We must fill in the missing
  	     arguments.  */
! 	  my_friendly_assert (context != NULL_TREE, 0);
! 	  while (!IS_AGGR_TYPE_CODE (TREE_CODE (context))
! 		 && context != global_namespace)
! 	    context = DECL_REAL_CONTEXT (context);
! 
! 	  if (context == global_namespace)
! 	    /* This is bad.  We cannot get enough arguments, even from
! 	       the surrounding context, to resolve this class.  One
! 	       case where this might happen is (illegal) code like:
! 
! 	           template <class U> 
! 		   template <class T>
! 		   struct S { 
! 		     A(const A<T>& a) {}
! 		   };  
! 	    
! 	       We should catch this error sooner (at the opening curly
! 	       for `S', but it is better to be safe than sorry here.  */
! 	    {
! 	      cp_error ("invalid use of `%D'", template);
! 	      return error_mark_node;
! 	    }
! 
! 	  arglist = add_to_template_args (TYPE_TI_ARGS (context),
! 					  arglist);
  	  arg_depth = TMPL_ARGS_DEPTH (arglist);
  	}
  
        my_friendly_assert (parm_depth == arg_depth, 0);
        
        /* Calculate the BOUND_ARGS.  These will be the args that are
  	 actually tsubst'd into the definition to create the
  	 instantiation.  */
--- 3680,3698 ----
  	     TEMPLATE will be `template <class T> template
  	     <class U> struct S1<T>::S2'.  We must fill in the missing
  	     arguments.  */
! 	  arglist 
! 	    = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
! 					   arglist);
  	  arg_depth = TMPL_ARGS_DEPTH (arglist);
  	}
  
+       /* Now we should enough arguments.  */
        my_friendly_assert (parm_depth == arg_depth, 0);
        
+       /* From here on, we're only interested in the most general
+ 	 template.  */
+       template = gen_tmpl;
+ 
        /* Calculate the BOUND_ARGS.  These will be the args that are
  	 actually tsubst'd into the definition to create the
  	 instantiation.  */


More information about the Gcc-patches mailing list