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]

C++ PATCH for address of overloaded function



This patch fixes our handling of address-of-overloaded-function
expressions to conform to [over.over].  The attached test-cases all
failed in various ways before this patch.

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

1998-12-09  Mark Mitchell  <mark@markmitchell.com>

	* cp-tree.h (most_specialized_instantiation): New function.
	(print_candidates): Likewise.
	* class.c (validate_lhs): Remove.
	(resolve_address_of_overloaded_function): New function, split out
	and then substantially reworked, from ...
	(instantiate_type): Use it.  Simplify.
	* cvt.c (convert_to_reference): Complain when caller has indicated
	that's the right thing to do.  Don't crash if instantiate_type
	fails.
	* pt.c: Substitute `parameters' for `paramters' throughout.
	(print_candidates): Don't make it static.
	(most_specialized_instantiation): Split out from ...
	(most_specialized): Here.

Index: testsuite/g++.old-deja/g++.other/overload8.C
===================================================================
RCS file: overload8.C
diff -N overload8.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- overload8.C	Wed Dec  9 16:09:29 1998
***************
*** 0 ****
--- 1,22 ----
+ class a {
+ public:
+   int f()        { return 0; }
+   int f() const  { return 1; }
+ };
+ 
+ class b : public a {
+ };
+ 
+ int main() 
+ {
+   int (b::* ptr1)()       = &b::f; 
+   int (b::* ptr2)() const = &b::f; 
+   
+   b ao;
+   
+   if ((ao.*ptr1)() != 0)
+     return 1;
+   if ((ao.*ptr2)() != 1)
+     return 1;
+ }
+ 
Index: testsuite/g++.old-deja/g++.pt/overload9.C
===================================================================
RCS file: overload9.C
diff -N overload9.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- overload9.C	Wed Dec  9 16:09:29 1998
***************
*** 0 ****
--- 1,21 ----
+ template <class T>
+ int f(T)
+ {
+   return 1;
+ }
+ 
+ 
+ template <class T>
+ int f(T*)
+ {
+   return 0;
+ }
+ 
+ 
+ int main()
+ {
+   int (*h)(int*) = &f;
+   int (&k)(int*) = f;
+ 
+   return (*h)(0) || (*k)(0);
+ }
Index: testsuite/g++.old-deja/g++.pt/overload10.C
===================================================================
RCS file: overload10.C
diff -N overload10.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- overload10.C	Wed Dec  9 16:09:29 1998
***************
*** 0 ****
--- 1,16 ----
+ struct B {
+   int f(int) { return 1; }
+ };
+ 
+ struct D {
+   template <class T>
+   int f(T) { return 0; }
+ };
+ 
+ int main()
+ {
+   int (D::*g)(int) = &D::f;
+   
+   D d;
+   return (d.*g)(0);
+ }
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.117
diff -c -p -r1.117 class.c
*** class.c	1998/12/03 16:57:58	1.117
--- class.c	1998/12/10 00:09:32
*************** pop_lang_context ()
*** 4971,4997 ****
  
  /* Type instantiation routines.  */
  
  static tree
! validate_lhs (lhstype, complain)
!      tree lhstype;
       int complain;
  {
!   if (TYPE_PTRMEMFUNC_P (lhstype))
!     lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
  
!   if (TREE_CODE (lhstype) == POINTER_TYPE)
      {
!       if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE
! 	  || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
! 	lhstype = TREE_TYPE (lhstype);
        else
  	{
! 	  if (complain)
! 	    error ("invalid type combination for overload");
! 	  return error_mark_node;
  	}
      }
!   return lhstype;
  }
  
  /* This function will instantiate the type of the expression given in
--- 4971,5215 ----
  
  /* Type instantiation routines.  */
  
+ /* Given an OVERLOAD and a TARGET_TYPE, return the function that
+    matches the TARGET_TYPE.  If there is no satisfactory match, return
+    error_mark_node, and issue an error message if COMPLAIN is
+    non-zero.  If TEMPLATE_ONLY, the name of the overloaded function
+    was a template-id, and EXPLICIT_TARGS are the explicitly provided
+    template arguments.  */
+ 
  static tree
! resolve_address_of_overloaded_function (target_type, 
! 					overload,
! 					complain, 
! 					template_only,
! 					explicit_targs)
!      tree target_type;
!      tree overload;
       int complain;
+      int template_only;
+      tree explicit_targs;
  {
!   /* Here's what the standard says:
!      
!        [over.over]
! 
!        If the name is a function template, template argument deduction
!        is done, and if the argument deduction succeeds, the deduced
!        arguments are used to generate a single template function, which
!        is added to the set of overloaded functions considered.
! 
!        Non-member functions and static member functions match targets of
!        type "pointer-to-function" or "reference-to-function."  Nonstatic
!        member functions match targets of type "pointer-to-member
!        function;" the function type of the pointer to member is used to
!        select the member function from the set of overloaded member
!        functions.  If a nonstatic member function is selected, the
!        reference to the overloaded function name is required to have the
!        form of a pointer to member as described in 5.3.1.
! 
!        If more than one function is selected, any template functions in
!        the set are eliminated if the set also contains a non-template
!        function, and any given template function is eliminated if the
!        set contains a second template function that is more specialized
!        than the first according to the partial ordering rules 14.5.5.2.
!        After such eliminations, if any, there shall remain exactly one
!        selected function.  */
! 
!   int is_ptrmem = 0;
!   int is_reference = 0;
!   /* We store the matches in a TREE_LIST rooted here.  The functions
!      are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
!      interoperability with most_specialized_instantiation.  */
!   tree matches = NULL_TREE;
! 
!   /* If the TARGET_TYPE is a pointer-to-a-method, we convert it to
!      proper pointer-to-member type here.  */
!   if (TREE_CODE (target_type) == POINTER_TYPE
!       && TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE)
!     target_type = build_ptrmemfunc_type (target_type);
! 
!   /* Check that the TARGET_TYPE is reasonable.  */
!   if (TYPE_PTRFN_P (target_type))
!     /* This is OK.  */
!     ;
!   else if (TYPE_PTRMEMFUNC_P (target_type))
!     /* This is OK, too.  */
!     is_ptrmem = 1;
!   else if (TREE_CODE (target_type) == FUNCTION_TYPE)
!     {
!       /* This is OK, too.  This comes from a conversion to reference
! 	 type.  */
!       target_type = build_reference_type (target_type);
!       is_reference = 1;
!     }
!   else 
!     {
!       if (complain)
! 	cp_error("cannot resolve overloaded function `%D' based on conversion to type `%T'", 
! 		 DECL_NAME (OVL_FUNCTION (overload)), target_type);
!       return error_mark_node;
!     }
!   
!   /* If we can find a non-template function that matches, we can just
!      use it.  There's no point in generating template instantiations
!      if we're just going to throw them out anyhow.  But, of course, we
!      can only do this when we don't *need* a template function.  */
!   if (!template_only)
!     {
!       tree fns;
! 
!       for (fns = overload; fns; fns = OVL_CHAIN (fns))
! 	{
! 	  tree fn = OVL_FUNCTION (fns);
! 	  tree fntype;
  
! 	  if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	    /* We're not looking for templates just yet.  */
! 	    continue;
! 
! 	  if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
! 	      != is_ptrmem)
! 	    /* We're looking for a non-static member, and this isn't
! 	       one, or vice versa.  */
! 	    continue;
! 	
! 	  /* See if there's a match.  */
! 	  fntype = TREE_TYPE (fn);
! 	  if (is_ptrmem)
! 	    fntype = build_ptrmemfunc_type (build_pointer_type (fntype));
! 	  else if (!is_reference)
! 	    fntype = build_pointer_type (fntype);
! 
! 	  if (can_convert_arg (target_type, fntype, fn))
! 	    matches = scratch_tree_cons (fn, NULL_TREE, matches);
! 	}
!     }
! 
!   /* Now, if we've already got a match (or matches), there's no need
!      to proceed to the template functions.  But, if we don't have a
!      match we need to look at them, too.  */
!   if (!matches) 
      {
!       tree target_fn_type;
!       tree target_arg_types;
!       tree fns;
! 
!       if (is_ptrmem)
! 	{
! 	  target_fn_type
! 	    = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type));
! 	  target_arg_types = TREE_CHAIN (TYPE_ARG_TYPES (target_fn_type));
! 	}
        else
  	{
! 	  target_fn_type = TREE_TYPE (target_type);
! 	  target_arg_types = TYPE_ARG_TYPES (target_fn_type);
  	}
+ 
+       for (fns = overload; fns; fns = OVL_CHAIN (fns))
+ 	{
+ 	  tree fn = OVL_FUNCTION (fns);
+ 	  tree fn_arg_types;
+ 	  tree instantiation;
+ 	  tree instantiation_type;
+ 	  tree targs;
+ 
+ 	  if (TREE_CODE (fn) != TEMPLATE_DECL)
+ 	    /* We're only looking for templates.  */
+ 	    continue;
+ 
+ 	  if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ 	      != is_ptrmem)
+ 	    /* We're looking for a non-static member, and this isn't
+ 	       one, or vice versa.  */
+ 	    continue;
+ 
+ 	  /* We don't use the `this' argument to do argument deduction
+ 	     since that would prevent us from converting a base class
+ 	     pointer-to-member to a derived class pointer-to-member.  */
+ 	  fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ 	  if (is_ptrmem)
+ 	    fn_arg_types = TREE_CHAIN (fn_arg_types);
+ 
+ 	  /* Try to do argument deduction.  */
+ 	  targs = make_scratch_vec (DECL_NTPARMS (fn));
+ 	  if (type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ 				targs,
+ 				fn_arg_types,
+ 				target_arg_types,
+ 				explicit_targs,
+ 				DEDUCE_EXACT,
+ 				/*allow_incomplete=*/1) != 0)
+ 	    /* Argument deduction failed.  */
+ 	    continue;
+ 
+ 	  /* Instantiate the template.  */
+ 	  instantiation = instantiate_template (fn, targs);
+ 	  if (instantiation == error_mark_node)
+ 	    /* Instantiation failed.  */
+ 	    continue;
+ 
+ 	  /* See if there's a match.  */
+ 	  instantiation_type = TREE_TYPE (instantiation);
+ 	  if (is_ptrmem)
+ 	    instantiation_type = 
+ 	      build_ptrmemfunc_type (build_pointer_type (instantiation_type));
+ 	  else if (!is_reference)
+ 	    instantiation_type = build_pointer_type (instantiation_type);
+ 	  if (can_convert_arg (target_type, instantiation_type, instantiation))
+ 	    matches = scratch_tree_cons (instantiation, fn, matches);
+ 	}
+ 
+       /* Now, remove all but the most specialized of the matches.  */
+       if (matches)
+ 	{
+ 	  tree match = most_specialized_instantiation (matches, 
+ 						       explicit_targs);
+ 
+ 	  if (match != error_mark_node)
+ 	    matches = scratch_tree_cons (match, NULL_TREE, NULL_TREE);
+ 	}
+     }
+ 
+   /* Now we should have exactly one function in MATCHES.  */
+   if (matches == NULL_TREE)
+     {
+       /* There were *no* matches.  */
+       if (complain)
+ 	{
+  	  cp_error ("cannot convert overloaded function `%D' to type `%#T'", 
+ 		    DECL_NAME (OVL_FUNCTION (overload)),
+ 		    target_type);
+ 	  cp_error ("because no suitable overload exists");
+ 	}
+       return error_mark_node;
      }
!   else if (TREE_CHAIN (matches))
!     {
!       /* There were too many matches.  */
! 
!       if (complain)
! 	{
! 	  tree match;
! 
!  	  cp_error ("converting overloaded function `%D' to type `%#T' is ambiguous", 
! 		    DECL_NAME (OVL_FUNCTION (overload)),
! 		    target_type);
! 
! 	  /* Since print_candidates expects the functions in the
! 	     TREE_VALUE slot, we flip them here.  */
! 	  for (match = matches; match; match = TREE_CHAIN (match))
! 	    TREE_VALUE (match) = TREE_PURPOSE (match);
! 
! 	  print_candidates (matches);
! 	}
!       
!       return error_mark_node;
!     }
! 
!   /* Good, exactly one match.  */
!   return TREE_PURPOSE (matches);
  }
  
  /* This function will instantiate the type of the expression given in
*************** instantiate_type (lhstype, rhs, complain
*** 5009,5017 ****
       tree lhstype, rhs;
       int complain;
  {
-   tree explicit_targs = NULL_TREE;
-   int template_only = 0;
- 
    if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
      {
        if (complain)
--- 5227,5232 ----
*************** instantiate_type (lhstype, rhs, complain
*** 5109,5250 ****
        /* Fall through.  */
  
      case TEMPLATE_ID_EXPR:
!       {
! 	explicit_targs = TREE_OPERAND (rhs, 1);
! 	template_only = 1;
! 	rhs = TREE_OPERAND (rhs, 0);
!       }
!       /* fall through */
!       my_friendly_assert (TREE_CODE (rhs) == OVERLOAD, 980401);
  
      case OVERLOAD:
!       {
! 	tree elem, elems;
! 
! 	/* Check that the LHSTYPE and the RHS are reasonable.  */
! 	lhstype = validate_lhs (lhstype, complain);
! 	if (lhstype == error_mark_node)
! 	  return lhstype;
  
- 	if (TREE_CODE (lhstype) != FUNCTION_TYPE
- 	    && TREE_CODE (lhstype) != METHOD_TYPE)
- 	  {
- 	    if (complain)
- 	      cp_error("cannot resolve overloaded function `%D' " 
- 		       "based on non-function type `%T'", 
- 		       DECL_NAME (OVL_FUNCTION (rhs)), lhstype);
- 	    return error_mark_node;
- 	  }
- 	
- 	/* Look for an exact match, by searching through the
- 	   overloaded functions.  */
- 	if (template_only)
- 	  /* If we're processing a template-id, only a template
- 	     function can match, so we don't look through the
- 	     overloaded functions.  */
- 	  ;
- 	else for (elems = rhs; elems; elems = OVL_CHAIN (elems))
- 	  {
- 	    elem = OVL_FUNCTION (elems);
- 	    if (TREE_CODE (elem) == FUNCTION_DECL
- 		&& same_type_p (lhstype, TREE_TYPE (elem)))
- 	      {
- 		mark_used (elem);
- 		return elem;
- 	      }
- 	  }
- 
- 	/* No overloaded function was an exact match.  See if we can
- 	   instantiate some template to match.  */
- 	{
- 	  tree save_elem = 0;
- 	  elems = rhs;
- 	  if (TREE_CODE (elems) == TREE_LIST)
- 	    elems = TREE_VALUE (rhs);
- 	  for (; elems; elems = OVL_NEXT (elems))
- 	    if (TREE_CODE (elem = OVL_CURRENT (elems)) == TEMPLATE_DECL)
- 	      {
- 		int n = DECL_NTPARMS (elem);
- 		tree t = make_scratch_vec (n);
- 		int i;
- 		i = type_unification
- 		  (DECL_INNERMOST_TEMPLATE_PARMS (elem), t,
- 		   TYPE_ARG_TYPES (TREE_TYPE (elem)),
- 		   TYPE_ARG_TYPES (lhstype), explicit_targs, DEDUCE_EXACT, 1);
- 		if (i == 0)
- 		  {
- 		    if (save_elem)
- 		      {
- 			cp_error ("ambiguous template instantiation converting to `%#T'", lhstype);
- 			return error_mark_node;
- 		      }
- 		    save_elem = instantiate_template (elem, t);
- 		    /* Check the return type.  */
- 		    if (!same_type_p (TREE_TYPE (lhstype),
- 				      TREE_TYPE (TREE_TYPE (save_elem))))
- 		      save_elem = 0;
- 		  }
- 	      }
- 	  if (save_elem)
- 	    {
- 	      mark_used (save_elem);
- 	      return save_elem;
- 	    }
- 	}
- 
- 	/* There's no exact match, and no templates can be
- 	   instantiated to match.  The last thing we try is to see if
- 	   some ordinary overloaded function is close enough.  If
- 	   we're only looking for template functions, we don't do
- 	   this.  */
- 	if (!template_only)
- 	  {
- 	    for (elems = rhs; elems; elems = OVL_NEXT (elems))
- 	      {
- 		elem = OVL_CURRENT (elems);
- 		if (TREE_CODE (elem) == FUNCTION_DECL
- 		    && comp_target_types (lhstype, TREE_TYPE (elem), 1) > 0)
- 		  break;
- 	      }
- 	    if (elems)
- 	      {
- 		tree save_elem = elem;
- 		for (elems = OVL_CHAIN (elems); elems; 
- 		     elems = OVL_CHAIN (elems))
- 		  {
- 		    elem = OVL_FUNCTION (elems);
- 		    if (TREE_CODE (elem) == FUNCTION_DECL
- 			&& comp_target_types (lhstype, TREE_TYPE (elem), 0) >0)
- 		      break;
- 		  }
- 		if (elems)
- 		  {
- 		    if (complain)
- 		      {
- 			cp_error 
- 			  ("cannot resolve overload to target type `%#T'",
- 			   lhstype);
- 			cp_error_at ("  ambiguity between `%#D'", save_elem); 
- 			cp_error_at ("  and `%#D', at least", elem);
- 		      }
- 		    return error_mark_node;
- 		  }
- 		mark_used (save_elem);
- 		return save_elem;
- 	      }
- 	  }
- 
- 	/* We failed to find a match.  */
- 	if (complain)
- 	  {
- 	    cp_error ("cannot resolve overload to target type `%#T'", lhstype);
- 	    cp_error 
- 	      ("  because no suitable overload of function `%D' exists",
- 	       DECL_NAME (OVL_FUNCTION (rhs)));
- 	  }
- 	return error_mark_node;
-       }
- 
      case TREE_LIST:
        {
  	if (TREE_PURPOSE (rhs) == error_mark_node)
--- 5324,5344 ----
        /* Fall through.  */
  
      case TEMPLATE_ID_EXPR:
!       return 
! 	resolve_address_of_overloaded_function (lhstype,
! 						TREE_OPERAND (rhs, 0),
! 						complain,
! 						/*template_only=*/1,
! 						TREE_OPERAND (rhs, 1));
  
      case OVERLOAD:
!       return 
! 	resolve_address_of_overloaded_function (lhstype, 
! 						rhs,
! 						complain,
! 						/*template_only=*/0,
! 						/*explicit_targs=*/NULL_TREE);
  
      case TREE_LIST:
        {
  	if (TREE_PURPOSE (rhs) == error_mark_node)
*************** instantiate_type (lhstype, rhs, complain
*** 5370,5385 ****
        return rhs;
        
      case ADDR_EXPR:
-       if (TYPE_PTRMEMFUNC_P (lhstype))
- 	lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
-       else if (TREE_CODE (lhstype) != POINTER_TYPE)
- 	{
- 	  if (complain)
- 	    error ("type for resolving address of overloaded function must be pointer type");
- 	  return error_mark_node;
- 	}
        {
! 	tree fn = instantiate_type (TREE_TYPE (lhstype), TREE_OPERAND (rhs, 0), complain);
  	if (fn == error_mark_node)
  	  return error_mark_node;
  	mark_addressable (fn);
--- 5464,5471 ----
        return rhs;
        
      case ADDR_EXPR:
        {
! 	tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
  	if (fn == error_mark_node)
  	  return error_mark_node;
  	mark_addressable (fn);
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.178
diff -c -p -r1.178 cp-tree.h
*** cp-tree.h	1998/12/07 12:27:35	1.178
--- cp-tree.h	1998/12/10 00:09:34
*************** extern int is_specialization_of         
*** 3030,3035 ****
--- 3030,3037 ----
  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 tree most_specialized_instantiation      PROTO((tree, tree));
+ extern void print_candidates                    PROTO((tree));
  
  extern int processing_specialization;
  extern int processing_explicit_instantiation;
Index: cp/cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.45
diff -c -p -r1.45 cvt.c
*** cvt.c	1998/12/07 12:27:36	1.45
--- cvt.c	1998/12/10 00:09:35
*************** convert_to_reference (reftype, expr, con
*** 414,420 ****
  
    if (TREE_CODE (type) == FUNCTION_TYPE && intype == unknown_type_node)
      {
!       expr = instantiate_type (type, expr, 0);
        intype = TREE_TYPE (expr);
      }
  
--- 414,424 ----
  
    if (TREE_CODE (type) == FUNCTION_TYPE && intype == unknown_type_node)
      {
!       expr = instantiate_type (type, expr, 
! 			       (flags & LOOKUP_COMPLAIN) != 0);
!       if (expr == error_mark_node)
! 	return error_mark_node;
! 
        intype = TREE_TYPE (expr);
      }
  
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.243
diff -c -p -r1.243 pt.c
*** pt.c	1998/12/04 11:14:21	1.243
--- pt.c	1998/12/10 00:09:45
*************** static void push_inline_template_parms_r
*** 112,118 ****
  static tree retrieve_specialization PROTO((tree, tree));
  static tree register_specialization PROTO((tree, tree, tree));
  static int unregister_specialization PROTO((tree, tree));
- static void print_candidates PROTO((tree));
  static tree reduce_template_parm_level PROTO((tree, tree, int));
  static tree build_template_decl PROTO((tree, tree));
  static int mark_template_parm PROTO((tree, void *));
--- 112,117 ----
*************** unregister_specialization (spec, tmpl)
*** 883,889 ****
  
  /* Print the list of candidate FNS in an error message.  */
  
! static void
  print_candidates (fns)
       tree fns;
  {
--- 882,888 ----
  
  /* Print the list of candidate FNS in an error message.  */
  
! void
  print_candidates (fns)
       tree fns;
  {
*************** process_partial_specialization (decl)
*** 1996,2002 ****
  		  /* We haven't yet initialized TPD2.  Do so now.  */
  		  tpd2.arg_uses_template_parms 
  		    =  (int*) alloca (sizeof (int) * nargs);
! 		  /* The number of paramters here is the number in the
  		     main template, which, as checked in the assertion
  		     above, is NARGS.  */
  		  tpd2.parms = (int*) alloca (sizeof (int) * nargs);
--- 1995,2001 ----
  		  /* We haven't yet initialized TPD2.  Do so now.  */
  		  tpd2.arg_uses_template_parms 
  		    =  (int*) alloca (sizeof (int) * nargs);
! 		  /* The number of parameters here is the number in the
  		     main template, which, as checked in the assertion
  		     above, is NARGS.  */
  		  tpd2.parms = (int*) alloca (sizeof (int) * nargs);
*************** process_partial_specialization (decl)
*** 2004,2010 ****
  		    TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
  		}
  
! 	      /* Mark the template paramters.  But this time, we're
  		 looking for the template parameters of the main
  		 template, not in the specialization.  */
  	      tpd2.current_arg = i;
--- 2003,2009 ----
  		    TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
  		}
  
! 	      /* Mark the template parameters.  But this time, we're
  		 looking for the template parameters of the main
  		 template, not in the specialization.  */
  	      tpd2.current_arg = i;
*************** process_partial_specialization (decl)
*** 2024,2030 ****
  		    if (tpd2.parms[j] != 0
  			&& tpd.arg_uses_template_parms [j])
  		      {
! 			cp_error ("type `%T' of template argument `%E' depends on template paramter(s)", 
  				  type,
  				  arg);
  			break;
--- 2023,2029 ----
  		    if (tpd2.parms[j] != 0
  			&& tpd.arg_uses_template_parms [j])
  		      {
! 			cp_error ("type `%T' of template argument `%E' depends on template parameter(s)", 
  				  type,
  				  arg);
  			break;
*************** check_default_tmpl_args (decl, parms, is
*** 2106,2112 ****
  
    if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
      /* If we're inside a class definition, there's no need to
!        examine the paramters to the class itself.  On the one
         hand, they will be checked when the class is defined, and,
         on the other, default arguments are legal in things like:
           template <class T = double>
--- 2105,2111 ----
  
    if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
      /* If we're inside a class definition, there's no need to
!        examine the parameters to the class itself.  On the one
         hand, they will be checked when the class is defined, and,
         on the other, default arguments are legal in things like:
           template <class T = double>
*************** get_class_bindings (tparms, parms, args)
*** 8024,8058 ****
    return vec;
  }
  
! /* Return the most specialized of the list of templates in FNS that can
!    produce an instantiation matching DECL, given the explicit template
!    arguments EXPLICIT_ARGS.  */
  
  tree
! most_specialized (fns, decl, explicit_args)
!      tree fns, decl, explicit_args;
  {
!   tree candidates = NULL_TREE;
!   tree fn, champ, args;
    int fate;
- 
-   for (fn = fns; fn; fn = TREE_CHAIN (fn))
-     {
-       tree candidate = TREE_VALUE (fn);
- 
-       args = get_bindings (candidate, decl, explicit_args);
-       if (args)
- 	candidates = scratch_tree_cons (NULL_TREE, candidate, 
- 					candidates);
-     }
  
!   if (!candidates)
      return NULL_TREE;
  
!   champ = TREE_VALUE (candidates);
!   for (fn = TREE_CHAIN (candidates); fn; fn = TREE_CHAIN (fn))
      {
!       fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
        if (fate == 1)
  	;
        else
--- 8023,8052 ----
    return vec;
  }
  
! /* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
!    Pick the most specialized template, and return the corresponding
!    instantiation, or if there is no corresponding instantiation, the
!    template itself.  EXPLICIT_ARGS is any template arguments explicity
!    mentioned in a template-id.  If there is no most specialized
!    tempalte, error_mark_node is returned.  If there are no templates
!    at all, NULL_TREE is returned.  */
  
  tree
! most_specialized_instantiation (instantiations, explicit_args)
!      tree instantiations;
!      tree explicit_args;
  {
!   tree fn, champ;
    int fate;
  
!   if (!instantiations)
      return NULL_TREE;
  
!   champ = instantiations;
!   for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
      {
!       fate = more_specialized (TREE_VALUE (champ), 
! 			       TREE_VALUE (fn), explicit_args);
        if (fate == 1)
  	;
        else
*************** most_specialized (fns, decl, explicit_ar
*** 8063,8080 ****
  	      if (! fn)
  		return error_mark_node;
  	    }
! 	  champ = TREE_VALUE (fn);
  	}
      }
  
!   for (fn = candidates; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn))
      {
!       fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
        if (fate != 1)
  	return error_mark_node;
      }
  
!   return champ;
  }
  
  /* If DECL is a specialization of some template, return the most
--- 8057,8099 ----
  	      if (! fn)
  		return error_mark_node;
  	    }
! 	  champ = fn;
  	}
      }
  
!   for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
      {
!       fate = more_specialized (TREE_VALUE (champ), 
! 			       TREE_VALUE (fn), explicit_args);
        if (fate != 1)
  	return error_mark_node;
      }
+ 
+   return TREE_PURPOSE (champ) ? TREE_PURPOSE (champ) : TREE_VALUE (champ);
+ }
+ 
+ /* Return the most specialized of the list of templates in FNS that can
+    produce an instantiation matching DECL, given the explicit template
+    arguments EXPLICIT_ARGS.  */
+ 
+ tree
+ most_specialized (fns, decl, explicit_args)
+      tree fns, decl, explicit_args;
+ {
+   tree candidates = NULL_TREE;
+   tree fn, args;
+ 
+   for (fn = fns; fn; fn = TREE_CHAIN (fn))
+     {
+       tree candidate = TREE_VALUE (fn);
+ 
+       args = get_bindings (candidate, decl, explicit_args);
+       if (args)
+ 	candidates = scratch_tree_cons (NULL_TREE, candidate, 
+ 					candidates);
+     }
  
!   return most_specialized_instantiation (candidates, explicit_args);
  }
  
  /* If DECL is a specialization of some template, return the most


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