FreeBSD/contrib/gcc/cp/class.c
/* 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 & warning messages under
   control of FLAGS.  Permit pointers to member function if FLAGS
   permits.  If TEMPLATE_ONLY, the name of the overloaded function was
   a template-id, and EXPLICIT_TARGS are the explicitly provided
   template arguments.  If OVERLOAD is for one or more member
   functions, then ACCESS_PATH is the base path used to reference
   those member functions.  */
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 & warning messages under
control of FLAGS.  Permit pointers to member function if FLAGS
permits.  If TEMPLATE_ONLY, the name of the overloaded function was
a template-id, and EXPLICIT_TARGS are the explicitly provided
template arguments.  If OVERLOAD is for one or more member
functions, then ACCESS_PATH is the base path used to reference
those member functions.
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 & warning messages under control of FLAGS . Permit pointers to member function if FLAGS permits . If TEMPLATE_ONLY the name of the overloaded function was a template - id and EXPLICIT_TARGS are the explicitly provided template arguments . If OVERLOAD is for one or more member functions then ACCESS_PATH is the base path used to reference those member functions .
static tree
resolve_address_of_overloaded_function (tree target_type,
					tree overload,
					tsubst_flags_t flags,
					bool template_only,
					tree explicit_targs,
					tree access_path)
{
  int is_ptrmem = 0;
  int is_reference = 0;
  tree matches = NULL_TREE;
  tree fn;
  gcc_assert (TREE_CODE (target_type) != POINTER_TYPE
	      || TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE);
  gcc_assert (is_overloaded_fn (overload));
  if (TYPE_PTRFN_P (target_type))
    ;
  else if (TYPE_PTRMEMFUNC_P (target_type))
    is_ptrmem = 1;
  else if (TREE_CODE (target_type) == FUNCTION_TYPE)
    {
      target_type = build_reference_type (target_type);
      is_reference = 1;
    }
  else
    {
      if (flags & tf_error)
	error ("cannot resolve overloaded function %qD based on"
	       " conversion to type %qT",
	       DECL_NAME (OVL_FUNCTION (overload)), target_type);
      return error_mark_node;
    }
  if (!template_only)
    {
      tree fns;
      for (fns = overload; fns; fns = OVL_NEXT (fns))
	{
	  tree fn = OVL_CURRENT (fns);
	  tree fntype;
	  if (TREE_CODE (fn) == TEMPLATE_DECL)
	    continue;
	  if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
	      != is_ptrmem)
	    continue;
	  if (DECL_ANTICIPATED (fn))
	    continue;
	  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, LOOKUP_NORMAL))
	    matches = tree_cons (fn, NULL_TREE, matches);
	}
    }
  if (!matches)
    {
      tree target_fn_type;
      tree target_arg_types;
      tree target_ret_type;
      tree fns;
      if (is_ptrmem)
	target_fn_type
	  = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type));
      else
	target_fn_type = TREE_TYPE (target_type);
      target_arg_types = TYPE_ARG_TYPES (target_fn_type);
      target_ret_type = TREE_TYPE (target_fn_type);
      if (TREE_CODE (target_fn_type) == METHOD_TYPE)
	target_arg_types = TREE_CHAIN (target_arg_types);
      for (fns = overload; fns; fns = OVL_NEXT (fns))
	{
	  tree fn = OVL_CURRENT (fns);
	  tree instantiation;
	  tree instantiation_type;
	  tree targs;
	  if (TREE_CODE (fn) != TEMPLATE_DECL)
	    continue;
	  if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
	      != is_ptrmem)
	    continue;
	  targs = make_tree_vec (DECL_NTPARMS (fn));
	  if (fn_type_unification (fn, explicit_targs, targs,
				   target_arg_types, target_ret_type,
				   DEDUCE_EXACT, LOOKUP_NORMAL))
	    continue;
	  instantiation = instantiate_template (fn, targs, flags);
	  if (instantiation == error_mark_node)
	    continue;
	  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,
			       LOOKUP_NORMAL))
	    matches = tree_cons (instantiation, fn, matches);
	}
      if (matches)
	{
	  tree match = most_specialized_instantiation (matches);
	  if (match != error_mark_node)
	    matches = tree_cons (TREE_PURPOSE (match),
				 NULL_TREE,
				 NULL_TREE);
	}
    }
  if (matches == NULL_TREE)
    {
      if (flags & tf_error)
	{
	  error ("no matches converting function %qD to type %q#T",
		 DECL_NAME (OVL_FUNCTION (overload)),
		 target_type);
	  for (; overload; overload = OVL_NEXT (overload))
	    matches = tree_cons (NULL_TREE, OVL_CURRENT (overload),
				 matches);
	  print_candidates (matches);
	}
      return error_mark_node;
    }
  else if (TREE_CHAIN (matches))
    {
      if (flags & tf_error)
	{
	  tree match;
	  error ("converting overloaded function %qD to type %q#T is ambiguous",
		    DECL_NAME (OVL_FUNCTION (overload)),
		    target_type);
	  for (match = matches; match; match = TREE_CHAIN (match))
	    TREE_VALUE (match) = TREE_PURPOSE (match);
	  print_candidates (matches);
	}
      return error_mark_node;
    }
  fn = TREE_PURPOSE (matches);
  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
      && !(flags & tf_ptrmem_ok) && !flag_ms_extensions)
    {
      static int explained;
      if (!(flags & tf_error))
	return error_mark_node;
      pedwarn ("assuming pointer to member %qD", fn);
      if (!explained)
	{
	  pedwarn ("(a pointer to member can only be formed with %<&%E%>)", fn);
	  explained = 1;
	}
    }
  if (!(flags & tf_conv))
    {
      mark_used (fn);
      if (DECL_FUNCTION_MEMBER_P (fn))
	{
	  gcc_assert (access_path);
	  perform_or_defer_access_check (access_path, fn, fn);
	}
    }
  if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
    return build_unary_op (ADDR_EXPR, fn, 0);
  else
    {
      cxx_mark_addressable (fn);
      return fn;
    }
}
static tree resolve_address_of_overloaded_function ( tree target_type , tree overload , tsubst_flags_t flags , bool template_only , tree explicit_targs , tree access_path ) { int is_ptrmem = 0 ; int is_reference = 0 ; tree matches = NULL_TREE ; tree fn ; gcc_assert ( TREE_CODE ( target_type ) != POINTER_TYPE || TREE_CODE ( TREE_TYPE ( target_type ) ) != METHOD_TYPE ) ; gcc_assert ( is_overloaded_fn ( overload ) ) ; if ( TYPE_PTRFN_P ( target_type ) ) ; else if ( TYPE_PTRMEMFUNC_P ( target_type ) ) is_ptrmem = 1 ; else if ( TREE_CODE ( target_type ) == FUNCTION_TYPE ) { target_type = build_reference_type ( target_type ) ; is_reference = 1 ; } else { if ( flags & tf_error ) error ( " " " " , DECL_NAME ( OVL_FUNCTION ( overload ) ) , target_type ) ; return error_mark_node ; } if ( ! template_only ) { tree fns ; for ( fns = overload ; fns ; fns = OVL_NEXT ( fns ) ) { tree fn = OVL_CURRENT ( fns ) ; tree fntype ; if ( TREE_CODE ( fn ) == TEMPLATE_DECL ) continue ; if ( ( TREE_CODE ( TREE_TYPE ( fn ) ) == METHOD_TYPE ) != is_ptrmem ) continue ; if ( DECL_ANTICIPATED ( fn ) ) continue ; 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 , LOOKUP_NORMAL ) ) matches = tree_cons ( fn , NULL_TREE , matches ) ; } } if ( ! matches ) { tree target_fn_type ; tree target_arg_types ; tree target_ret_type ; tree fns ; if ( is_ptrmem ) target_fn_type = TREE_TYPE ( TYPE_PTRMEMFUNC_FN_TYPE ( target_type ) ) ; else target_fn_type = TREE_TYPE ( target_type ) ; target_arg_types = TYPE_ARG_TYPES ( target_fn_type ) ; target_ret_type = TREE_TYPE ( target_fn_type ) ; if ( TREE_CODE ( target_fn_type ) == METHOD_TYPE ) target_arg_types = TREE_CHAIN ( target_arg_types ) ; for ( fns = overload ; fns ; fns = OVL_NEXT ( fns ) ) { tree fn = OVL_CURRENT ( fns ) ; tree instantiation ; tree instantiation_type ; tree targs ; if ( TREE_CODE ( fn ) != TEMPLATE_DECL ) continue ; if ( ( TREE_CODE ( TREE_TYPE ( fn ) ) == METHOD_TYPE ) != is_ptrmem ) continue ; targs = make_tree_vec ( DECL_NTPARMS ( fn ) ) ; if ( fn_type_unification ( fn , explicit_targs , targs , target_arg_types , target_ret_type , DEDUCE_EXACT , LOOKUP_NORMAL ) ) continue ; instantiation = instantiate_template ( fn , targs , flags ) ; if ( instantiation == error_mark_node ) continue ; 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 , LOOKUP_NORMAL ) ) matches = tree_cons ( instantiation , fn , matches ) ; } if ( matches ) { tree match = most_specialized_instantiation ( matches ) ; if ( match != error_mark_node ) matches = tree_cons ( TREE_PURPOSE ( match ) , NULL_TREE , NULL_TREE ) ; } } if ( matches == NULL_TREE ) { if ( flags & tf_error ) { error ( " " , DECL_NAME ( OVL_FUNCTION ( overload ) ) , target_type ) ; for ( ; overload ; overload = OVL_NEXT ( overload ) ) matches = tree_cons ( NULL_TREE , OVL_CURRENT ( overload ) , matches ) ; print_candidates ( matches ) ; } return error_mark_node ; } else if ( TREE_CHAIN ( matches ) ) { if ( flags & tf_error ) { tree match ; error ( " " , DECL_NAME ( OVL_FUNCTION ( overload ) ) , target_type ) ; for ( match = matches ; match ; match = TREE_CHAIN ( match ) ) TREE_VALUE ( match ) = TREE_PURPOSE ( match ) ; print_candidates ( matches ) ; } return error_mark_node ; } fn = TREE_PURPOSE ( matches ) ; if ( DECL_NONSTATIC_MEMBER_FUNCTION_P ( fn ) && ! ( flags & tf_ptrmem_ok ) && ! flag_ms_extensions ) { static int explained ; if ( ! ( flags & tf_error ) ) return error_mark_node ; pedwarn ( " " , fn ) ; if ( ! explained ) { pedwarn ( " " , fn ) ; explained = 1 ; } } if ( ! ( flags & tf_conv ) ) { mark_used ( fn ) ; if ( DECL_FUNCTION_MEMBER_P ( fn ) ) { gcc_assert ( access_path ) ; perform_or_defer_access_check ( access_path , fn , fn ) ; } } if ( TYPE_PTRFN_P ( target_type ) || TYPE_PTRMEMFUNC_P ( target_type ) ) return build_unary_op ( ADDR_EXPR , fn , 0 ) ; else { cxx_mark_addressable ( fn ) ; return fn ; } }
Given an OVERLOAD and a TARGET_TYPE, return the function that
matches the TARGET_TYPE.
Given an OVERLOAD and a TARGET_TYPE return the function that matches the TARGET_TYPE .
/* 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.  */ /* 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.  */ /* By the time we get here, we should be seeing only real
     pointer-to-member types, not the internal POINTER_TYPE to
     METHOD_TYPE representation.  */ /* Check that the TARGET_TYPE is reasonable.  */ /* This is OK.  */ /* This is OK, too.  */ /* This is OK, too.  This comes from a conversion to reference
	 type.  */ /* 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.  */ /* We're not looking for templates just yet.  */ /* We're looking for a non-static member, and this isn't
	       one, or vice versa.  */ /* Ignore functions which haven't been explicitly
	     declared.  */ /* See if there's a match.  */ /* 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.  */ /* Never do unification on the 'this' parameter.  */ /* We're only looking for templates.  */ /* We're not looking for a non-static member, and this is
	       one, or vice versa.  */ /* Try to do argument deduction.  */ /* Argument deduction failed.  */ /* Instantiate the template.  */ /* Instantiation failed.  */ /* See if there's a match.  */ /* Now, remove all but the most specialized of the matches.  */ /* Now we should have exactly one function in MATCHES.  */ /* There were *no* matches.  */ /* print_candidates expects a chain with the functions in
	     TREE_VALUE slots, so we cons one up here (we're losing anyway,
	     so why be clever?).  */ /* There were too many matches.  */ /* Since print_candidates expects the functions in the
	     TREE_VALUE slot, we flip them here.  */ /* Good, exactly one match.  Now, convert it to the correct type.  */ /* If we're doing overload resolution purely for the purpose of
     determining conversion sequences, we should not consider the
     function used.  If this conversion sequence is selected, the
     function will be marked as used at this point.  */ /* We could not check access when this expression was originally
	 created since we did not know at that time to which function
	 the expression referred.  */ /* The target must be a REFERENCE_TYPE.  Above, build_unary_op
	 will mark the function as addressed, but here we must do it
	 explicitly.  */