(C++) fix for function conversion overloading

Jason Merrill jason@cygnus.com
Tue Nov 24 02:33:00 GMT 1998


Fixes g++.other/overload7.C.  We were adding multiple candidates for
conversion ops overloaded on `this' quals, and calling it ambiguous.

1998-11-24  Jason Merrill  <jason@yorick.cygnus.com>

	* class.c (add_method): Build up OVERLOADs properly for conversion ops.
	* search.c (lookup_conversions): Handle getting real OVERLOADs.
	(add_conversions): Likewise.  Revert last change.
	* call.c (add_conv_candidate): Pass totype to add_candidate instead
	of fn.  Don't add a new candidate if the last one was for the same 
	type.
	(print_z_candidates): Handle getting a type as a function.
	(joust): If we got two conversion candidates to the same type, 
	just pick one.
	(build_object_call): Lose 'templates'.
	(build_user_type_conversion_1): Handle getting real OVERLOADs

Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.120
diff -c -p -r1.120 call.c
*** call.c	1998/11/18 12:27:21	1.120
--- call.c	1998/11/24 10:30:28
*************** add_function_candidate (candidates, fn, 
*** 1217,1224 ****
  /* Create an overload candidate for the conversion function FN which will
     be invoked for expression OBJ, producing a pointer-to-function which
     will in turn be called with the argument list ARGLIST, and add it to
!    CANDIDATES.  FLAGS is passed on to implicit_conversion.  */
  
  static struct z_candidate *
  add_conv_candidate (candidates, fn, obj, arglist)
       struct z_candidate *candidates;
--- 1217,1230 ----
  /* Create an overload candidate for the conversion function FN which will
     be invoked for expression OBJ, producing a pointer-to-function which
     will in turn be called with the argument list ARGLIST, and add it to
!    CANDIDATES.  FLAGS is passed on to implicit_conversion.
  
+    Actually, we don't really care about FN; we care about the type it
+    converts to.  There may be multiple conversion functions that will
+    convert to that type, and we rely on build_user_type_conversion_1 to
+    choose the best one; so when we create our candidate, we record the type
+    instead of the function.  */
+ 
  static struct z_candidate *
  add_conv_candidate (candidates, fn, obj, arglist)
       struct z_candidate *candidates;
*************** add_conv_candidate (candidates, fn, obj,
*** 1233,1238 ****
--- 1239,1248 ----
    int viable = 1;
    int flags = LOOKUP_NORMAL;
  
+   /* Don't bother looking up the same type twice.  */
+   if (candidates && candidates->fn == totype)
+     return candidates;
+ 
    for (i = 0; i < len; ++i)
      {
        tree arg = i == 0 ? obj : TREE_VALUE (argnode);
*************** add_conv_candidate (candidates, fn, obj,
*** 1277,1283 ****
  	break;
        }
  
!   return add_candidate (candidates, fn, convs, viable);
  }
  
  static struct z_candidate *
--- 1287,1293 ----
  	break;
        }
  
!   return add_candidate (candidates, totype, convs, viable);
  }
  
  static struct z_candidate *
*************** print_z_candidates (candidates)
*** 2058,2063 ****
--- 2068,2075 ----
  	    cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
  		      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
  	}
+       else if (TYPE_P (candidates->fn))
+ 	cp_error ("%s %T <conversion>", str, candidates->fn);
        else
  	cp_error_at ("%s %+D%s", str, candidates->fn,
  		     candidates->viable == -1 ? " <near match>" : "");
*************** build_user_type_conversion_1 (totype, ex
*** 2143,2149 ****
        if (TREE_CODE (totype) == REFERENCE_TYPE)
  	convflags |= LOOKUP_NO_TEMP_BIND;
  
!       if (TREE_CODE (fns) != TEMPLATE_DECL)
  	ics = implicit_conversion
  	  (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
        else
--- 2155,2161 ----
        if (TREE_CODE (totype) == REFERENCE_TYPE)
  	convflags |= LOOKUP_NO_TEMP_BIND;
  
!       if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
  	ics = implicit_conversion
  	  (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
        else
*************** build_object_call (obj, args)
*** 2369,2375 ****
    struct z_candidate *candidates = 0, *cand;
    tree fns, convs, mem_args = NULL_TREE;
    tree type = TREE_TYPE (obj);
-   tree templates = NULL_TREE;
  
    if (TYPE_PTRMEMFUNC_P (type))
      {
--- 2381,2386 ----
*************** build_object_call (obj, args)
*** 2399,2405 ****
  	  tree fn = OVL_CURRENT (fns);
  	  if (TREE_CODE (fn) == TEMPLATE_DECL)
  	    {
- 	      templates = scratch_tree_cons (NULL_TREE, fn, templates);
  	      candidates 
  		= add_template_candidate (candidates, fn, NULL_TREE,
  					  mem_args, NULL_TREE, 
--- 2410,2415 ----
*************** build_object_call (obj, args)
*** 2429,2435 ****
  	    tree fn = OVL_CURRENT (fns);
  	    if (TREE_CODE (fn) == TEMPLATE_DECL) 
  	      {
- 		templates = scratch_tree_cons (NULL_TREE, fn, templates);
  		candidates = add_template_conv_candidate (candidates,
  							  fn,
  							  obj,
--- 2439,2444 ----
*************** joust (cand1, cand2, warn)
*** 4218,4223 ****
--- 4227,4237 ----
      return 1;
    if (cand1->viable < cand2->viable)
      return -1;
+ 
+   /* If we have two pseudo-candidates for conversions to the same type,
+      arbitrarily pick one.  */
+   if (TYPE_P (cand1->fn) && cand1->fn == cand2->fn)
+     return 1;
  
    /* a viable function F1
       is defined to be a better function than another viable function F2  if
Index: class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.113
diff -c -p -r1.113 class.c
*** class.c	1998/11/23 23:59:48	1.113
--- class.c	1998/11/24 10:30:29
*************** add_method (type, fields, method)
*** 1235,1241 ****
  		}
  	    }
  
! 	  if (DECL_CONV_FN_P (method))
  	    {
  	      /* Type conversion operators have to come before
  		 ordinary methods; add_conversions depends on this to
--- 1235,1243 ----
  		}
  	    }
  
! 	  if (TREE_VEC_ELT (method_vec, i))
! 	    /* We found a match.  */;
! 	  else if (DECL_CONV_FN_P (method))
  	    {
  	      /* Type conversion operators have to come before
  		 ordinary methods; add_conversions depends on this to
Index: search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.72
diff -c -p -r1.72 search.c
*** search.c	1998/11/23 03:12:30	1.72
--- search.c	1998/11/24 10:30:30
*************** add_conversions (binfo)
*** 3302,3341 ****
  {
    int i;
    tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
-   tree name = NULL_TREE;
  
    for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
      {
        tree tmp = TREE_VEC_ELT (method_vec, i);
  
        if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
  	break;
  
!       if (TREE_CODE (tmp) == OVERLOAD)
! 	{
! 	  my_friendly_assert (TREE_CHAIN (tmp) == NULL_TREE, 981121);
! 	  tmp = OVL_FUNCTION (tmp);
! 	}
  
-       /* We don't want to mark 'name' until we've seen all the overloads
- 	 in this class; we could be overloading on the quals of 'this'.  */
-       if (name && name != DECL_NAME (tmp))
- 	{
- 	  IDENTIFIER_MARKED (name) = 1;
- 	  name = NULL_TREE;
- 	}
- 
        /* Make sure we don't already have this conversion.  */
!       if (! IDENTIFIER_MARKED (DECL_NAME (tmp)))
  	{
  	  conversions = scratch_tree_cons (binfo, tmp, conversions);
! 	  name = DECL_NAME (tmp);
  	}
      }
- 
-   if (name)
-      IDENTIFIER_MARKED (name) = 1;
- 
    return NULL_TREE;
  }
  
--- 3302,3325 ----
  {
    int i;
    tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
  
    for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
      {
        tree tmp = TREE_VEC_ELT (method_vec, i);
+       tree name;
  
        if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
  	break;
  
!       name = DECL_NAME (OVL_CURRENT (tmp));
  
        /* Make sure we don't already have this conversion.  */
!       if (! IDENTIFIER_MARKED (name))
  	{
  	  conversions = scratch_tree_cons (binfo, tmp, conversions);
! 	  IDENTIFIER_MARKED (name) = 1;
  	}
      }
    return NULL_TREE;
  }
  
*************** lookup_conversions (type)
*** 3351,3357 ****
      breadth_first_search (TYPE_BINFO (type), add_conversions, 0);
  
    for (t = conversions; t; t = TREE_CHAIN (t))
!     IDENTIFIER_MARKED (DECL_NAME (TREE_VALUE (t))) = 0;
  
    return conversions;
  }
--- 3335,3341 ----
      breadth_first_search (TYPE_BINFO (type), add_conversions, 0);
  
    for (t = conversions; t; t = TREE_CHAIN (t))
!     IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
  
    return conversions;
  }



More information about the Gcc-patches mailing list