FreeBSD/contrib/gcc/cp/call.c
/* Determine whether or not the EXPR (of class type S) can be
   converted to T as in [over.match.ref].  */
Determine whether or not the EXPR (of class type S) can be
converted to T as in [over.match.ref].
Determine whether or not the EXPR ( of class type S ) can be converted to T as in [ over . match . ref ] .
static conversion *
convert_class_to_reference (tree t, tree s, tree expr)
{
  tree conversions;
  tree arglist;
  conversion *conv;
  tree reference_type;
  struct z_candidate *candidates;
  struct z_candidate *cand;
  bool any_viable_p;
  conversions = lookup_conversions (s);
  if (!conversions)
    return NULL;
  candidates = 0;
  arglist = build_int_cst (build_pointer_type (s), 0);
  arglist = build_tree_list (NULL_TREE, arglist);
  reference_type = build_reference_type (t);
  while (conversions)
    {
      tree fns = TREE_VALUE (conversions);
      for (; fns; fns = OVL_NEXT (fns))
	{
	  tree f = OVL_CURRENT (fns);
	  tree t2 = TREE_TYPE (TREE_TYPE (f));
	  cand = NULL;
	  if (TREE_CODE (f) == TEMPLATE_DECL)
	    {
	      cand = add_template_candidate (&candidates,
					     f, s,
					     NULL_TREE,
					     arglist,
					     reference_type,
					     TYPE_BINFO (s),
					     TREE_PURPOSE (conversions),
					     LOOKUP_NORMAL,
					     DEDUCE_CONV);
	      if (cand)
		{
		  f = cand->fn;
		  t2 = TREE_TYPE (TREE_TYPE (f));
		  if (TREE_CODE (t2) != REFERENCE_TYPE
		      || !reference_compatible_p (t, TREE_TYPE (t2)))
		    {
		      candidates = candidates->next;
		      cand = NULL;
		    }
		}
	    }
	  else if (TREE_CODE (t2) == REFERENCE_TYPE
		   && reference_compatible_p (t, TREE_TYPE (t2)))
	    cand = add_function_candidate (&candidates, f, s, arglist,
					   TYPE_BINFO (s),
					   TREE_PURPOSE (conversions),
					   LOOKUP_NORMAL);
	  if (cand)
	    {
	      conversion *identity_conv;
	      identity_conv
		= build_identity_conv (TREE_TYPE (TREE_TYPE
						  (TREE_TYPE (cand->fn))),
				       NULL_TREE);
	      cand->second_conv
		= (direct_reference_binding
		   (reference_type, identity_conv));
	      cand->second_conv->bad_p |= cand->convs[0]->bad_p;
	    }
	}
      conversions = TREE_CHAIN (conversions);
    }
  candidates = splice_viable (candidates, pedantic, &any_viable_p);
  if (!any_viable_p)
    return NULL;
  cand = tourney (candidates);
  if (!cand)
    return NULL;
  cand->args = tree_cons (NULL_TREE,
			  build_this (expr),
			  TREE_CHAIN (cand->args));
  conv = build_conv (ck_user,
		     TREE_TYPE (TREE_TYPE (cand->fn)),
		     build_identity_conv (TREE_TYPE (expr), expr));
  conv->cand = cand;
  cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
  if (cand->viable == -1)
    conv->bad_p = true;
  return cand->second_conv;
}
static conversion * convert_class_to_reference ( tree t , tree s , tree expr ) { tree conversions ; tree arglist ; conversion * conv ; tree reference_type ; struct z_candidate * candidates ; struct z_candidate * cand ; bool any_viable_p ; conversions = lookup_conversions ( s ) ; if ( ! conversions ) return NULL ; candidates = 0 ; arglist = build_int_cst ( build_pointer_type ( s ) , 0 ) ; arglist = build_tree_list ( NULL_TREE , arglist ) ; reference_type = build_reference_type ( t ) ; while ( conversions ) { tree fns = TREE_VALUE ( conversions ) ; for ( ; fns ; fns = OVL_NEXT ( fns ) ) { tree f = OVL_CURRENT ( fns ) ; tree t2 = TREE_TYPE ( TREE_TYPE ( f ) ) ; cand = NULL ; if ( TREE_CODE ( f ) == TEMPLATE_DECL ) { cand = add_template_candidate ( & candidates , f , s , NULL_TREE , arglist , reference_type , TYPE_BINFO ( s ) , TREE_PURPOSE ( conversions ) , LOOKUP_NORMAL , DEDUCE_CONV ) ; if ( cand ) { f = cand -> fn ; t2 = TREE_TYPE ( TREE_TYPE ( f ) ) ; if ( TREE_CODE ( t2 ) != REFERENCE_TYPE || ! reference_compatible_p ( t , TREE_TYPE ( t2 ) ) ) { candidates = candidates -> next ; cand = NULL ; } } } else if ( TREE_CODE ( t2 ) == REFERENCE_TYPE && reference_compatible_p ( t , TREE_TYPE ( t2 ) ) ) cand = add_function_candidate ( & candidates , f , s , arglist , TYPE_BINFO ( s ) , TREE_PURPOSE ( conversions ) , LOOKUP_NORMAL ) ; if ( cand ) { conversion * identity_conv ; identity_conv = build_identity_conv ( TREE_TYPE ( TREE_TYPE ( TREE_TYPE ( cand -> fn ) ) ) , NULL_TREE ) ; cand -> second_conv = ( direct_reference_binding ( reference_type , identity_conv ) ) ; cand -> second_conv -> bad_p |= cand -> convs [ 0 ] -> bad_p ; } } conversions = TREE_CHAIN ( conversions ) ; } candidates = splice_viable ( candidates , pedantic , & any_viable_p ) ; if ( ! any_viable_p ) return NULL ; cand = tourney ( candidates ) ; if ( ! cand ) return NULL ; cand -> args = tree_cons ( NULL_TREE , build_this ( expr ) , TREE_CHAIN ( cand -> args ) ) ; conv = build_conv ( ck_user , TREE_TYPE ( TREE_TYPE ( cand -> fn ) ) , build_identity_conv ( TREE_TYPE ( expr ) , expr ) ) ; conv -> cand = cand ; cand -> second_conv = merge_conversion_sequences ( conv , cand -> second_conv ) ; if ( cand -> viable == -1 ) conv -> bad_p = true ; return cand -> second_conv ; }
Determine whether or not the EXPR (of class type S) can be
converted to T as in [over.match.ref].
Determine whether or not the EXPR ( of class type S ) can be converted to T as in [ over . match . ref ] .
/* [over.match.ref]

     Assuming that "cv1 T" is the underlying type of the reference
     being initialized, and "cv S" is the type of the initializer
     expression, with S a class type, the candidate functions are
     selected as follows:

     --The conversion functions of S and its base classes are
       considered.  Those that are not hidden within S and yield type
       "reference to cv2 T2", where "cv1 T" is reference-compatible
       (_dcl.init.ref_) with "cv2 T2", are candidate functions.

     The argument list has one argument, which is the initializer
     expression.  */ /* Conceptually, we should take the address of EXPR and put it in
     the argument list.  Unfortunately, however, that can result in
     error messages, which we should not issue now because we are just
     trying to find a conversion operator.  Therefore, we use NULL,
     cast to the appropriate type.  */ /* If this is a template function, try to get an exact
	     match.  */ /* Now, see if the conversion function really returns
		     an lvalue of the appropriate type.  From the
		     point of view of unification, simply returning an
		     rvalue of the right type is good enough.  */ /* Build a standard conversion sequence indicating the
		 binding from the reference type returned by the
		 function to the desired REFERENCE_TYPE.  */ /* If none of the conversion functions worked out, let our caller
     know.  */ /* Now that we know that this is the function we're going to use fix
     the dummy first argument.  */ /* Build a user-defined conversion sequence representing the
     conversion.  */ /* Merge it with the standard conversion sequence from the
     conversion function's return type to the desired type.  */