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]

Re: C++ PATCH for member template classes



>>>>> "Jason" == Jason Merrill <jason@cygnus.com> writes:

    Jason> This seems wrong; I don't see anything in the standard to
    Jason> suggest that (say) auto_ptr<void>::auto_ptr_ref<int> and
    Jason> auto_ptr<int>::auto_ptr_ref<int> have anything in common.

Actually, on second thought, I'm not sure the patch would have broken
things after all.  Even if specializations_of_same_template_p holds,
unify will be unable to unify the outer template arguments.  So, for
example,

  template <class T>
  struct S
  {
    template <class U>
    struct I {};

    template <class U>
    static void f(I<U> iu);
  };

  void g()
  {
    S<double>::I<char> i;
    S<int>::f(i);
  }

still gives an error, as expected.  But, back to the original test
case:

  template <class T> struct S 
  {
    template <class U> struct I 
    {
    };

    S();
    S(S& s);
    S(I<T>);

    template <class U> operator I<U>();
  };

  S<int> f();
  void g(S<int>);

  void h()
  {
    g(f());
  }

The oddity I referred to earlier, is that when we unify S<int>::I<U>
with S<int>::I<int> it turns out that CLASSTYPE_TI_TEMPLATE for the
former is S<int>::I<U> while for the latter it is S<T>::I<U>.  (That's
why unification failed.)  The reason for this anomaly is that
lookup_template_class doesn't make any effort to find the immediate
parent (S<int>::I<U>) when asked to find a specialization of
S<T>::I<U> given the two levels of args { int, int }.  The attached
patch fixes that problem, which allows the removal of my earlier
patch.

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com

1998-10-13  Mark Mitchell  <mark@markmitchell.com>

	* cp-tree.h (specializations_of_same_template_p): Remove.
	* search.c (get_template_base): Don't use it.
	(get_template_base_recursive): Likewise.
	* pt.c (specializations_of_same_template_p): Remove.
	(unify): Don't use it.
	(lookup_template_class): Find the correct parent when setting
	CLASSTYPE_TI_TEMPLATE.
	
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.151
diff -c -p -r1.151 cp-tree.h
*** cp-tree.h	1998/10/12 02:08:06	1.151
--- cp-tree.h	1998/10/13 21:15:00
*************** extern int is_specialization_of         
*** 2869,2875 ****
  extern int comp_template_args                   PROTO((tree, tree));
  extern void maybe_process_partial_specialization PROTO((tree));
  extern void maybe_check_template_type           PROTO((tree));
- extern int specializations_of_same_template_p   PROTO((tree, tree));
  
  extern int processing_specialization;
  extern int processing_explicit_instantiation;
--- 2869,2874 ----
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.212
diff -c -p -r1.212 pt.c
*** pt.c	1998/10/11 17:38:53	1.212
--- pt.c	1998/10/13 21:15:50
*************** is_specialization_of (decl, tmpl)
*** 756,777 ****
    return 0;
  }
  
- /* Returns nonzero if T1 and T2 are instances of the same template.
-    (They may have different template arguments.)  */
- 
- int
- specializations_of_same_template_p (t1, t2)
-      tree t1;
-      tree t2;
- {
-   /* For now, we only deal with instances of class templates, since
-      that is the only way in which this function is used.  */
- 
-   return (most_general_template (CLASSTYPE_TI_TEMPLATE (t1))
- 	  == most_general_template (CLASSTYPE_TI_TEMPLATE (t2)));
- }
- 
- 
  /* Register the specialization SPEC as a specialization of TMPL with
     the indicated ARGS.  Returns SPEC, or an equivalent prior
     declaration, if available.  */
--- 756,761 ----
*************** classtype_mangled_name (t)
*** 3201,3222 ****
    if (CLASSTYPE_TEMPLATE_INFO (t)
        /* Specializations have already had their names set up in
  	 lookup_template_class.  */
!       && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
        /* For non-primary templates, the template parameters are
  	 implicit from their surrounding context.  */
!       && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
!     {
!       tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
!       char *mangled_name = mangle_class_name_for_template
! 	(IDENTIFIER_POINTER (name),
! 	 DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
! 	 CLASSTYPE_TI_ARGS (t));
!       tree id = get_identifier (mangled_name);
!       IDENTIFIER_TEMPLATE (id) = name;
!       return id;
      }
!   else
!     return TYPE_IDENTIFIER (t);
  }
  
  static void
--- 3185,3210 ----
    if (CLASSTYPE_TEMPLATE_INFO (t)
        /* Specializations have already had their names set up in
  	 lookup_template_class.  */
!       && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
!     {
!       tree tmpl = most_general_template (CLASSTYPE_TI_TEMPLATE (t));
! 
        /* For non-primary templates, the template parameters are
  	 implicit from their surrounding context.  */
!       if (PRIMARY_TEMPLATE_P (tmpl))
! 	{
! 	  tree name = DECL_NAME (tmpl);
! 	  char *mangled_name = mangle_class_name_for_template
! 	    (IDENTIFIER_POINTER (name), 
! 	     DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
! 	     CLASSTYPE_TI_ARGS (t));
! 	  tree id = get_identifier (mangled_name);
! 	  IDENTIFIER_TEMPLATE (id) = name;
! 	  return id;
! 	}
      }
! 
!   return TYPE_IDENTIFIER (t);
  }
  
  static void
*************** lookup_template_class (d1, arglist, in_d
*** 3602,3612 ****
  	}
        else
  	type_decl = TYPE_NAME (t);
  
-       /* Set up the template information.  */
        arglist = copy_to_permanent (arglist);
        SET_TYPE_TEMPLATE_INFO (t,
! 			      tree_cons (template, arglist, NULL_TREE));
        DECL_TEMPLATE_INSTANTIATIONS (template) 
  	= tree_cons (arglist, t, 
  		     DECL_TEMPLATE_INSTANTIATIONS (template));
--- 3590,3649 ----
  	}
        else
  	type_decl = TYPE_NAME (t);
+ 
+       /* Set up the template information.  We have to figure out which
+ 	 template is the immediate parent if this is a full
+ 	 instantiation.  */
+       if (parm_depth == 1 || is_partial_instantiation
+ 	  || !PRIMARY_TEMPLATE_P (template))
+ 	/* This case is easy; there are no member templates involved.  */
+ 	found = template;
+       else
+ 	{
+ 	  /* This is a full instantiation of a member template.  There
+ 	     should be some partial instantiation of which this is an
+ 	     instance.  */
+ 
+ 	  for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ 	       found; found = TREE_CHAIN (found))
+ 	    {
+ 	      int success;
+ 	      tree tmpl = CLASSTYPE_TI_TEMPLATE (TREE_VALUE (found));
+ 
+ 	      /* We only want partial instantiations, here, not
+ 		 specializations or full instantiations.  */
+ 	      if (CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_VALUE (found))
+ 		  || !uses_template_parms (TREE_VALUE (found)))
+ 		continue;
+ 
+ 	      /* Temporarily reduce by one the number of levels in the
+ 		 ARGLIST and in FOUND so as to avoid comparing the
+ 		 last set of arguments.  */
+ 	      TREE_VEC_LENGTH (arglist)--;
+ 	      TREE_VEC_LENGTH (TREE_PURPOSE (found)) --;
+ 
+ 	      /* See if the arguments match.  If they do, then TMPL is
+ 		 the partial instantiation we want.  */
+ 	      success = comp_template_args (TREE_PURPOSE (found), arglist);
+ 
+ 	      /* Restore the argument vectors to their full size.  */
+ 	      TREE_VEC_LENGTH (arglist)++;
+ 	      TREE_VEC_LENGTH (TREE_PURPOSE (found))++;
+ 
+ 	      if (success)
+ 		{
+ 		  found = tmpl;
+ 		  break;
+ 		}
+ 	    }
+ 
+ 	  if (!found)
+ 	    my_friendly_abort (0);
+ 	}
  
        arglist = copy_to_permanent (arglist);
        SET_TYPE_TEMPLATE_INFO (t,
! 			      tree_cons (found, arglist, NULL_TREE));  
        DECL_TEMPLATE_INSTANTIATIONS (template) 
  	= tree_cons (arglist, t, 
  		     DECL_TEMPLATE_INSTANTIATIONS (template));
*************** unify (tparms, targs, parm, arg, strict,
*** 7363,7369 ****
  	       derivation is involved.  */
  	    t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
  	  else if (CLASSTYPE_TEMPLATE_INFO (arg) 
! 		   && specializations_of_same_template_p (parm, arg))
  	    /* Perhaps PARM is something like S<U> and ARG is S<int>.
  	       Then, we should unify `int' and `U'.  */
  	    t = arg;
--- 7400,7407 ----
  	       derivation is involved.  */
  	    t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
  	  else if (CLASSTYPE_TEMPLATE_INFO (arg) 
! 		   && (CLASSTYPE_TI_TEMPLATE (parm) 
! 		       == CLASSTYPE_TI_TEMPLATE (arg)))
  	    /* Perhaps PARM is something like S<U> and ARG is S<int>.
  	       Then, we should unify `int' and `U'.  */
  	    t = arg;
Index: search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.58
diff -c -p -r1.58 search.c
*** search.c	1998/10/11 17:38:52	1.58
--- search.c	1998/10/13 21:15:59
*************** get_template_base_recursive (binfo, rval
*** 3317,3324 ****
    tree type = BINFO_TYPE (binfo);
  
    if (CLASSTYPE_TEMPLATE_INFO (type)
!       && specializations_of_same_template_p (TREE_TYPE (template), 
! 					     type))
      {
        if (rval == NULL_TREE || rval == type)
  	return type;
--- 3317,3323 ----
    tree type = BINFO_TYPE (binfo);
  
    if (CLASSTYPE_TEMPLATE_INFO (type)
!       && CLASSTYPE_TI_TEMPLATE (type) == template)
      {
        if (rval == NULL_TREE || rval == type)
  	return type;
*************** get_template_base (template, binfo)
*** 3376,3383 ****
      my_friendly_abort (92);
  
    if (CLASSTYPE_TEMPLATE_INFO (type)
!       && specializations_of_same_template_p (TREE_TYPE (template), 
! 					     type))
      return type;
  
    rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
--- 3375,3381 ----
      my_friendly_abort (92);
  
    if (CLASSTYPE_TEMPLATE_INFO (type)
!       && CLASSTYPE_TI_TEMPLATE (type) == template)
      return type;
  
    rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com


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