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]
Other format: [Raw text]

C++ PATCH: Reorganize function-call machinery


This patch (in preparation for the new parser) moves name lookup
towards the parser (where it should be) when processing function call
expressions.  There is now a reasonably clear separation between the
routines that process parse-tree nodes (SCOPE_REF, IDENTIFIER_NODE)
and those that process expression nodes (VAR_DECL, FUNCTION_DECL,
OVERLOAD).

There is more that can be done in this direction, but this is a good
first step.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2002-07-31  Mark Mitchell  <mark@codesourcery.com>

	* call.c (build_field_call): Do not look up the field by name.
	(build_method_call): Simplify.
	(struct z_candidate): Add access_path and conversion_path.  Remove
	basetype_path.
	(convert_class_to_reference): Adjust use of
	add_function_candidate.
	(add_candidate): Add conversion_path argument.
	(add_function_candidate): Use it.
	(add_conv_dndidate): Likewise.
	(build_builtin_candidate): Likewise.
	(add_template_candidate_real): Add conversion_path argument.
	(add_template_conv_candidate): Likewise.
	(add_template_candidate): Likewise.
	(build_user_type_conversion_1): Use it.
	(build_new_function_call): Remove name lookup code.  Adjust use of
	add_template_candidate and add_function_candidate.
	(build_new_op): Likewise.
	(convert_like_real): Use build_special_member_call.
	(build_over_call): Use cand->conversion_path.
	(build_special_member_call): New method.
	(build_new_method_call): Remove name lookup code.
	* cp-tree.def (OFFSET_REF): Update documentation.
	(TEMPLATE_ID_EXPR): Likewise.
	* cp-tree.h (BASELINK_ACCESS_BINFO): New macro.
	(BASELINK_OPTYPE): Likewise.
	(build_new_method_call): Adjust prototype.
	(build_special_member_call): New method.
	(build_baselink): New method.
	(build_offset_ref_call_from_tree): Likewise.
	(build_call_from_tree): Likewise.
	(finish_qualified_call_expr): Remove.
	(finish_call_expr): Adjust prototype.
	(build_x_function_call): Remove.
	* cvt.c (ocp_convert): Use build_special_member_call.
	* decl2.c (reparse_absdcl_as_expr): Use finish_call_expr.
	(build_expr_from_tree): Adjust handling for TEMPLATE_ID_EXPR and
	CALL_EXPR.
	(build_offset_ref_call_from_tree): New function.
	(build_call_from_tree): Likewise.
	* init.c (expand_cleanup): Use build_special_member_call.
	(expand_default_init): Likewise.
	(build_member_call): Use finish_call_expr.
	(build_new_1): Use build_special_member_call.
	(push_base_cleanups): Likewise.
	* method.c (do_build_assign_ref): Likewise.
	* parse.y (template_id): Do not pass a COMPONENT_REF to
	lookup_template_function.
	(primary): Use parse_finish_call_epxr, not finish_call_expr.
	(parse_finish_call_expr): New function.
	* pt.c (lookup_template_function): Add assertions.
	* search.c (lookup_base): Allow T to be a binfo.
	(build_baselink): New function.
	(lookup_member): Use it.
	* semantics.c (finish_call_expr): Do not do name lookup.
	(finish_object_call_expr): Remove #if 0'd code.
	(finish_qualified_call_expr): Remove.
	* typeck.c (build_x_function_call): Remove.
	(build_static_case): Use build_special_member_call.
	* typeck2.c (build_functional_cast): Likewise.

2002-07-31  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/inherit/operator1.C: New test.
	* g++.dg/lookup/disamb1.C: Fix typo in comment.
	* g++.dg/other/error1.C: Change expected error message.
	* g++.dg/template/conv4.C: Likewise.
	
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.323
diff -c -p -r1.323 call.c
*** cp/call.c	26 Jul 2002 20:10:40 -0000	1.323
--- cp/call.c	1 Aug 2002 04:43:45 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 38,46 ****
  
  extern int inhibit_warnings;
  
! static tree build_new_method_call PARAMS ((tree, tree, tree, tree, int));
! 
! static tree build_field_call PARAMS ((tree, tree, tree, tree));
  static struct z_candidate * tourney PARAMS ((struct z_candidate *));
  static int equal_functions PARAMS ((tree, tree));
  static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
--- 38,44 ----
  
  extern int inhibit_warnings;
  
! static tree build_field_call PARAMS ((tree, tree, tree));
  static struct z_candidate * tourney PARAMS ((struct z_candidate *));
  static int equal_functions PARAMS ((tree, tree));
  static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
*************** static struct z_candidate * splice_viabl
*** 64,76 ****
  static int any_viable PARAMS ((struct z_candidate *));
  static int any_strictly_viable PARAMS ((struct z_candidate *));
  static struct z_candidate * add_template_candidate
! 	PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
! 	       unification_kind_t));
  static struct z_candidate * add_template_candidate_real
! 	PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
! 	       tree, unification_kind_t));
  static struct z_candidate * add_template_conv_candidate 
!         PARAMS ((struct z_candidate *, tree, tree, tree, tree));
  static struct z_candidate * add_builtin_candidates
  	PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
  	       tree, tree *, int));
--- 62,74 ----
  static int any_viable PARAMS ((struct z_candidate *));
  static int any_strictly_viable PARAMS ((struct z_candidate *));
  static struct z_candidate * add_template_candidate
! 	PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, 
! 		 tree, tree, int, unification_kind_t));
  static struct z_candidate * add_template_candidate_real
! 	PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, 
! 		 tree, tree, int, tree, unification_kind_t));
  static struct z_candidate * add_template_conv_candidate 
!         PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, tree));
  static struct z_candidate * add_builtin_candidates
  	PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
  	       tree, tree *, int));
*************** static struct z_candidate * build_builti
*** 82,90 ****
  	PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *,
  	       int));
  static struct z_candidate * add_conv_candidate 
! 	PARAMS ((struct z_candidate *, tree, tree, tree));
  static struct z_candidate * add_function_candidate 
! 	PARAMS ((struct z_candidate *, tree, tree, tree, int));
  static tree implicit_conversion PARAMS ((tree, tree, tree, int));
  static tree standard_conversion PARAMS ((tree, tree, tree));
  static tree reference_binding PARAMS ((tree, tree, tree, int));
--- 80,88 ----
  	PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *,
  	       int));
  static struct z_candidate * add_conv_candidate 
! 	PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree));
  static struct z_candidate * add_function_candidate 
! 	(struct z_candidate *, tree, tree, tree, tree, tree, int);
  static tree implicit_conversion PARAMS ((tree, tree, tree, int));
  static tree standard_conversion PARAMS ((tree, tree, tree));
  static tree reference_binding PARAMS ((tree, tree, tree, int));
*************** static tree build_conv PARAMS ((enum tre
*** 93,100 ****
  static int is_subseq PARAMS ((tree, tree));
  static tree maybe_handle_ref_bind PARAMS ((tree*));
  static void maybe_handle_implicit_object PARAMS ((tree*));
! static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
! 						   tree, tree, int));
  static tree source_type PARAMS ((tree));
  static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
  static int reference_related_p PARAMS ((tree, tree));
--- 91,98 ----
  static int is_subseq PARAMS ((tree, tree));
  static tree maybe_handle_ref_bind PARAMS ((tree*));
  static void maybe_handle_implicit_object PARAMS ((tree*));
! static struct z_candidate *add_candidate 
!         (struct z_candidate *, tree, tree, tree, tree, int);
  static tree source_type PARAMS ((tree));
  static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
  static int reference_related_p PARAMS ((tree, tree));
*************** build_vfield_ref (datum, type)
*** 129,158 ****
     operator ()(), or is a pointer-to-function or pointer-to-method.  */
  
  static tree
! build_field_call (basetype_path, instance_ptr, name, parms)
!      tree basetype_path, instance_ptr, name, parms;
  {
!   tree field, instance;
! 
!   if (IDENTIFIER_CTOR_OR_DTOR_P (name))
!     return NULL_TREE;
  
!   /* Speed up the common case.  */
!   if (instance_ptr == current_class_ptr
!       && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE)
!     return NULL_TREE;
! 
!   field = lookup_field (basetype_path, name, 1, 0);
  
!   if (field == error_mark_node || field == NULL_TREE)
!     return field;
! 
!   if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL)
      {
        /* If it's a field, try overloading operator (),
  	 or calling if the field is a pointer-to-function.  */
        instance = build_indirect_ref (instance_ptr, NULL);
!       instance = build_component_ref_1 (instance, field, 0);
  
        if (instance == error_mark_node)
  	return error_mark_node;
--- 127,145 ----
     operator ()(), or is a pointer-to-function or pointer-to-method.  */
  
  static tree
! build_field_call (tree instance_ptr, tree decl, tree parms)
  {
!   tree instance;
  
!   if (decl == error_mark_node || decl == NULL_TREE)
!     return decl;
  
!   if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL)
      {
        /* If it's a field, try overloading operator (),
  	 or calling if the field is a pointer-to-function.  */
        instance = build_indirect_ref (instance_ptr, NULL);
!       instance = build_component_ref_1 (instance, decl, 0);
  
        if (instance == error_mark_node)
  	return error_mark_node;
*************** build_method_call (instance, name, parms
*** 476,482 ****
       tree instance, name, parms, basetype_path;
       int flags;
  {
!   tree basetype, instance_ptr;
  
  #ifdef GATHER_STATISTICS
    n_build_method_call++;
--- 463,472 ----
       tree instance, name, parms, basetype_path;
       int flags;
  {
!   tree fn;
!   tree object_type;
!   tree template_args = NULL_TREE;
!   bool has_template_args = false;
  
  #ifdef GATHER_STATISTICS
    n_build_method_call++;
*************** build_method_call (instance, name, parms
*** 485,491 ****
    if (instance == error_mark_node
        || name == error_mark_node
        || parms == error_mark_node
!       || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
      return error_mark_node;
  
    if (processing_template_decl)
--- 475,481 ----
    if (instance == error_mark_node
        || name == error_mark_node
        || parms == error_mark_node
!       || (instance && TREE_TYPE (instance) == error_mark_node))
      return error_mark_node;
  
    if (processing_template_decl)
*************** build_method_call (instance, name, parms
*** 508,546 ****
        return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
      }
  
    if (TREE_CODE (name) == BIT_NOT_EXPR)
      {
        if (parms)
  	error ("destructors take no parameters");
-       basetype = TREE_TYPE (instance);
-       if (TREE_CODE (basetype) == REFERENCE_TYPE)
- 	basetype = TREE_TYPE (basetype);
  
!       if (! check_dtor_name (basetype, name))
  	error
  	  ("destructor name `~%T' does not match type `%T' of expression",
! 	   TREE_OPERAND (name, 0), basetype);
  
!       if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
  	return cp_convert (void_type_node, instance);
        instance = default_conversion (instance);
        instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
!       return build_delete (build_pointer_type (basetype),
  			   instance_ptr, sfk_complete_destructor,
  			   LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
      }
  
!   return build_new_method_call (instance, name, parms, basetype_path, flags);
  }
  
  /* New overloading code.  */
  
  struct z_candidate GTY(()) {
    tree fn;
    tree convs;
    tree second_conv;
    int viable;
!   tree basetype_path;
    tree template;
    tree warnings;
    struct z_candidate *next;
--- 498,595 ----
        return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
      }
  
+   if (TREE_CODE (instance) == OFFSET_REF)
+     instance = resolve_offset_ref (instance);
+   if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
+     instance = convert_from_reference (instance);
+   object_type = TREE_TYPE (instance);
+ 
    if (TREE_CODE (name) == BIT_NOT_EXPR)
      {
+       tree instance_ptr;
+ 
        if (parms)
  	error ("destructors take no parameters");
  
!       if (! check_dtor_name (object_type, name))
  	error
  	  ("destructor name `~%T' does not match type `%T' of expression",
! 	   TREE_OPERAND (name, 0), object_type);
  
!       if (! TYPE_HAS_DESTRUCTOR (complete_type (object_type)))
  	return cp_convert (void_type_node, instance);
        instance = default_conversion (instance);
        instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
!       return build_delete (build_pointer_type (object_type),
  			   instance_ptr, sfk_complete_destructor,
  			   LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
      }
  
!   if (!CLASS_TYPE_P (object_type))
!     {
!       if ((flags & LOOKUP_COMPLAIN) 
! 	  && TREE_TYPE (instance) != error_mark_node)
! 	error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
! 	       name, instance, object_type);
!       return error_mark_node;
!     }
! 
!   if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
!     {
!       template_args = TREE_OPERAND (name, 1);
!       has_template_args = true;
!       name = TREE_OPERAND (name, 0);
!     }
!   if (TREE_CODE (name) == OVERLOAD)
!     name = DECL_NAME (get_first_fn (name));
!   else if (DECL_P (name))
!     name = DECL_NAME (name);
!   if (has_template_args)
!     fn = lookup_fnfields (object_type, name, /*protect=*/0);
!   else
!     fn = lookup_member (object_type, name, /*protect=*/0, 
! 			/*want_type=*/0);
!   
!   /* If the name could not be found, issue an error.  */
!   if (!fn)
!     {
!       unqualified_name_lookup_error (name);
!       return error_mark_node;
!     }
! 
!   if (BASELINK_P (fn) && has_template_args)
!     BASELINK_FUNCTIONS (fn)
!       = build_nt (TEMPLATE_ID_EXPR,
! 		  BASELINK_FUNCTIONS (fn),
! 		  template_args);
!   if (BASELINK_P (fn) && basetype_path)
!     BASELINK_ACCESS_BINFO (fn) = basetype_path;
! 
!   return build_new_method_call (instance, fn, parms, 
! 				/*conversion_path=*/NULL_TREE, flags);
  }
  
  /* New overloading code.  */
  
  struct z_candidate GTY(()) {
+   /* The FUNCTION_DECL that will be called if this candidate is
+      selected by overload resolution.  */
    tree fn;
    tree convs;
    tree second_conv;
    int viable;
!   /* If FN is a member function, the binfo indicating the path used to
!      qualify the name of FN at the call site.  This path is used to
!      determine whether or not FN is accessible if it is selected by
!      overload resolution.  The DECL_CONTEXT of FN will always be a
!      (possibly improper) base of this binfo.  */
!   tree access_path;
!   /* If FN is a non-static member function, the binfo indicating the
!      subobject to which the `this' pointer should be converted if FN
!      is selected by overload resolution.  The type pointed to the by
!      the `this' pointer must correspond to the most derived class
!      indicated by the CONVERSION_PATH.  */
!   tree conversion_path;
    tree template;
    tree warnings;
    struct z_candidate *next;
*************** convert_class_to_reference (t, s, expr)
*** 981,986 ****
--- 1030,1037 ----
  					  NULL_TREE,
  					  arglist,
  					  build_reference_type (t),
+ 					  TYPE_BINFO (s),
+ 					  TREE_PURPOSE (conversions),
  					  LOOKUP_NORMAL,
  					  DEDUCE_CONV);
  	      
*************** convert_class_to_reference (t, s, expr)
*** 1001,1010 ****
  		   && reference_compatible_p (t, TREE_TYPE (t2)))
  	    candidates 
  	      = add_function_candidate (candidates, f, s, arglist, 
  					LOOKUP_NORMAL);
- 
- 	  if (candidates != old_candidates)
- 	    candidates->basetype_path = TYPE_BINFO (s);
  	}
      }
  
--- 1052,1060 ----
  		   && reference_compatible_p (t, TREE_TYPE (t2)))
  	    candidates 
  	      = add_function_candidate (candidates, f, s, arglist, 
+ 					TYPE_BINFO (s), 	
+ 					TREE_PURPOSE (conversions),
  					LOOKUP_NORMAL);
  	}
      }
  
*************** implicit_conversion (to, from, expr, fla
*** 1282,1297 ****
     functions.  */
  
  static struct z_candidate *
! add_candidate (candidates, fn, convs, viable)
!      struct z_candidate *candidates;
!      tree fn, convs;
!      int viable;
  {
    struct z_candidate *cand
      = (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
  
    cand->fn = fn;
    cand->convs = convs;
    cand->viable = viable;
    cand->next = candidates;
  
--- 1332,1348 ----
     functions.  */
  
  static struct z_candidate *
! add_candidate (struct z_candidate *candidates, 
! 	       tree fn, tree convs, tree access_path, tree
! 	       conversion_path, int viable)
  {
    struct z_candidate *cand
      = (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
  
    cand->fn = fn;
    cand->convs = convs;
+   cand->access_path = access_path;
+   cand->conversion_path = conversion_path;
    cand->viable = viable;
    cand->next = candidates;
  
*************** add_candidate (candidates, fn, convs, vi
*** 1306,1315 ****
     comes from for purposes of overload resolution.  */
  
  static struct z_candidate *
! add_function_candidate (candidates, fn, ctype, arglist, flags)
!      struct z_candidate *candidates;
!      tree fn, ctype, arglist;
!      int flags;
  {
    tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
    int i, len;
--- 1357,1366 ----
     comes from for purposes of overload resolution.  */
  
  static struct z_candidate *
! add_function_candidate (struct z_candidate *candidates, 
! 			tree fn, tree ctype, tree arglist, 
! 			tree access_path, tree conversion_path,
! 			int flags)
  {
    tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
    int i, len;
*************** add_function_candidate (candidates, fn, 
*** 1421,1427 ****
      }
  
   out:
!   return add_candidate (candidates, fn, convs, viable);
  }
  
  /* Create an overload candidate for the conversion function FN which will
--- 1472,1479 ----
      }
  
   out:
!   return add_candidate (candidates, fn, convs, access_path,
! 			conversion_path, viable);
  }
  
  /* Create an overload candidate for the conversion function FN which will
*************** add_function_candidate (candidates, fn, 
*** 1436,1444 ****
     instead of the function.  */
  
  static struct z_candidate *
! add_conv_candidate (candidates, fn, obj, arglist)
       struct z_candidate *candidates;
       tree fn, obj, arglist;
  {
    tree totype = TREE_TYPE (TREE_TYPE (fn));
    int i, len, viable, flags;
--- 1488,1499 ----
     instead of the function.  */
  
  static struct z_candidate *
! add_conv_candidate (candidates, fn, obj, arglist, access_path,
! 		    conversion_path)
       struct z_candidate *candidates;
       tree fn, obj, arglist;
+      tree access_path;
+      tree conversion_path;
  {
    tree totype = TREE_TYPE (TREE_TYPE (fn));
    int i, len, viable, flags;
*************** add_conv_candidate (candidates, fn, obj,
*** 1498,1504 ****
    if (!sufficient_parms_p (parmnode))
      viable = 0;
  
!   return add_candidate (candidates, totype, convs, viable);
  }
  
  static struct z_candidate *
--- 1553,1560 ----
    if (!sufficient_parms_p (parmnode))
      viable = 0;
  
!   return add_candidate (candidates, totype, convs, access_path,
! 			conversion_path, viable);
  }
  
  static struct z_candidate *
*************** build_builtin_candidate (candidates, fnn
*** 1547,1553 ****
  	viable = 0;
      }      
  
!   return add_candidate (candidates, fnname, convs, viable);
  }
  
  static int
--- 1603,1612 ----
  	viable = 0;
      }      
  
!   return add_candidate (candidates, fnname, convs, 
! 			/*access_path=*/NULL_TREE,
! 			/*conversion_path=*/NULL_TREE,
! 			viable);
  }
  
  static int
*************** add_builtin_candidates (candidates, code
*** 2185,2194 ****
  
  static struct z_candidate*
  add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
! 			     arglist, return_type, flags,
! 			     obj, strict)
       struct z_candidate *candidates;
       tree tmpl, ctype, explicit_targs, arglist, return_type;
       int flags;
       tree obj;
       unification_kind_t strict;
--- 2244,2255 ----
  
  static struct z_candidate*
  add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
! 			     arglist, return_type, access_path,
! 			     conversion_path, flags, obj, strict)
       struct z_candidate *candidates;
       tree tmpl, ctype, explicit_targs, arglist, return_type;
+      tree access_path;
+      tree conversion_path;
       int flags;
       tree obj;
       unification_kind_t strict;
*************** add_template_candidate_real (candidates,
*** 2253,2262 ****
  
    if (obj != NULL_TREE)
      /* Aha, this is a conversion function.  */
!     cand = add_conv_candidate (candidates, fn, obj, arglist);
    else
      cand = add_function_candidate (candidates, fn, ctype,
! 				   arglist, flags);
    if (DECL_TI_TEMPLATE (fn) != tmpl)
      /* This situation can occur if a member template of a template
         class is specialized.  Then, instantiate_template might return
--- 2314,2325 ----
  
    if (obj != NULL_TREE)
      /* Aha, this is a conversion function.  */
!     cand = add_conv_candidate (candidates, fn, obj, access_path,
! 			       conversion_path, arglist);
    else
      cand = add_function_candidate (candidates, fn, ctype,
! 				   arglist, access_path, 
! 				   conversion_path, flags);
    if (DECL_TI_TEMPLATE (fn) != tmpl)
      /* This situation can occur if a member template of a template
         class is specialized.  Then, instantiate_template might return
*************** add_template_candidate_real (candidates,
*** 2285,2311 ****
  
  static struct z_candidate *
  add_template_candidate (candidates, tmpl, ctype, explicit_targs, 
! 			arglist, return_type, flags, strict)
       struct z_candidate *candidates;
       tree tmpl, ctype, explicit_targs, arglist, return_type;
       int flags;
       unification_kind_t strict;
  {
    return 
      add_template_candidate_real (candidates, tmpl, ctype,
! 				 explicit_targs, arglist, return_type, flags,
! 				 NULL_TREE, strict);
  }
  
  
  static struct z_candidate *
! add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
       struct z_candidate *candidates;
       tree tmpl, obj, arglist, return_type;
  {
    return 
      add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
! 				 arglist, return_type, 0, obj, DEDUCE_CONV);
  }
  
  
--- 2348,2382 ----
  
  static struct z_candidate *
  add_template_candidate (candidates, tmpl, ctype, explicit_targs, 
! 			arglist, return_type, access_path, 
! 			conversion_path, flags, strict)
       struct z_candidate *candidates;
       tree tmpl, ctype, explicit_targs, arglist, return_type;
+      tree access_path;
+      tree conversion_path;
       int flags;
       unification_kind_t strict;
  {
    return 
      add_template_candidate_real (candidates, tmpl, ctype,
! 				 explicit_targs, arglist, return_type, 
! 				 access_path, conversion_path,
! 				 flags, NULL_TREE, strict);
  }
  
  
  static struct z_candidate *
! add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type,
! 			     access_path, conversion_path)
       struct z_candidate *candidates;
       tree tmpl, obj, arglist, return_type;
+      tree access_path;
+      tree conversion_path;
  {
    return 
      add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
! 				 arglist, return_type, access_path,
! 				 conversion_path, 0, obj, DEDUCE_CONV);
  }
  
  
*************** build_user_type_conversion_1 (totype, ex
*** 2446,2463 ****
  	  templates = tree_cons (NULL_TREE, ctor, templates);
  	  candidates = 
  	    add_template_candidate (candidates, ctor, totype,
! 				    NULL_TREE, args, NULL_TREE, flags,
  				    DEDUCE_CALL);
! 	} 
        else 
  	candidates = add_function_candidate (candidates, ctor, totype,
! 					     args, flags); 
  
        if (candidates) 
! 	{
! 	  candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
! 	  candidates->basetype_path = TYPE_BINFO (totype);
! 	} 
      }
  
    if (convs)
--- 2517,2536 ----
  	  templates = tree_cons (NULL_TREE, ctor, templates);
  	  candidates = 
  	    add_template_candidate (candidates, ctor, totype,
! 				    NULL_TREE, args, NULL_TREE, 
! 				    TYPE_BINFO (totype),
! 				    TYPE_BINFO (totype),
! 				    flags,
  				    DEDUCE_CALL);
! 	}
        else 
  	candidates = add_function_candidate (candidates, ctor, totype,
! 					     args, TYPE_BINFO (totype), 
! 					     TYPE_BINFO (totype),
! 					     flags); 
  
        if (candidates) 
! 	candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
      }
  
    if (convs)
*************** build_user_type_conversion_1 (totype, ex
*** 2465,2471 ****
  
    for (; convs; convs = TREE_CHAIN (convs))
      {
!       tree fns = TREE_VALUE (convs);
        int convflags = LOOKUP_NO_CONVERSION;
  
        /* If we are called to convert to a reference type, we are trying to
--- 2538,2545 ----
  
    for (; convs; convs = TREE_CHAIN (convs))
      {
!       tree fns;
!       tree conversion_path = TREE_PURPOSE (convs);
        int convflags = LOOKUP_NO_CONVERSION;
  
        /* If we are called to convert to a reference type, we are trying to
*************** build_user_type_conversion_1 (totype, ex
*** 2475,2481 ****
        if (TREE_CODE (totype) == REFERENCE_TYPE)
  	convflags |= LOOKUP_NO_TEMP_BIND;
        
!       for (; fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  struct z_candidate *old_candidates = candidates;
--- 2549,2555 ----
        if (TREE_CODE (totype) == REFERENCE_TYPE)
  	convflags |= LOOKUP_NO_TEMP_BIND;
        
!       for (fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  struct z_candidate *old_candidates = candidates;
*************** build_user_type_conversion_1 (totype, ex
*** 2492,2503 ****
  	      templates = tree_cons (NULL_TREE, fn, templates);
  	      candidates = 
  		add_template_candidate (candidates, fn, fromtype, NULL_TREE,
! 					args, totype, flags,
  					DEDUCE_CONV);
  	    } 
  	  else 
  	    candidates = add_function_candidate (candidates, fn, fromtype,
! 						 args, flags); 
  
  	  if (candidates != old_candidates)
  	    {
--- 2566,2582 ----
  	      templates = tree_cons (NULL_TREE, fn, templates);
  	      candidates = 
  		add_template_candidate (candidates, fn, fromtype, NULL_TREE,
! 					args, totype, TYPE_BINFO (fromtype), 
! 					conversion_path,
! 					flags,
  					DEDUCE_CONV);
  	    } 
  	  else 
  	    candidates = add_function_candidate (candidates, fn, fromtype,
! 						 args,
! 						 TYPE_BINFO (fromtype),
! 						 conversion_path,
! 						 flags); 
  
  	  if (candidates != old_candidates)
  	    {
*************** build_user_type_conversion_1 (totype, ex
*** 2506,2512 ****
  		 0, convflags);
  
  	      candidates->second_conv = ics;
- 	      candidates->basetype_path = TYPE_BINFO (fromtype);
  	      
  	      if (ics == NULL_TREE)
  		candidates->viable = 0;
--- 2585,2590 ----
*************** build_user_type_conversion_1 (totype, ex
*** 2517,2535 ****
      }
  
    if (! any_viable (candidates))
!     {
! #if 0
!       if (flags & LOOKUP_COMPLAIN)
! 	{
! 	  if (candidates && ! candidates->next)
! 	    /* say why this one won't work or try to be loose */;
! 	  else
! 	    error ("no viable candidates");
! 	}
! #endif
! 
!       return 0;
!     }
  
    candidates = splice_viable (candidates);
    cand = tourney (candidates);
--- 2595,2601 ----
      }
  
    if (! any_viable (candidates))
!     return 0;
  
    candidates = splice_viable (candidates);
    cand = tourney (candidates);
*************** resolve_args (args)
*** 2609,2614 ****
--- 2675,2683 ----
      }
    return args;
  }
+ 
+ /* Return an expression for a call to FN (a namespace-scope function)
+    with the ARGS.  */
        
  tree
  build_new_function_call (fn, args)
*************** build_new_function_call (fn, args)
*** 2618,2623 ****
--- 2687,2701 ----
    tree explicit_targs = NULL_TREE;
    int template_only = 0;
  
+   /* Check FN and ARGS.  */
+   my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL 
+ 		      || TREE_CODE (fn) == TEMPLATE_DECL
+ 		      || TREE_CODE (fn) == OVERLOAD
+ 		      || TREE_CODE (fn) == TEMPLATE_ID_EXPR,
+ 		      20020712);
+   my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
+ 		      20020712);
+ 
    if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
      {
        explicit_targs = TREE_OPERAND (fn, 1);
*************** build_new_function_call (fn, args)
*** 2625,2631 ****
        template_only = 1;
      }
  
!   if (really_overloaded_fn (fn))
      {
        tree t1;
        tree templates = NULL_TREE;
--- 2703,2710 ----
        template_only = 1;
      }
  
!   if (really_overloaded_fn (fn) 
!       || TREE_CODE (fn) == TEMPLATE_DECL)
      {
        tree t1;
        tree templates = NULL_TREE;
*************** build_new_function_call (fn, args)
*** 2635,2654 ****
        if (args == error_mark_node)
  	return error_mark_node;
  
!       for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
  	{
! 	  tree t = OVL_FUNCTION (t1);
  
  	  if (TREE_CODE (t) == TEMPLATE_DECL)
  	    {
  	      templates = tree_cons (NULL_TREE, t, templates);
  	      candidates = add_template_candidate
! 		(candidates, t, NULL_TREE, explicit_targs, args, NULL_TREE,
  		 LOOKUP_NORMAL, DEDUCE_CALL);  
  	    }
  	  else if (! template_only)
  	    candidates = add_function_candidate
! 	      (candidates, t, NULL_TREE, args, LOOKUP_NORMAL);
  	}
  
        if (! any_viable (candidates))
--- 2714,2736 ----
        if (args == error_mark_node)
  	return error_mark_node;
  
!       for (t1 = fn; t1; t1 = OVL_NEXT (t1))
  	{
! 	  tree t = OVL_CURRENT (t1);
  
  	  if (TREE_CODE (t) == TEMPLATE_DECL)
  	    {
  	      templates = tree_cons (NULL_TREE, t, templates);
  	      candidates = add_template_candidate
! 		(candidates, t, NULL_TREE, explicit_targs, args, 
! 		 NULL_TREE,
! 		 /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
  		 LOOKUP_NORMAL, DEDUCE_CALL);  
  	    }
  	  else if (! template_only)
  	    candidates = add_function_candidate
! 	      (candidates, t, NULL_TREE, args, /*access_path=*/NULL_TREE, 
! 	       /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
  	}
  
        if (! any_viable (candidates))
*************** build_new_function_call (fn, args)
*** 2656,2662 ****
  	  if (candidates && ! candidates->next)
  	    return build_function_call (candidates->fn, args);
  	  error ("no matching function for call to `%D(%A)'",
! 		    DECL_NAME (OVL_FUNCTION (fn)), args);
  	  if (candidates)
  	    print_z_candidates (candidates);
  	  return error_mark_node;
--- 2738,2744 ----
  	  if (candidates && ! candidates->next)
  	    return build_function_call (candidates->fn, args);
  	  error ("no matching function for call to `%D(%A)'",
! 		    DECL_NAME (OVL_CURRENT (fn)), args);
  	  if (candidates)
  	    print_z_candidates (candidates);
  	  return error_mark_node;
*************** build_object_call (obj, args)
*** 2719,2732 ****
  	      candidates 
  		= add_template_candidate (candidates, fn, base, NULL_TREE,
  					  mem_args, NULL_TREE, 
  					  LOOKUP_NORMAL, DEDUCE_CALL);
  	    }
  	  else
  	    candidates = add_function_candidate
! 	      (candidates, fn, base, mem_args, LOOKUP_NORMAL);
! 
! 	  if (candidates)
! 	    candidates->basetype_path = TYPE_BINFO (type);
  	}
      }
  
--- 2801,2814 ----
  	      candidates 
  		= add_template_candidate (candidates, fn, base, NULL_TREE,
  					  mem_args, NULL_TREE, 
+ 					  TYPE_BINFO (type),
+ 					  TYPE_BINFO (type),
  					  LOOKUP_NORMAL, DEDUCE_CALL);
  	    }
  	  else
  	    candidates = add_function_candidate
! 	      (candidates, fn, base, mem_args, TYPE_BINFO (type),
! 	       TYPE_BINFO (type), LOOKUP_NORMAL);
  	}
      }
  
*************** build_object_call (obj, args)
*** 2749,2762 ****
  	    tree fn = OVL_CURRENT (fns);
  	    if (TREE_CODE (fn) == TEMPLATE_DECL) 
  	      {
! 		candidates = add_template_conv_candidate (candidates,
! 							  fn,
! 							  obj,
! 							  args,
! 							  totype);
  	      }
  	    else
! 	      candidates = add_conv_candidate (candidates, fn, obj, args);
  	  }
      }
  
--- 2831,2845 ----
  	    tree fn = OVL_CURRENT (fns);
  	    if (TREE_CODE (fn) == TEMPLATE_DECL) 
  	      {
! 		candidates = (add_template_conv_candidate 
! 			      (candidates, fn, obj, args, totype,
! 			       /*access_path=*/NULL_TREE,
! 			       /*conversion_path=*/NULL_TREE));
  	      }
  	    else
! 	      candidates = add_conv_candidate (candidates, fn, obj, args,
! 					       /*conversion_path=*/NULL_TREE,
! 					       /*access_path=*/NULL_TREE);
  	  }
      }
  
*************** conditional_conversion (e1, e2)
*** 2890,2898 ****
  }
  
  /* Implement [expr.cond].  ARG1, ARG2, and ARG3 are the three
!    arguments to the conditional expression.  By the time this function
!    is called, any suitable candidate functions are included in
!    CANDIDATES.  */
  
  tree
  build_conditional_expr (arg1, arg2, arg3)
--- 2973,2979 ----
  }
  
  /* Implement [expr.cond].  ARG1, ARG2, and ARG3 are the three
!    arguments to the conditional expression.  */
  
  tree
  build_conditional_expr (arg1, arg2, arg3)
*************** build_new_op (code, flags, arg1, arg2, a
*** 3331,3341 ****
  	  candidates 
  	    = add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
  				      arglist, TREE_TYPE (fnname),
  				      flags, DEDUCE_CALL); 
  	}
        else
  	candidates = add_function_candidate (candidates, fn, NULL_TREE,
! 					     arglist, flags);
      }
  
    if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
--- 3412,3427 ----
  	  candidates 
  	    = add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
  				      arglist, TREE_TYPE (fnname),
+ 				      /*access_path=*/NULL_TREE,
+ 				      /*conversion_path=*/NULL_TREE,
  				      flags, DEDUCE_CALL); 
  	}
        else
  	candidates = add_function_candidate (candidates, fn, NULL_TREE,
! 					     arglist,
! 					     /*access_path=*/NULL_TREE,
! 					     /*conversion_path=*/NULL_TREE,
! 					     flags);
      }
  
    if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
*************** build_new_op (code, flags, arg1, arg2, a
*** 3349,3360 ****
  
    if (fns)
      {
!       tree basetype = BINFO_TYPE (TREE_PURPOSE (fns));
        mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
!       for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  tree this_arglist;
  
  	  if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
  	    this_arglist = mem_arglist;
--- 3435,3448 ----
  
    if (fns)
      {
!       tree conversion_path = BASELINK_BINFO (fns);
! 
        mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
!       for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  tree this_arglist;
+ 	  tree access_path = TYPE_BINFO (TREE_TYPE (arg1));
  
  	  if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
  	    this_arglist = mem_arglist;
*************** build_new_op (code, flags, arg1, arg2, a
*** 3366,3381 ****
  	      /* A member template. */
  	      templates = tree_cons (NULL_TREE, fn, templates);
  	      candidates 
! 		= add_template_candidate (candidates, fn, basetype, NULL_TREE,
  					  this_arglist,  TREE_TYPE (fnname),
  					  flags, DEDUCE_CALL); 
  	    }
  	  else
  	    candidates = add_function_candidate
! 	      (candidates, fn, basetype, this_arglist, flags);
! 
! 	  if (candidates)
! 	    candidates->basetype_path = TYPE_BINFO (TREE_TYPE (arg1));
  	}
      }
  
--- 3454,3470 ----
  	      /* A member template. */
  	      templates = tree_cons (NULL_TREE, fn, templates);
  	      candidates 
! 		= add_template_candidate (candidates, fn, 
! 					  BINFO_TYPE (conversion_path),
! 					  NULL_TREE,
  					  this_arglist,  TREE_TYPE (fnname),
+ 					  access_path, conversion_path,
  					  flags, DEDUCE_CALL); 
  	    }
  	  else
  	    candidates = add_function_candidate
! 	      (candidates, fn, BINFO_TYPE (conversion_path), this_arglist, 
! 	       access_path, conversion_path, flags);
  	}
      }
  
*************** convert_like_real (convs, expr, fn, argn
*** 3863,3869 ****
  	    && (inner >= 0 || !lvalue_p (expr)))
  	  {
  	    savew = warningcount, savee = errorcount;
! 	    expr = build_new_method_call
  	      (NULL_TREE, complete_ctor_identifier,
  	       build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
  	       /* Core issue 84, now a DR, says that we don't allow UDCs
--- 3952,3958 ----
  	    && (inner >= 0 || !lvalue_p (expr)))
  	  {
  	    savew = warningcount, savee = errorcount;
! 	    expr = build_special_member_call
  	      (NULL_TREE, complete_ctor_identifier,
  	       build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
  	       /* Core issue 84, now a DR, says that we don't allow UDCs
*************** convert_like_real (convs, expr, fn, argn
*** 3945,3954 ****
  	 type is the same class as, or a derived class of, the class of the
  	 destination [is treated as direct-initialization].  [dcl.init] */
        savew = warningcount, savee = errorcount;
!       expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
! 				    build_tree_list (NULL_TREE, expr),
! 				    TYPE_BINFO (totype),
! 				    LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
        if (fn)
  	{
  	  if (warningcount > savew)
--- 4034,4043 ----
  	 type is the same class as, or a derived class of, the class of the
  	 destination [is treated as direct-initialization].  [dcl.init] */
        savew = warningcount, savee = errorcount;
!       expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
! 					build_tree_list (NULL_TREE, expr),
! 					TYPE_BINFO (totype),
! 					LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
        if (fn)
  	{
  	  if (warningcount > savew)
*************** build_over_call (cand, args, flags)
*** 4207,4213 ****
        joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
  
    if (DECL_FUNCTION_MEMBER_P (fn))
!     enforce_access (cand->basetype_path, fn);
  
    if (args && TREE_CODE (args) != TREE_LIST)
      args = build_tree_list (NULL_TREE, args);
--- 4296,4302 ----
        joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
  
    if (DECL_FUNCTION_MEMBER_P (fn))
!     enforce_access (cand->access_path, fn);
  
    if (args && TREE_CODE (args) != TREE_LIST)
      args = build_tree_list (NULL_TREE, args);
*************** build_over_call (cand, args, flags)
*** 4236,4242 ****
      {
        tree parmtype = TREE_VALUE (parm);
        tree argtype = TREE_TYPE (TREE_VALUE (arg));
!       tree t;
        if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
  	pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
  		    TREE_TYPE (argtype), fn);
--- 4325,4332 ----
      {
        tree parmtype = TREE_VALUE (parm);
        tree argtype = TREE_TYPE (TREE_VALUE (arg));
!       tree converted_arg;
! 
        if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
  	pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
  		    TREE_TYPE (argtype), fn);
*************** build_over_call (cand, args, flags)
*** 4248,4257 ****
           So we can assume that anything passed as 'this' is non-null, and
  	 optimize accordingly.  */
        my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
!       t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))),
! 		       TREE_TYPE (parmtype), ba_ignore, NULL);
!       t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1);
!       converted_args = tree_cons (NULL_TREE, t, converted_args);
        parm = TREE_CHAIN (parm);
        arg = TREE_CHAIN (arg);
        ++i;
--- 4338,4350 ----
           So we can assume that anything passed as 'this' is non-null, and
  	 optimize accordingly.  */
        my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
!       /* Convert to the base in which the function was declared.  */
!       my_friendly_assert (cand->conversion_path != NULL_TREE, 20020730);
!       converted_arg = build_base_path (PLUS_EXPR,
! 				       TREE_VALUE (arg),
! 				       cand->conversion_path,
! 				       1);
!       converted_args = tree_cons (NULL_TREE, converted_arg, converted_args);
        parm = TREE_CHAIN (parm);
        arg = TREE_CHAIN (arg);
        ++i;
*************** in_charge_arg_for_name (name)
*** 4534,4676 ****
    return NULL_TREE;
  }
  
! static tree
! build_new_method_call (instance, name, args, basetype_path, flags)
!      tree instance, name, args, basetype_path;
!      int flags;
  {
    struct z_candidate *candidates = 0, *cand;
    tree explicit_targs = NULL_TREE;
!   tree basetype, mem_args = NULL_TREE, fns, instance_ptr;
!   tree pretty_name;
    tree user_args;
    tree templates = NULL_TREE;
    tree call;
    int template_only = 0;
  
!   if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
!     {
!       explicit_targs = TREE_OPERAND (name, 1);
!       name = TREE_OPERAND (name, 0);
!       if (DECL_P (name))
! 	name = DECL_NAME (name);
!       else
! 	{
! 	  if (TREE_CODE (name) == COMPONENT_REF)
! 	    name = TREE_OPERAND (name, 1);
! 	  if (TREE_CODE (name) == OVERLOAD)
! 	    name = DECL_NAME (OVL_CURRENT (name));
! 	}
  
!       template_only = 1;
!     }
  
    user_args = args;
    args = resolve_args (args);
- 
    if (args == error_mark_node)
      return error_mark_node;
  
!   if (instance == NULL_TREE)
!     basetype = BINFO_TYPE (basetype_path);
!   else
!     {
!       if (TREE_CODE (instance) == OFFSET_REF)
! 	instance = resolve_offset_ref (instance);
!       if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
! 	instance = convert_from_reference (instance);
!       basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
! 
!       /* XXX this should be handled before we get here.  */
!       if (! IS_AGGR_TYPE (basetype))
! 	{
! 	  if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
! 	    error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
! 		      name, instance, basetype);
! 
! 	  return error_mark_node;
! 	}
      }
  
!   if (basetype_path == NULL_TREE)
!     basetype_path = TYPE_BINFO (basetype);
  
!   if (instance)
      {
!       instance_ptr = build_this (instance);
! 
!       if (! template_only)
! 	{
! 	  /* XXX this should be handled before we get here.  */
! 	  fns = build_field_call (basetype_path, instance_ptr, name, args);
! 	  if (fns)
! 	    return fns;
! 	}
      }
!   else
!     {
!       instance_ptr = build_int_2 (0, 0);
!       TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
      }
  
!   /* Callers should explicitly indicate whether they want to construct
!      the complete object or just the part without virtual bases.  */
!   my_friendly_assert (name != ctor_identifier, 20000408);
!   /* Similarly for destructors.  */
!   my_friendly_assert (name != dtor_identifier, 20000408);
  
    if (IDENTIFIER_CTOR_OR_DTOR_P (name))
      {
!       int constructor_p;
! 
!       constructor_p = (name == complete_ctor_identifier
! 		       || name == base_ctor_identifier);
!       pretty_name = (constructor_p 
! 		     ? constructor_name (basetype) : dtor_identifier);
! 
!       /* If we're a call to a constructor or destructor for a
! 	 subobject that uses virtual base classes, then we need to
! 	 pass down a pointer to a VTT for the subobject.  */
!       if ((name == base_ctor_identifier
! 	   || name == base_dtor_identifier)
! 	  && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
! 	{
! 	  tree vtt;
! 	  tree sub_vtt;
! 	  tree basebinfo = basetype_path;
! 
! 	  /* If the current function is a complete object constructor
! 	     or destructor, then we fetch the VTT directly.
! 	     Otherwise, we look it up using the VTT we were given.  */
! 	  vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
! 	  vtt = decay_conversion (vtt);
! 	  vtt = build (COND_EXPR, TREE_TYPE (vtt),
! 		       build (EQ_EXPR, boolean_type_node,
! 			      current_in_charge_parm, integer_zero_node),
! 		       current_vtt_parm,
! 		       vtt);
! 	  if (TREE_VIA_VIRTUAL (basebinfo))
! 	    basebinfo = binfo_for_vbase (basetype, current_class_type);
! 	  my_friendly_assert (BINFO_SUBVTT_INDEX (basebinfo), 20010110);
! 	  sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
! 			   BINFO_SUBVTT_INDEX (basebinfo));
! 
! 	  args = tree_cons (NULL_TREE, sub_vtt, args);
! 	}
      }
    else
      pretty_name = name;
  
-   fns = lookup_fnfields (basetype_path, name, 1);
- 
-   if (fns == error_mark_node)
-     return error_mark_node;
    if (fns)
      {
!       tree base = BINFO_TYPE (TREE_PURPOSE (fns));
!       tree fn = TREE_VALUE (fns);
        mem_args = tree_cons (NULL_TREE, instance_ptr, args);
!       for (; fn; fn = OVL_NEXT (fn))
  	{
  	  tree t = OVL_CURRENT (fn);
  	  tree this_arglist;
--- 4627,4817 ----
    return NULL_TREE;
  }
  
! /* Build a call to a constructor, destructor, or an assignment
!    operator for INSTANCE, an expression with class type.  NAME
!    indicates the special member function to call; ARGS are the
!    arguments.  BINFO indicates the base of INSTANCE that is to be
!    passed as the `this' parameter to the member function called.
! 
!    FLAGS are the LOOKUP_* flags to use when processing the call.
! 
!    If NAME indicates a complete object constructor, INSTANCE may be
!    NULL_TREE.  In this case, the caller will call build_cplus_new to
!    store the newly constructed object into a VAR_DECL.  */
! 
! tree
! build_special_member_call (tree instance, tree name, tree args, 
! 			   tree binfo, int flags)
! {
!   tree fns;
!   /* The type of the subobject to be constructed or destroyed.  */
!   tree class_type;
! 
!   my_friendly_assert (name == complete_ctor_identifier
! 		      || name == base_ctor_identifier
! 		      || name == complete_dtor_identifier
! 		      || name == base_dtor_identifier
! 		      || name == deleting_dtor_identifier
! 		      || name == ansi_assopname (NOP_EXPR),
! 		      20020712);
!   my_friendly_assert (binfo != NULL_TREE, 20020712);
! 
!   class_type = BINFO_TYPE (binfo);
! 
!   /* Handle the special case where INSTANCE is NULL_TREE.  */
!   if (name == complete_ctor_identifier && !instance)
!     {
!       instance = build_int_2 (0, 0);
!       TREE_TYPE (instance) = build_pointer_type (class_type);
!       instance = build1 (INDIRECT_REF, class_type, instance);
!     }
!   else if (name == complete_dtor_identifier 
! 	   || name == base_dtor_identifier
! 	   || name == deleting_dtor_identifier)
!     my_friendly_assert (args == NULL_TREE, 20020712);
! 
!   my_friendly_assert (instance != NULL_TREE, 20020712);
! 
!   /* Resolve the name.  */
!   if (!complete_type_or_else (BINFO_TYPE (binfo), NULL_TREE))
!     return error_mark_node;
! 
!   fns = lookup_fnfields (binfo, name, 1);
!     
!   /* When making a call to a constructor or destructor for a subobject
!      that uses virtual base classes, pass down a pointer to a VTT for
!      the subobject.  */
!   if ((name == base_ctor_identifier
!        || name == base_dtor_identifier)
!       && TYPE_USES_VIRTUAL_BASECLASSES (class_type))
!     {
!       tree vtt;
!       tree sub_vtt;
! 
!       /* If the current function is a complete object constructor
! 	 or destructor, then we fetch the VTT directly.
! 	 Otherwise, we look it up using the VTT we were given.  */
!       vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
!       vtt = decay_conversion (vtt);
!       vtt = build (COND_EXPR, TREE_TYPE (vtt),
! 		   build (EQ_EXPR, boolean_type_node,
! 			  current_in_charge_parm, integer_zero_node),
! 		   current_vtt_parm,
! 		   vtt);
!       if (TREE_VIA_VIRTUAL (binfo))
! 	binfo = binfo_for_vbase (class_type, current_class_type);
!       my_friendly_assert (BINFO_SUBVTT_INDEX (binfo), 20010110);
!       sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
! 		       BINFO_SUBVTT_INDEX (binfo));
! 
!       args = tree_cons (NULL_TREE, sub_vtt, args);
!     }
! 
!   return build_new_method_call (instance, fns, args, binfo, flags);
! }
! 
! /* Build a call to "INSTANCE.FN (ARGS)".  */
! 
! tree
! build_new_method_call (tree instance, tree fns, tree args, 
! 		       tree conversion_path, int flags)
  {
    struct z_candidate *candidates = 0, *cand;
    tree explicit_targs = NULL_TREE;
!   tree basetype = NULL_TREE;
!   tree access_binfo;
!   tree optype;
!   tree mem_args = NULL_TREE, instance_ptr;
!   tree name, pretty_name;
    tree user_args;
    tree templates = NULL_TREE;
    tree call;
    int template_only = 0;
  
!   my_friendly_assert (instance != NULL_TREE, 20020729);
  
!   if (instance == error_mark_node || fns == error_mark_node 
!       || args == error_mark_node)
!     return error_mark_node;
  
+   /* Process the argument list.  */
    user_args = args;
    args = resolve_args (args);
    if (args == error_mark_node)
      return error_mark_node;
  
!   if (TREE_CODE (instance) == OFFSET_REF)
!     instance = resolve_offset_ref (instance);
!   if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
!     instance = convert_from_reference (instance);
!   basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
!   instance_ptr = build_this (instance);
! 
!   if (!BASELINK_P (fns))
!     {
!       call = build_field_call (instance_ptr, fns, args);
!       if (call)
! 	return call;
!       error ("call to non-function `%D'", fns);
!       return error_mark_node;
      }
  
!   if (!conversion_path)
!     conversion_path = BASELINK_BINFO (fns);
!   access_binfo = BASELINK_ACCESS_BINFO (fns);
!   optype = BASELINK_OPTYPE (fns);
!   fns = BASELINK_FUNCTIONS (fns);
  
!   if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
      {
!       explicit_targs = TREE_OPERAND (fns, 1);
!       fns = TREE_OPERAND (fns, 0);
!       template_only = 1;
      }
! 
!   my_friendly_assert (TREE_CODE (fns) == FUNCTION_DECL
! 		      || TREE_CODE (fns) == TEMPLATE_DECL
! 		      || TREE_CODE (fns) == OVERLOAD,
! 		      20020712);
! 
!   /* XXX this should be handled before we get here.  */
!   if (! IS_AGGR_TYPE (basetype))
!     {
!       if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
! 	error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
! 	       fns, instance, basetype);
! 
!       return error_mark_node;
      }
  
!   name = DECL_NAME (get_first_fn (fns));
  
    if (IDENTIFIER_CTOR_OR_DTOR_P (name))
      {
!       /* Callers should explicitly indicate whether they want to construct
! 	 the complete object or just the part without virtual bases.  */
!       my_friendly_assert (name != ctor_identifier, 20000408);
!       /* Similarly for destructors.  */
!       my_friendly_assert (name != dtor_identifier, 20000408);
!       
!       if (name == complete_ctor_identifier
! 	  || name == base_ctor_identifier)
! 	pretty_name = constructor_name (basetype);
!       else
! 	pretty_name = dtor_identifier;
      }
    else
      pretty_name = name;
  
    if (fns)
      {
!       tree fn;
!       tree class_type = (conversion_path 
! 			 ? BINFO_TYPE (conversion_path)
! 			 : NULL_TREE);
! 
        mem_args = tree_cons (NULL_TREE, instance_ptr, args);
!       for (fn = fns; fn; fn = OVL_NEXT (fn))
  	{
  	  tree t = OVL_CURRENT (fn);
  	  tree this_arglist;
*************** build_new_method_call (instance, name, a
*** 4690,4705 ****
  	      /* A member template. */
  	      templates = tree_cons (NULL_TREE, t, templates);
  	      candidates = 
! 		add_template_candidate (candidates, t, base, explicit_targs,
! 					this_arglist,
! 					TREE_TYPE (name), flags, DEDUCE_CALL); 
  	    }
  	  else if (! template_only)
! 	    candidates = add_function_candidate (candidates, t, base,
! 						 this_arglist, flags);
! 
! 	  if (candidates)
! 	    candidates->basetype_path = basetype_path;
  	}
      }
  
--- 4831,4852 ----
  	      /* A member template. */
  	      templates = tree_cons (NULL_TREE, t, templates);
  	      candidates = 
! 		add_template_candidate (candidates, t, 
! 					class_type,
! 					explicit_targs,
! 					this_arglist, optype,
! 					access_binfo, 
! 					conversion_path,
! 					flags,
! 					DEDUCE_CALL);
  	    }
  	  else if (! template_only)
! 	    candidates = add_function_candidate (candidates, t, 
! 						 class_type,
! 						 this_arglist,
! 						 access_binfo,
! 						 conversion_path,
! 						 flags);
  	}
      }
  
*************** build_new_method_call (instance, name, a
*** 4754,4762 ****
    else
      {
        call = build_over_call (cand, args, flags);
!       /* Do evaluate the object parameter in a call to a static member
! 	 function.  */
!       if (TREE_SIDE_EFFECTS (instance))
  	call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
      }
  
--- 4901,4909 ----
    else
      {
        call = build_over_call (cand, args, flags);
!       /* In an expression of the form `a->f()' where `f' turns out to
! 	 be a static member function, `a' is none-the-less evaluated.  */
!       if (instance && TREE_SIDE_EFFECTS (instance))
  	call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
      }
  
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.63
diff -c -p -r1.63 cp-tree.def
*** cp/cp-tree.def	4 Apr 2002 00:10:55 -0000	1.63
--- cp/cp-tree.def	1 Aug 2002 04:43:45 -0000
*************** the Free Software Foundation, 59 Temple 
*** 23,33 ****
  Boston, MA 02111-1307, USA.  */
  
   
! /* Reference to the contents of an offset
!    (a value whose type is an OFFSET_TYPE).
!    Operand 0 is the object within which the offset is taken.
!    Operand 1 is the offset.  The language independent OFFSET_REF
!    just won't work for us.  */
  DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
  
  /* A pointer-to-member constant.  For a pointer-to-member constant
--- 23,47 ----
  Boston, MA 02111-1307, USA.  */
  
   
! /* An OFFSET_REF is used in two situations:
! 
!    1. An expression of the form `A::m' where `A' is a class and `m' is
!       a non-static data member.  In this case, operand 0 will be a
!       TYPE (corresponding to `A') and operand 1 will be a FIELD_DECL
!       (corresponding to `m'.
! 
!       The expression is a pointer-to-member if its address is taken,
!       but simply denotes a member of the object if its address isnot
!       taken.  In the latter case, resolve_offset_ref is used to
!       convert it to a representation of the member referred to by the
!       OFFSET_REF.
! 
!    2. An expression of the form `x.*p'.  In this case, operand 0 will
!       be an expression corresponding to `x' and operand 1 will be an
!       expression with pointer-to-member type.
! 
!    OFFSET_REFs are only used during the parsing phase; once semantic
!    analysis has taken place they are eliminated.  */
  DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
  
  /* A pointer-to-member constant.  For a pointer-to-member constant
*************** DEFTREECODE (DEFAULT_ARG, "default_arg",
*** 186,192 ****
     The second is the TREE_LIST or TREE_VEC of explicitly specified
     arguments.  The template will be a FUNCTION_DECL, TEMPLATE_DECL, or
     an OVERLOAD.  If the template-id refers to a member template, the
!    template may be an IDENTIFIER_NODE.  */
  DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
  
  /* An association between name and entity. Parameters are the scope
--- 200,207 ----
     The second is the TREE_LIST or TREE_VEC of explicitly specified
     arguments.  The template will be a FUNCTION_DECL, TEMPLATE_DECL, or
     an OVERLOAD.  If the template-id refers to a member template, the
!    template may be an IDENTIFIER_NODE.  In an uninstantiated template,
!    the template may be a LOOKUP_EXPR.  */
  DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
  
  /* An association between name and entity. Parameters are the scope
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.738
diff -c -p -r1.738 cp-tree.h
*** cp/cp-tree.h	30 Jul 2002 07:49:40 -0000	1.738
--- cp/cp-tree.h	1 Aug 2002 04:43:46 -0000
*************** struct tree_overload GTY(())
*** 385,394 ****
--- 385,409 ----
    (TREE_CODE (NODE) == TREE_LIST && TREE_LANG_FLAG_1 (NODE))
  #define SET_BASELINK_P(NODE) \
    (TREE_LANG_FLAG_1 (NODE) = 1)
+ /* The BINFO indicated the base from which the BASELINK_FUNCTIONS came.  */
+ #define BASELINK_BINFO(NODE) \
+   (TREE_PURPOSE (NODE))
  /* The functions referred to by the BASELINK; either a FUNCTION_DECL
     or an OVERLOAD.  */
  #define BASELINK_FUNCTIONS(NODE) \
    (TREE_VALUE (NODE))
+ /* The BINFO in which the search for the functions indicated by this baselink 
+    began.  This base is used to determine the accessibility of functions 
+    selected by overload resolution.  */
+ #define BASELINK_ACCESS_BINFO(NODE) \
+   (TREE_TYPE (NODE))
+ /* For a type-conversion operator, the BASELINK_OPTYPE indicates the type
+    to which the conversion should occur.  This value is important if
+    the BASELINK_FUNCTIONS include a template conversion operator --
+    the BASELINK_OPTYPE can be used to determine what type the user
+    requested.  */
+ #define BASELINK_OPTYPE(NODE) \
+   (TREE_CHAIN (NODE))
  
  #define WRAPPER_ZC(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c)
  
*************** extern int sufficient_parms_p           
*** 3676,3681 ****
--- 3691,3698 ----
  extern tree type_decays_to			PARAMS ((tree));
  extern tree build_user_type_conversion		PARAMS ((tree, tree, int));
  extern tree build_new_function_call		PARAMS ((tree, tree));
+ extern tree build_new_method_call               (tree, tree, tree, tree, int);
+ extern tree build_special_member_call           (tree, tree, tree, tree, int);
  extern tree build_new_op			PARAMS ((enum tree_code, int, tree, tree, tree));
  extern tree build_op_delete_call		PARAMS ((enum tree_code, tree, tree, int, tree));
  extern int can_convert				PARAMS ((tree, tree));
*************** extern void finish_file				PARAMS ((void
*** 3950,3955 ****
--- 3967,3974 ----
  extern tree reparse_absdcl_as_expr		PARAMS ((tree, tree));
  extern tree reparse_absdcl_as_casts		PARAMS ((tree, tree));
  extern tree build_expr_from_tree		PARAMS ((tree));
+ extern tree build_offset_ref_call_from_tree     (tree, tree);
+ extern tree build_call_from_tree                (tree, tree, bool);
  extern tree reparse_decl_as_expr		PARAMS ((tree, tree));
  extern tree finish_decl_parsing			PARAMS ((tree));
  extern void set_decl_namespace                  PARAMS ((tree, tree, int));
*************** extern tree unmarked_vtable_pathp       
*** 4229,4234 ****
--- 4248,4254 ----
  extern tree find_vbase_instance                 PARAMS ((tree, tree));
  extern tree binfo_for_vbase                     PARAMS ((tree, tree));
  extern tree binfo_via_virtual                   PARAMS ((tree, tree));
+ extern tree build_baselink                      (tree, tree, tree, tree);
  
  /* in semantics.c */
  extern void init_cp_semantics                   PARAMS ((void));
*************** extern void finish_subobject            
*** 4281,4293 ****
  extern tree finish_parenthesized_expr           PARAMS ((tree));
  extern tree begin_stmt_expr                     PARAMS ((void));
  extern tree finish_stmt_expr                    PARAMS ((tree));
! extern tree finish_call_expr                    PARAMS ((tree, tree, int));
  extern tree finish_increment_expr               PARAMS ((tree, enum tree_code));
  extern tree finish_this_expr                    PARAMS ((void));
  extern tree finish_object_call_expr             PARAMS ((tree, tree, tree));
  extern tree finish_qualified_object_call_expr   PARAMS ((tree, tree, tree));
  extern tree finish_pseudo_destructor_call_expr  PARAMS ((tree, tree, tree));
- extern tree finish_qualified_call_expr          PARAMS ((tree, tree));
  extern tree finish_unary_op_expr                PARAMS ((enum tree_code, tree));
  extern tree finish_id_expr                      PARAMS ((tree));
  extern tree finish_fname                        (tree);
--- 4301,4312 ----
  extern tree finish_parenthesized_expr           PARAMS ((tree));
  extern tree begin_stmt_expr                     PARAMS ((void));
  extern tree finish_stmt_expr                    PARAMS ((tree));
! extern tree finish_call_expr                    (tree, tree, bool);
  extern tree finish_increment_expr               PARAMS ((tree, enum tree_code));
  extern tree finish_this_expr                    PARAMS ((void));
  extern tree finish_object_call_expr             PARAMS ((tree, tree, tree));
  extern tree finish_qualified_object_call_expr   PARAMS ((tree, tree, tree));
  extern tree finish_pseudo_destructor_call_expr  PARAMS ((tree, tree, tree));
  extern tree finish_unary_op_expr                PARAMS ((enum tree_code, tree));
  extern tree finish_id_expr                      PARAMS ((tree));
  extern tree finish_fname                        (tree);
*************** extern tree build_x_component_ref		PARAM
*** 4454,4460 ****
  extern tree build_x_indirect_ref		PARAMS ((tree, const char *));
  extern tree build_indirect_ref			PARAMS ((tree, const char *));
  extern tree build_array_ref			PARAMS ((tree, tree));
- extern tree build_x_function_call		PARAMS ((tree, tree, tree));
  extern tree get_member_function_from_ptrfunc	PARAMS ((tree *, tree));
  extern tree build_function_call_real		PARAMS ((tree, tree, int, int));
  extern tree build_function_call_maybe		PARAMS ((tree, tree));
--- 4473,4478 ----
Index: cp/cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.119
diff -c -p -r1.119 cvt.c
*** cp/cvt.c	5 Jul 2002 22:10:07 -0000	1.119
--- cp/cvt.c	1 Aug 2002 04:43:46 -0000
*************** ocp_convert (type, expr, convtype, flags
*** 771,780 ****
  	   the target with the temp (see [dcl.init]).  */
  	ctor = build_user_type_conversion (type, ctor, flags);
        else
! 	ctor = build_method_call (NULL_TREE, 
! 				  complete_ctor_identifier,
! 				  build_tree_list (NULL_TREE, ctor),
! 				  TYPE_BINFO (type), flags);
        if (ctor)
  	return build_cplus_new (type, ctor);
      }
--- 771,780 ----
  	   the target with the temp (see [dcl.init]).  */
  	ctor = build_user_type_conversion (type, ctor, flags);
        else
! 	ctor = build_special_member_call (NULL_TREE, 
! 					  complete_ctor_identifier,
! 					  build_tree_list (NULL_TREE, ctor),
! 					  TYPE_BINFO (type), flags);
        if (ctor)
  	return build_cplus_new (type, ctor);
      }
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.552
diff -c -p -r1.552 decl2.c
*** cp/decl2.c	27 Jul 2002 21:15:39 -0000	1.552
--- cp/decl2.c	1 Aug 2002 04:43:47 -0000
*************** reparse_absdcl_as_expr (type, decl)
*** 3587,3600 ****
    /* recurse */
    decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
  
!   decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
! 
!   if (TREE_CODE (decl) == CALL_EXPR
!       && (! TREE_TYPE (decl)
!           || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE))
!     decl = require_complete_type (decl);
! 
!   return decl;
  }
  
  /* This is something of the form `int ((int)(int)(int)1)' that has turned
--- 3587,3593 ----
    /* recurse */
    decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
  
!   return finish_call_expr (decl, NULL_TREE, /*disallow_virtual=*/false);
  }
  
  /* This is something of the form `int ((int)(int)(int)1)' that has turned
*************** reparse_absdcl_as_casts (decl, expr)
*** 3647,3653 ****
    return expr;
  }
  
! /* Given plain tree nodes for an expression, build up the full semantics.  */
  
  tree
  build_expr_from_tree (t)
--- 3640,3647 ----
    return expr;
  }
  
! /* T is the parse tree for an expression.  Return the expression after
!    performing semantic analysis.  */
  
  tree
  build_expr_from_tree (t)
*************** build_expr_from_tree (t)
*** 3671,3679 ****
  	return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
  
      case TEMPLATE_ID_EXPR:
!       return (lookup_template_function
! 	      (build_expr_from_tree (TREE_OPERAND (t, 0)),
! 	       build_expr_from_tree (TREE_OPERAND (t, 1))));
  
      case INDIRECT_REF:
        return build_x_indirect_ref
--- 3665,3693 ----
  	return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
  
      case TEMPLATE_ID_EXPR:
!       {
! 	tree template;
! 	tree args;
! 	tree object;
! 
! 	template = build_expr_from_tree (TREE_OPERAND (t, 0));
! 	args = build_expr_from_tree (TREE_OPERAND (t, 1));
! 	
! 	if (TREE_CODE (template) == COMPONENT_REF)
! 	  {
! 	    object = TREE_OPERAND (template, 0);
! 	    template = TREE_OPERAND (template, 1);
! 	  }
! 	else
! 	  object = NULL_TREE;
! 
! 	template = lookup_template_function (template, args);
! 	if (object)
! 	  return build (COMPONENT_REF, TREE_TYPE (template), 
! 			object, template);
! 	else
! 	  return template;
!       }
  
      case INDIRECT_REF:
        return build_x_indirect_ref
*************** build_expr_from_tree (t)
*** 3881,3889 ****
                name = do_identifier (id, 0, args);
              }
            else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
! 	      || ! really_overloaded_fn (name))
  	    name = build_expr_from_tree (name);
! 	  return build_x_function_call (name, args, current_class_ref);
  	}
  
      case COND_EXPR:
--- 3895,3912 ----
                name = do_identifier (id, 0, args);
              }
            else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
! 		   || ! really_overloaded_fn (name))
  	    name = build_expr_from_tree (name);
! 
! 	  if (TREE_CODE (name) == OFFSET_REF)
! 	    return build_offset_ref_call_from_tree (name, args);
! 	  if (TREE_CODE (name) == COMPONENT_REF)
! 	    return finish_object_call_expr (TREE_OPERAND (name, 1),
! 					    TREE_OPERAND (name, 0),
! 					    args);
! 	  name = convert_from_reference (name);
! 	  return build_call_from_tree (name, args, 
! 				       /*disallow_virtual=*/false);
  	}
  
      case COND_EXPR:
*************** build_expr_from_tree (t)
*** 3986,3991 ****
--- 4009,4113 ----
      default:
        return t;
      }
+ }
+ 
+ /* FN is an OFFSET_REF indicating the function to call in parse-tree
+    form; it has not yet been semantically analyzed.  ARGS are the
+    arguments to the function.  They have already been semantically
+    analzyed.  */
+ 
+ tree
+ build_offset_ref_call_from_tree (tree fn, tree args)
+ {
+   tree object_addr;
+ 
+   my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
+ 
+   /* A qualified name corresponding to a non-static member
+      function or a pointer-to-member is represented as an 
+      OFFSET_REF.  
+ 
+      For both of these function calls, FN will be an OFFSET_REF.
+ 
+ 	struct A { void f(); };
+ 	void A::f() { (A::f) (); } 
+ 
+ 	struct B { void g(); };
+ 	void (B::*p)();
+ 	void B::g() { (this->*p)(); }  */
+ 
+   /* This code is not really correct (for example, it does not
+      handle the case that `A::f' is overloaded), but it is
+      historically how we have handled this situation.  */
+   object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
+   if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
+     fn = resolve_offset_ref (fn);
+   else
+     {
+       fn = TREE_OPERAND (fn, 1);
+       fn = get_member_function_from_ptrfunc (&object_addr, fn);
+     }
+   args = tree_cons (NULL_TREE, object_addr, args);
+   return build_function_call (fn, args);
+ }
+ 
+ /* FN indicates the function to call.  Name resolution has been
+    performed on FN.  ARGS are the arguments to the function.  They
+    have already been semantically analyzed.  DISALLOW_VIRTUAL is true
+    if the function call should be determined at compile time, even if
+    FN is virtual.  */
+ 
+ tree
+ build_call_from_tree (tree fn, tree args, bool disallow_virtual)
+ {
+   tree template_args;
+   tree template_id;
+   tree f;
+   
+   /* Check to see that name lookup has already been performed.  */
+   my_friendly_assert (TREE_CODE (fn) != OFFSET_REF, 20020725);
+   my_friendly_assert (TREE_CODE (fn) != SCOPE_REF, 20020725);
+ 
+   /* In the future all of this should be eliminated.  Instead,
+      name-lookup for a member function should simply return a
+      baselink, instead of a FUNCTION_DECL, TEMPLATE_DECL, or
+      TEMPLATE_ID_EXPR.  */
+ 
+   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+     {
+       template_id = fn;
+       template_args = TREE_OPERAND (fn, 1);
+       fn = TREE_OPERAND (fn, 0);
+     }
+   else
+     template_id = NULL_TREE;
+ 
+   f = (TREE_CODE (fn) == OVERLOAD) ? get_first_fn (fn) : fn;
+   /* Make sure we have a baselink (rather than simply a
+      FUNCTION_DECL) for a member function.  */
+   if (current_class_type
+       && ((TREE_CODE (f) == FUNCTION_DECL
+ 	   && DECL_FUNCTION_MEMBER_P (f))
+ 	  || (DECL_FUNCTION_TEMPLATE_P (f) 
+ 	      && DECL_FUNCTION_MEMBER_P (f))))
+     {
+       f = lookup_member (current_class_type, DECL_NAME (f), 
+ 			 /*protect=*/1, /*want_type=*/0);
+       if (f)
+ 	fn = f;
+     }
+ 
+   if (template_id)
+     {
+       if (BASELINK_P (fn))
+ 	  BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR, 
+ 					      BASELINK_FUNCTIONS (fn),
+ 					      template_args);
+       else
+ 	fn = template_id;
+     }
+ 
+   return finish_call_expr (fn, args, disallow_virtual);
  }
  
  /* This is something of the form `int (*a)++' that has turned out to be an
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.286
diff -c -p -r1.286 init.c
*** cp/init.c	26 Jul 2002 20:10:42 -0000	1.286
--- cp/init.c	1 Aug 2002 04:43:48 -0000
*************** expand_cleanup_for_base (binfo, flag)
*** 852,859 ****
      return;
  
    /* Call the destructor.  */
!   expr = (build_scoped_method_call
! 	  (current_class_ref, binfo, base_dtor_identifier, NULL_TREE));
    if (flag)
      expr = fold (build (COND_EXPR, void_type_node,
  			c_common_truthvalue_conversion (flag),
--- 852,862 ----
      return;
  
    /* Call the destructor.  */
!   expr = build_special_member_call (current_class_ref, 
! 				    base_dtor_identifier,
! 				    NULL_TREE,
! 				    binfo,
! 				    LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
    if (flag)
      expr = fold (build (COND_EXPR, void_type_node,
  			c_common_truthvalue_conversion (flag),
*************** expand_default_init (binfo, true_exp, ex
*** 1282,1288 ****
    else
      ctor_name = base_ctor_identifier;
  
!   rval = build_method_call (exp, ctor_name, parms, binfo, flags);
    if (TREE_SIDE_EFFECTS (rval))
      {
        if (building_stmt_tree ())
--- 1285,1291 ----
    else
      ctor_name = base_ctor_identifier;
  
!   rval = build_special_member_call (exp, ctor_name, parms, binfo, flags);
    if (TREE_SIDE_EFFECTS (rval))
      {
        if (building_stmt_tree ())
*************** build_member_call (type, name, parmlist)
*** 1451,1465 ****
  	  TREE_OPERAND (name, 0) = method_name;
  	}
        my_friendly_assert (is_overloaded_fn (method_name), 980519);
!       return build_x_function_call (name, parmlist, current_class_ref);
      }
  
    if (DECL_P (name))
      name = DECL_NAME (name);
  
    if (TREE_CODE (type) == NAMESPACE_DECL)
!     return build_x_function_call (lookup_namespace_name (type, name),
! 				  parmlist, current_class_ref);
  
    if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
      {
--- 1454,1469 ----
  	  TREE_OPERAND (name, 0) = method_name;
  	}
        my_friendly_assert (is_overloaded_fn (method_name), 980519);
!       return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
      }
  
    if (DECL_P (name))
      name = DECL_NAME (name);
  
    if (TREE_CODE (type) == NAMESPACE_DECL)
!     return finish_call_expr (lookup_namespace_name (type, name),
! 			     parmlist,
! 			     /*disallow_virtual=*/true);
  
    if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
      {
*************** build_member_call (type, name, parmlist)
*** 1486,1495 ****
      {
        tree ns = lookup_name (type, 0);
        if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
! 	{
! 	  return build_x_function_call (build_offset_ref (type, name),
! 					parmlist, current_class_ref);
! 	}
      }
  
    if (type == NULL_TREE || ! is_aggr_type (type, 1))
--- 1490,1498 ----
      {
        tree ns = lookup_name (type, 0);
        if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
! 	return finish_call_expr (lookup_namespace_name (ns, name),
! 				 parmlist,
! 				 /*disallow_virtual=*/true);
      }
  
    if (type == NULL_TREE || ! is_aggr_type (type, 1))
*************** build_new_1 (exp)
*** 2326,2332 ****
  		       args));
        else
  	alloc_call = build_method_call (build_dummy_object (true_type),
! 					fnname, args, NULL_TREE,
  					LOOKUP_NORMAL);
      }
  
--- 2329,2336 ----
  		       args));
        else
  	alloc_call = build_method_call (build_dummy_object (true_type),
! 					fnname, args, 
! 					TYPE_BINFO (true_type),
  					LOOKUP_NORMAL);
      }
  
*************** build_new_1 (exp)
*** 2415,2424 ****
        if (has_array)
  	init_expr = build_vec_init (init_expr, init, 0);
        else if (TYPE_NEEDS_CONSTRUCTING (type))
! 	init_expr = build_method_call (init_expr, 
! 				       complete_ctor_identifier,
! 				       init, TYPE_BINFO (true_type),
! 				       LOOKUP_NORMAL);
        else
  	{
  	  /* We are processing something like `new int (10)', which
--- 2419,2428 ----
        if (has_array)
  	init_expr = build_vec_init (init_expr, init, 0);
        else if (TYPE_NEEDS_CONSTRUCTING (type))
! 	init_expr = build_special_member_call (init_expr, 
! 					       complete_ctor_identifier,
! 					       init, TYPE_BINFO (true_type),
! 					       LOOKUP_NORMAL);
        else
  	{
  	  /* We are processing something like `new int (10)', which
*************** build_dtor_call (exp, dtor_kind, flags)
*** 3090,3096 ****
      default:
        abort ();
      }
!   return build_method_call (exp, name, NULL_TREE, NULL_TREE, flags);
  }
  
  /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
--- 3094,3101 ----
      default:
        abort ();
      }
!   return build_method_call (exp, name, NULL_TREE, 
! 			    TYPE_BINFO (TREE_TYPE (exp)), flags);
  }
  
  /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
*************** push_base_cleanups ()
*** 3282,3290 ****
  
  	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
  	    {
! 	      expr = build_scoped_method_call (current_class_ref, vbase,
! 					       base_dtor_identifier,
! 					       NULL_TREE);
  	      expr = build (COND_EXPR, void_type_node, cond,
  			    expr, void_zero_node);
  	      finish_decl_cleanup (NULL_TREE, expr);
--- 3287,3298 ----
  
  	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
  	    {
! 	      expr = build_special_member_call (current_class_ref, 
! 						base_dtor_identifier,
! 						NULL_TREE,
! 						vbase,
! 						(LOOKUP_NORMAL 
! 						 | LOOKUP_NONVIRTUAL));
  	      expr = build (COND_EXPR, void_type_node, cond,
  			    expr, void_zero_node);
  	      finish_decl_cleanup (NULL_TREE, expr);
*************** push_base_cleanups ()
*** 3303,3312 ****
  	  || TREE_VIA_VIRTUAL (base_binfo))
  	continue;
  
!       expr = build_scoped_method_call (current_class_ref, base_binfo,
! 				       base_dtor_identifier,
! 				       NULL_TREE);
! 
        finish_decl_cleanup (NULL_TREE, expr);
      }
  
--- 3311,3320 ----
  	  || TREE_VIA_VIRTUAL (base_binfo))
  	continue;
  
!       expr = build_special_member_call (current_class_ref, 
! 					base_dtor_identifier,
! 					NULL_TREE, base_binfo, 
! 					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
        finish_decl_cleanup (NULL_TREE, expr);
      }
  
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.225
diff -c -p -r1.225 method.c
*** cp/method.c	23 Jul 2002 06:22:03 -0000	1.225
--- cp/method.c	1 Aug 2002 04:43:48 -0000
*************** do_build_assign_ref (fndecl)
*** 623,650 ****
      }
    else
      {
!       tree fields = TYPE_FIELDS (current_class_type);
!       int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
!       tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
        int cvquals = cp_type_quals (TREE_TYPE (parm));
        int i;
  
!       for (i = 0; i < n_bases; ++i)
  	{
! 	  /* We must deal with the binfo's directly as a direct base
! 	     might be inaccessible due to ambiguity.  */
! 	  tree binfo = TREE_VEC_ELT (binfos, i);
! 	  tree src = build_base_path (PLUS_EXPR, parm, binfo, 1);
! 	  tree dst = build_base_path (PLUS_EXPR, current_class_ref, binfo, 1);
  
! 	  tree expr = build_method_call (dst,
! 					 ansi_assopname (NOP_EXPR),
! 					 build_tree_list (NULL_TREE, src),
! 					 binfo,
! 					 LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
! 	  finish_expr_stmt (expr);
  	}
!       for (; fields; fields = TREE_CHAIN (fields))
  	{
  	  tree comp, init, t;
  	  tree field = fields;
--- 623,656 ----
      }
    else
      {
!       tree fields;
        int cvquals = cp_type_quals (TREE_TYPE (parm));
        int i;
  
!       /* Assign to each of thedirect base classes.  */
!       for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i)
  	{
! 	  tree binfo;
! 	  tree converted_parm;
  
! 	  binfo = BINFO_BASETYPE (TYPE_BINFO (current_class_type), i);
! 	  /* We must convert PARM directly to the base class
! 	     explicitly since the base class may be ambiguous.  */
! 	  converted_parm = build_base_path (PLUS_EXPR, parm, binfo, 1);
! 	  /* Call the base class assignment operator.  */
! 	  finish_expr_stmt 
! 	    (build_special_member_call (current_class_ref, 
! 					ansi_assopname (NOP_EXPR),
! 					build_tree_list (NULL_TREE, 
! 							 converted_parm),
! 					binfo,
! 					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
  	}
! 
!       /* Assign to each of the non-static data members.  */
!       for (fields = TYPE_FIELDS (current_class_type); 
! 	   fields; 
! 	   fields = TREE_CHAIN (fields))
  	{
  	  tree comp, init, t;
  	  tree field = fields;
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parse.y,v
retrieving revision 1.272
diff -c -p -r1.272 parse.y
*** cp/parse.y	22 Jul 2002 14:23:35 -0000	1.272
--- cp/parse.y	1 Aug 2002 04:43:48 -0000
*************** static tree parse_xref_tag (tree, tree, 
*** 131,136 ****
--- 131,137 ----
  static tree parse_handle_class_head (tree, tree, tree, int, int *);
  static void parse_decl_instantiation (tree, tree, tree);
  static int parse_begin_function_definition (tree, tree);
+ static tree parse_finish_call_expr (tree, tree, int);
  
  /* Cons up an empty parameter list.  */
  static inline tree
*************** do_id:
*** 1534,1542 ****
  
  template_id:
            PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
!                 { $$ = lookup_template_function ($3, $4); }
          | operator_name '<' do_id template_arg_list_opt template_close_bracket
!                 { $$ = lookup_template_function ($3, $4); }
  	;
  
  object_template_id:
--- 1535,1553 ----
  
  template_id:
            PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
!                 { 
! 		  tree template_name = $3;
! 		  if (TREE_CODE (template_name) == COMPONENT_REF)
! 		    template_name = TREE_OPERAND (template_name, 1);
! 		  $$ = lookup_template_function (template_name, $4); 
! 		}
          | operator_name '<' do_id template_arg_list_opt template_close_bracket
!                 { 
! 		  tree template_name = $3;
! 		  if (TREE_CODE (template_name) == COMPONENT_REF)
! 		    template_name = TREE_OPERAND (template_name, 1);
! 		  $$ = lookup_template_function (template_name, $4); 
! 		}
  	;
  
  object_template_id:
*************** primary:
*** 1637,1649 ****
             We could store lastiddecl in $1 to avoid another lookup,
             but that would result in many additional reduce/reduce conflicts. */
          | notype_unqualified_id '(' nonnull_exprlist ')'
!                { $$ = finish_call_expr ($1, $3, 1); }
          | notype_unqualified_id LEFT_RIGHT
!                { $$ = finish_call_expr ($1, NULL_TREE, 1); }
  	| primary '(' nonnull_exprlist ')'
!                { $$ = finish_call_expr ($1, $3, 0); }
  	| primary LEFT_RIGHT
!                { $$ = finish_call_expr ($1, NULL_TREE, 0); }
  	| VA_ARG '(' expr_no_commas ',' type_id ')'
  		{ $$ = build_x_va_arg ($3, groktypename ($5.t));
  		  check_for_new_type ("__builtin_va_arg", $5); }
--- 1648,1660 ----
             We could store lastiddecl in $1 to avoid another lookup,
             but that would result in many additional reduce/reduce conflicts. */
          | notype_unqualified_id '(' nonnull_exprlist ')'
!                { $$ = parse_finish_call_expr ($1, $3, 1); }
          | notype_unqualified_id LEFT_RIGHT
!                { $$ = parse_finish_call_expr ($1, NULL_TREE, 1); }
  	| primary '(' nonnull_exprlist ')'
!                { $$ = parse_finish_call_expr ($1, $3, 0); }
  	| primary LEFT_RIGHT
!                { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
  	| VA_ARG '(' expr_no_commas ',' type_id ')'
  		{ $$ = build_x_va_arg ($3, groktypename ($5.t));
  		  check_for_new_type ("__builtin_va_arg", $5); }
*************** primary:
*** 1705,1713 ****
  	| overqualified_id  %prec HYPERUNARY
  		{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
  	| overqualified_id '(' nonnull_exprlist ')'
!                 { $$ = finish_qualified_call_expr ($1, $3); }
  	| overqualified_id LEFT_RIGHT
! 		{ $$ = finish_qualified_call_expr ($1, NULL_TREE); }
          | object object_template_id %prec UNARY
                  {
  		  $$ = build_x_component_ref ($$, $2, NULL_TREE);
--- 1716,1724 ----
  	| overqualified_id  %prec HYPERUNARY
  		{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
  	| overqualified_id '(' nonnull_exprlist ')'
!                 { $$ = parse_finish_call_expr ($1, $3, 0); }
  	| overqualified_id LEFT_RIGHT
! 		{ $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
          | object object_template_id %prec UNARY
                  {
  		  $$ = build_x_component_ref ($$, $2, NULL_TREE);
*************** parse_begin_function_definition (tree sp
*** 4097,4102 ****
--- 4108,4255 ----
    
    split_specs_attrs (specs_attrs, &specs, &attrs);
    return begin_function_definition (specs, attrs, declarator);
+ }
+ 
+ /* Like finish_call_expr, but the name for FN has not yet been
+    resolved.  */
+ 
+ static tree
+ parse_finish_call_expr (tree fn, tree args, int koenig)
+ {
+   bool disallow_virtual;
+   tree template_args;
+   tree template_id;
+   tree f;
+ 
+   if (TREE_CODE (fn) == OFFSET_REF)
+     return build_offset_ref_call_from_tree (fn, args);
+ 
+   if (TREE_CODE (fn) == SCOPE_REF)
+     {
+       tree scope;
+       tree name;
+ 
+       scope = TREE_OPERAND (fn, 0);
+       name = TREE_OPERAND (fn, 1);
+ 
+       if (scope == error_mark_node || name == error_mark_node)
+ 	return error_mark_node;
+       if (!processing_template_decl)
+ 	{
+ 	  if (TREE_CODE (scope) == NAMESPACE_DECL)
+ 	    fn = lookup_namespace_name (scope, name);
+ 	  else
+ 	    {
+ 	      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ 		{
+ 		  template_id = name;
+ 		  template_args = TREE_OPERAND (name, 1);
+ 		  name = TREE_OPERAND (name, 0);
+ 		}
+ 	      else 
+ 		template_id = NULL_TREE;
+ 
+ 	      if (TREE_CODE (name) == OVERLOAD)
+ 		name = DECL_NAME (get_first_fn (name));
+ 	      fn = lookup_member (scope, name, /*protect=*/1, 
+ 				  /*prefer_type=*/0);
+ 	      if (BASELINK_P (fn) && template_id)
+ 		BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR,
+ 						    BASELINK_FUNCTIONS (fn),
+ 						    template_args);
+ 	      if (BASELINK_P (fn) 
+ 		  && current_class_type 
+ 		  && DERIVED_FROM_P (scope, current_class_type))
+ 		{
+ 		  scope = lookup_base (current_class_type, scope,
+ 				       ba_ignore | ba_quiet, NULL);
+ 		  if (scope)
+ 		    {
+ 		      BASELINK_ACCESS_BINFO (fn) = scope;
+ 		      BASELINK_BINFO (fn) 
+ 			= lookup_base (scope,
+ 				       BINFO_TYPE (BASELINK_BINFO (fn)),
+ 				       ba_ignore | ba_quiet,
+ 				       NULL);
+ 		    }
+ 		}
+ 	    }
+ 	}
+       disallow_virtual = true;
+     }
+   else
+     disallow_virtual = false;
+ 
+   if (koenig && TREE_CODE (fn) == IDENTIFIER_NODE)
+     {
+       /* Do the Koenig lookup.  */
+       fn = do_identifier (fn, 2, args);
+       /* If name lookup didn't find any matching declarations, we've
+ 	 got an unbound identifier.  */
+       if (TREE_CODE (fn) == IDENTIFIER_NODE)
+ 	{
+ 	  /* For some reason, do_identifier does not resolve
+ 	     conversion operator names if the only matches would be
+ 	     template conversion operators.  So, we do it here.  */
+ 	  if (IDENTIFIER_TYPENAME_P (fn) && current_class_type)
+ 	    {
+ 	      f = lookup_member (current_class_type, fn,
+ 				 /*protect=*/1, /*want_type=*/0);
+ 	      if (f)
+ 		return finish_call_expr (f, args,
+ 					 /*disallow_virtual=*/false);
+ 	    }
+ 	  /* If the name still could not be resolved, then the program
+ 	     is ill-formed.  */
+ 	  if (TREE_CODE (fn) == IDENTIFIER_NODE)
+ 	    {
+ 	      unqualified_name_lookup_error (fn);
+ 	      return error_mark_node;
+ 	    }
+ 	}
+       else if (TREE_CODE (fn) == FUNCTION_DECL
+ 	       || DECL_FUNCTION_TEMPLATE_P (fn)
+ 	       || TREE_CODE (fn) == OVERLOAD)
+ 	{
+ 	  tree scope = DECL_CONTEXT (get_first_fn (fn));
+ 	  if (scope && TYPE_P (scope))
+ 	    {
+ 	      tree access_scope;
+ 
+ 	      if (DERIVED_FROM_P (scope, current_class_type)
+ 		  && current_class_ref)
+ 		return finish_object_call_expr (fn,
+ 						current_class_ref,
+ 						args);
+ 
+ 	      access_scope = current_class_type;
+ 	      while (!DERIVED_FROM_P (scope, access_scope))
+ 		{
+ 		  access_scope = TYPE_CONTEXT (access_scope);
+ 		  while (DECL_P (access_scope))
+ 		    access_scope = DECL_CONTEXT (access_scope);
+ 		}
+ 	      
+ 	      fn = build_baselink (NULL_TREE,
+ 				   TYPE_BINFO (access_scope),
+ 				   fn,
+ 				   /*optype=*/NULL_TREE);
+ 	    }
+ 	}
+     }
+ 
+   if (TREE_CODE (fn) == COMPONENT_REF)
+     /* If the parser sees `(x->y)(bar)' we get here because the
+        parentheses confuse the parser.  Treat this like 
+        `x->y(bar)'.  */
+     return finish_object_call_expr (TREE_OPERAND (fn, 1),
+ 				    TREE_OPERAND (fn, 0),
+ 				    args);
+ 
+   if (processing_template_decl)
+     return build_nt (CALL_EXPR, fn, args, NULL_TREE);
+ 
+   return build_call_from_tree (fn, args, disallow_virtual);
  }
  
  #include "gt-cp-parse.h"
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.605
diff -c -p -r1.605 pt.c
*** cp/pt.c	26 Jul 2002 20:10:42 -0000	1.605
--- cp/pt.c	1 Aug 2002 04:43:50 -0000
*************** add_pending_template (d)
*** 3814,3822 ****
  }
  
  
! /* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS (which
!    may be either a _DECL or an overloaded function or an
!    IDENTIFIER_NODE), and ARGLIST.  */
  
  tree
  lookup_template_function (fns, arglist)
--- 3814,3822 ----
  }
  
  
! /* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS and
!    ARGLIST.  Valid choices for FNS are given in the cp-tree.def
!    documentation for TEMPLATE_ID_EXPR.  */
  
  tree
  lookup_template_function (fns, arglist)
*************** lookup_template_function (fns, arglist)
*** 3824,3843 ****
  {
    tree type;
  
    if (fns == NULL_TREE)
      {
        error ("non-template used as template");
        return error_mark_node;
      }
  
    type = TREE_TYPE (fns);
    if (TREE_CODE (fns) == OVERLOAD || !type)
      type = unknown_type_node;
! 
!   if (processing_template_decl)
!     return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);  
!   else
!     return build (TEMPLATE_ID_EXPR, type, fns, arglist);
  }
  
  /* Within the scope of a template class S<T>, the name S gets bound
--- 3824,3849 ----
  {
    tree type;
  
+   if (fns == error_mark_node || arglist == error_mark_node)
+     return error_mark_node;
+ 
    if (fns == NULL_TREE)
      {
        error ("non-template used as template");
        return error_mark_node;
      }
  
+   my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
+ 		      || TREE_CODE (fns) == OVERLOAD
+ 		      || TREE_CODE (fns) == IDENTIFIER_NODE
+ 		      || TREE_CODE (fns) == LOOKUP_EXPR,
+ 		      20020730);
+ 
    type = TREE_TYPE (fns);
    if (TREE_CODE (fns) == OVERLOAD || !type)
      type = unknown_type_node;
!   
!   return build (TEMPLATE_ID_EXPR, type, fns, arglist);
  }
  
  /* Within the scope of a template class S<T>, the name S gets bound
*************** type_unification_real (tparms, targs, xp
*** 8012,8019 ****
    my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
    my_friendly_assert (xparms == NULL_TREE 
  		      || TREE_CODE (xparms) == TREE_LIST, 290);
!   /* ARGS could be NULL (via a call from parse.y to
!      build_x_function_call).  */
    if (xargs)
      my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
    my_friendly_assert (ntparms > 0, 292);
--- 8018,8024 ----
    my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
    my_friendly_assert (xparms == NULL_TREE 
  		      || TREE_CODE (xparms) == TREE_LIST, 290);
!   /* ARGS could be NULL.  */
    if (xargs)
      my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
    my_friendly_assert (ntparms > 0, 292);
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.232
diff -c -p -r1.232 search.c
*** cp/search.c	23 Jul 2002 06:22:04 -0000	1.232
--- cp/search.c	1 Aug 2002 04:43:50 -0000
*************** lookup_base (t, base, access, kind_ptr)
*** 310,315 ****
--- 310,316 ----
       base_kind *kind_ptr;
  {
    tree binfo = NULL;		/* The binfo we've found so far. */
+   tree t_binfo = NULL;
    base_kind bk;
    
    if (t == error_mark_node || base == error_mark_node)
*************** lookup_base (t, base, access, kind_ptr)
*** 318,330 ****
  	*kind_ptr = bk_not_base;
        return error_mark_node;
      }
!   my_friendly_assert (TYPE_P (t) && TYPE_P (base), 20011127);
    
    /* Ensure that the types are instantiated.  */
    t = complete_type (TYPE_MAIN_VARIANT (t));
    base = complete_type (TYPE_MAIN_VARIANT (base));
    
!   bk = lookup_base_r (TYPE_BINFO (t), base, access & ~ba_quiet,
  		      0, 0, 0, &binfo);
  
    switch (bk)
--- 319,339 ----
  	*kind_ptr = bk_not_base;
        return error_mark_node;
      }
!   my_friendly_assert (TYPE_P (base), 20011127);
    
+   if (!TYPE_P (t))
+     {
+       t_binfo = t;
+       t = BINFO_TYPE (t);
+     }
+   else 
+     t_binfo = TYPE_BINFO (t);
+ 
    /* Ensure that the types are instantiated.  */
    t = complete_type (TYPE_MAIN_VARIANT (t));
    base = complete_type (TYPE_MAIN_VARIANT (base));
    
!   bk = lookup_base_r (t_binfo, base, access & ~ba_quiet,
  		      0, 0, 0, &binfo);
  
    switch (bk)
*************** lookup_field_r (binfo, data)
*** 1361,1366 ****
--- 1370,1401 ----
    return NULL_TREE;
  }
  
+ /* Return a "baselink" which BASELINK_BINFO, BASELINK_ACCESS_BINFO,
+    BASELINK_FUNCTIONS, and BASELINK_OPTYPE set to BINFO, ACCESS_BINFO,
+    FUNCTIONS, and OPTYPE respectively.  */
+ 
+ tree
+ build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
+ {
+   tree baselink;
+ 
+   my_friendly_assert (TREE_CODE (functions) == FUNCTION_DECL
+ 		      || TREE_CODE (functions) == TEMPLATE_DECL
+ 		      || TREE_CODE (functions) == TEMPLATE_ID_EXPR
+ 		      || TREE_CODE (functions) == OVERLOAD,
+ 		      20020730);
+   my_friendly_assert (!optype || TYPE_P (optype), 20020730);
+ 
+   baselink = build_tree_list (NULL_TREE, NULL_TREE);
+   SET_BASELINK_P (baselink);
+   BASELINK_BINFO (baselink) = binfo;
+   BASELINK_ACCESS_BINFO (baselink) = access_binfo;
+   BASELINK_FUNCTIONS (baselink) = functions;
+   BASELINK_OPTYPE (baselink) = optype;
+ 
+   return baselink;
+ }
+ 
  /* Look for a member named NAME in an inheritance lattice dominated by
     XBASETYPE.  If PROTECT is 0 or two, we do not check access.  If it is
     1, we enforce accessibility.  If PROTECT is zero, then, for an
*************** lookup_member (xbasetype, name, protect,
*** 1470,1488 ****
  						TREE_TYPE (rval)));
  
    if (rval && is_overloaded_fn (rval)) 
!     {
!       /* Note that the binfo we put in the baselink is the binfo where
! 	 we found the functions, which we need for overload
! 	 resolution, but which should not be passed to enforce_access;
! 	 rather, enforce_access wants a binfo which refers to the
! 	 scope in which we started looking for the function.  This
! 	 will generally be the binfo passed into this function as
! 	 xbasetype.  */
! 
!       rval = tree_cons (rval_binfo, rval, NULL_TREE);
!       SET_BASELINK_P (rval);
!     }
! 
    return rval;
  }
  
--- 1505,1513 ----
  						TREE_TYPE (rval)));
  
    if (rval && is_overloaded_fn (rval)) 
!     rval = build_baselink (rval_binfo, basetype_path, rval,
! 			   (IDENTIFIER_TYPENAME_P (name)
! 			   ? TREE_TYPE (name): NULL_TREE));
    return rval;
  }
  
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.269
diff -c -p -r1.269 semantics.c
*** cp/semantics.c	23 Jul 2002 13:54:05 -0000	1.269
--- cp/semantics.c	1 Aug 2002 04:43:51 -0000
*************** finish_stmt_expr (rtl_expr)
*** 1242,1273 ****
    return result;
  }
  
! /* Finish a call to FN with ARGS.  Returns a representation of the
!    call.  */
  
  tree 
! finish_call_expr (fn, args, koenig)
!      tree fn;
!      tree args;
!      int koenig;
  {
!   tree result;
  
!   if (koenig)
      {
!       if (TREE_CODE (fn) == BIT_NOT_EXPR)
! 	fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0));
!       else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
! 	fn = do_identifier (fn, 2, args);
!     }
!   result = build_x_function_call (fn, args, current_class_ref);
! 
!   if (TREE_CODE (result) == CALL_EXPR
!       && (! TREE_TYPE (result)
!           || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
!     result = require_complete_type (result);
  
!   return result;
  }
  
  /* Finish a call to a postfix increment or decrement or EXPR.  (Which
--- 1242,1327 ----
    return result;
  }
  
! /* Generate an expression for `FN (ARGS)'.
! 
!    If DISALLOW_VIRTUAL is true, the call to FN will be not generated
!    as a virtual call, even if FN is virtual.  (This flag is set when
!    encountering an expression where the function name is explicitly
!    qualified.  For example a call to `X::f' never generates a virtual
!    call.)
! 
!    Returns code for the call.  */
  
  tree 
! finish_call_expr (tree fn, tree args, bool disallow_virtual)
  {
!   if (fn == error_mark_node || args == error_mark_node)
!     return error_mark_node;
! 
!   if (processing_template_decl)
!     return build_nt (CALL_EXPR, fn, args, NULL_TREE);
! 
!   /* ARGS should be a list of arguments.  */
!   my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
! 		      20020712);
  
!   if (BASELINK_P (fn))
      {
!       tree object;
  
!       /* A call to a member function.  From [over.call.func]:
! 
! 	   If the keyword this is in scope and refers to the class of
! 	   that member function, or a derived class thereof, then the
! 	   function call is transformed into a qualified function call
! 	   using (*this) as the postfix-expression to the left of the
! 	   . operator.... [Otherwise] a contrived object of type T
! 	   becomes the implied object argument.  
! 
!         This paragraph is unclear about this situation:
! 
! 	  struct A { void f(); };
! 	  struct B : public A {};
! 	  struct C : public A { void g() { B::f(); }};
! 
! 	In particular, for `B::f', this paragraph does not make clear
! 	whether "the class of that member function" refers to `A' or 
! 	to `B'.  We believe it refers to `B'.  */
!       if (current_class_type 
! 	  && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
! 			     current_class_type)
! 	  && current_class_ref)
! 	object = current_class_ref;
!       else
! 	{
! 	  tree representative_fn;
! 
! 	  representative_fn = BASELINK_FUNCTIONS (fn);
! 	  if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR)
! 	    representative_fn = TREE_OPERAND (representative_fn, 0);
! 	  representative_fn = get_first_fn (representative_fn);
! 	  object = build_dummy_object (DECL_CONTEXT (representative_fn));
! 	}
! 
!       return build_new_method_call (object, fn, args, NULL_TREE,
! 				    (disallow_virtual 
! 				     ? LOOKUP_NONVIRTUAL : 0));
!     }
!   else if (is_overloaded_fn (fn))
!     /* A call to a namespace-scope function.  */
!     return build_new_function_call (fn, args);
!   else if (CLASS_TYPE_P (TREE_TYPE (fn)))
!     {
!       /* If the "function" is really an object of class type, it might
! 	 have an overloaded `operator ()'.  */
!       tree result;
!       result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
!       if (result)
! 	return result;
!     }
! 
!   /* A call where the function is unknown.  */
!   return build_function_call (fn, args);
  }
  
  /* Finish a call to a postfix increment or decrement or EXPR.  (Which
*************** finish_object_call_expr (fn, object, arg
*** 1327,1340 ****
       tree object;
       tree args;
  {
- #if 0
-   /* This is a future direction of this code, but because
-      build_x_function_call cannot always undo what is done in
-      build_component_ref entirely yet, we cannot do this.  */
- 
-   tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
-   return finish_call_expr (real_fn, args);
- #else
    if (DECL_DECLARES_TYPE_P (fn))
      {
        if (processing_template_decl)
--- 1381,1386 ----
*************** finish_object_call_expr (fn, object, arg
*** 1353,1361 ****
  	  return error_mark_node;
  	}
      }
! 
    return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
- #endif
  }
  
  /* Finish a qualified member function call using OBJECT and ARGS as
--- 1399,1406 ----
  	  return error_mark_node;
  	}
      }
!   
    return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
  }
  
  /* Finish a qualified member function call using OBJECT and ARGS as
*************** finish_pseudo_destructor_call_expr (obje
*** 1394,1415 ****
      error ("`%E' is not of type `%T'", object, destructor);
  
    return cp_convert (void_type_node, object);
- }
- 
- /* Finish a call to a globally qualified member function FN using
-    ARGS.  Returns an expression for the call.  */
- 
- tree 
- finish_qualified_call_expr (fn, args)
-      tree fn;
-      tree args;
- {
-   if (processing_template_decl)
-     return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
-   else
-     return build_member_call (TREE_OPERAND (fn, 0),
- 			      TREE_OPERAND (fn, 1),
- 			      args);
  }
  
  /* Finish an expression of the form CODE EXPR.  */
--- 1439,1444 ----
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.413
diff -c -p -r1.413 typeck.c
*** cp/typeck.c	26 Jul 2002 20:10:43 -0000	1.413
--- cp/typeck.c	1 Aug 2002 04:43:52 -0000
*************** build_array_ref (array, idx)
*** 2455,2763 ****
    }
  }
  
- /* Build a function call to function FUNCTION with parameters PARAMS.
-    PARAMS is a list--a chain of TREE_LIST nodes--in which the
-    TREE_VALUE of each node is a parameter-expression.  The PARAMS do
-    not include any object pointer that may be required.  FUNCTION's
-    data type may be a function type or a pointer-to-function.
- 
-    For C++: If FUNCTION's data type is a TREE_LIST, then the tree list
-    is the list of possible methods that FUNCTION could conceivably
-    be.  If the list of methods comes from a class, then it will be
-    a list of lists (where each element is associated with the class
-    that produced it), otherwise it will be a simple list (for
-    functions overloaded in global scope).
- 
-    In the first case, TREE_VALUE (function) is the head of one of those
-    lists, and TREE_PURPOSE is the name of the function.
- 
-    In the second case, TREE_PURPOSE (function) is the function's
-    name directly.
- 
-    DECL is the class instance variable, usually CURRENT_CLASS_REF.
- 
-    When calling a TEMPLATE_DECL, we don't require a complete return
-    type.  */
- 
- tree
- build_x_function_call (function, params, decl)
-      tree function, params, decl;
- {
-   tree type;
-   tree template_id = NULL_TREE;
-   int is_method;
- 
-   if (function == error_mark_node)
-     return error_mark_node;
- 
-   if (processing_template_decl)
-     return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
- 
-   /* Save explicit template arguments if found */
-   if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
-     {
-       template_id = function;
-       function = TREE_OPERAND (function, 0);
-     }
- 
-   type = TREE_TYPE (function);
- 
-   if (TREE_CODE (type) == OFFSET_TYPE
-       && TREE_TYPE (type) == unknown_type_node
-       && TREE_CODE (function) == TREE_LIST
-       && TREE_CHAIN (function) == NULL_TREE)
-     {
-       /* Undo (Foo:bar)()...  */
-       type = TYPE_OFFSET_BASETYPE (type);
-       function = TREE_VALUE (function);
-       my_friendly_assert (TREE_CODE (function) == TREE_LIST, 999);
-       my_friendly_assert (TREE_CHAIN (function) == NULL_TREE, 999);
-       function = TREE_VALUE (function);
-       if (TREE_CODE (function) == OVERLOAD)
- 	function = OVL_FUNCTION (function);
-       my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 999);
-       function = DECL_NAME (function);
-       return build_method_call (decl, function, params,
- 				TYPE_BINFO (type), LOOKUP_NORMAL);
-     }
-     
-   if (TREE_CODE (function) == OFFSET_REF
-       && TREE_CODE (type) != METHOD_TYPE)
-     function = resolve_offset_ref (function);
- 
-   if ((TREE_CODE (function) == FUNCTION_DECL
-        && DECL_STATIC_FUNCTION_P (function))
-       || (DECL_FUNCTION_TEMPLATE_P (function)
- 	  && DECL_STATIC_FUNCTION_P (DECL_TEMPLATE_RESULT (function))))
-       return build_member_call (DECL_CONTEXT (function), 
- 				template_id 
- 				? template_id : DECL_NAME (function), 
- 				params);
- 
-   is_method = ((TREE_CODE (function) == TREE_LIST
- 		&& current_class_type != NULL_TREE
- 		&& (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function))
- 		    == function))
- 	       || (TREE_CODE (function) == OVERLOAD
- 		   && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (function)))
- 	       || TREE_CODE (function) == IDENTIFIER_NODE
- 	       || TREE_CODE (type) == METHOD_TYPE
- 	       || TYPE_PTRMEMFUNC_P (type));
- 
-   /* A friend template.  Make it look like a toplevel declaration.  */
-   if (! is_method && TREE_CODE (function) == TEMPLATE_DECL)
-     function = ovl_cons (function, NULL_TREE);
- 
-   /* Handle methods, friends, and overloaded functions, respectively.  */
-   if (is_method)
-     {
-       tree basetype = NULL_TREE;
- 
-       if (TREE_CODE (function) == OVERLOAD)
- 	function = OVL_CURRENT (function);
- 
-       if (TREE_CODE (function) == FUNCTION_DECL
- 	  || DECL_FUNCTION_TEMPLATE_P (function))
- 	{
- 	  basetype = DECL_CONTEXT (function);
- 
- 	  if (DECL_NAME (function))
- 	    function = DECL_NAME (function);
- 	  else
- 	    function = TYPE_IDENTIFIER (DECL_CONTEXT (function));
- 	}
-       else if (TREE_CODE (function) == TREE_LIST)
- 	{
- 	  my_friendly_assert (TREE_CODE (TREE_VALUE (function))
- 			      == FUNCTION_DECL, 312);
- 	  basetype = DECL_CONTEXT (TREE_VALUE (function));
- 	  function = TREE_PURPOSE (function);
- 	}
-       else if (TREE_CODE (function) != IDENTIFIER_NODE)
- 	{
- 	  if (TREE_CODE (function) == OFFSET_REF)
- 	    {
- 	      if (TREE_OPERAND (function, 0))
- 		decl = TREE_OPERAND (function, 0);
- 	    }
- 	  /* Call via a pointer to member function.  */
- 	  if (decl == NULL_TREE)
- 	    {
- 	      error ("pointer to member function called, but not in class scope");
- 	      return error_mark_node;
- 	    }
- 	  /* What other type of POINTER_TYPE could this be? */
- 	  if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE
- 	      && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (function))
- 	      && TREE_CODE (function) != OFFSET_REF)
- 	    function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE,
- 			      function);
- 	  goto do_x_function;
- 	}
- 
-       /* this is an abbreviated method call.
-          must go through here in case it is a virtual function.
- 	 @@ Perhaps this could be optimized.  */
- 
-       if (basetype && (! current_class_type
- 		       || ! DERIVED_FROM_P (basetype, current_class_type)))
- 	return build_member_call (basetype, function, params);
- 
-       if (decl == NULL_TREE)
- 	{
- 	  if (current_class_type == NULL_TREE)
- 	    {
- 	      error ("object missing in call to method `%D'", function);
- 	      return error_mark_node;
- 	    }
- 	  /* Yow: call from a static member function.  */
- 	  decl = build_dummy_object (current_class_type);
- 	}
- 
-       /* Put back explicit template arguments, if any.  */
-       if (template_id)
-         function = template_id;
-       return build_method_call (decl, function, params,
- 				NULL_TREE, LOOKUP_NORMAL);
-     }
-   else if (TREE_CODE (function) == COMPONENT_REF
- 	   && type == unknown_type_node)
-     {
-       /* Undo what we did in build_component_ref.  */
-       decl = TREE_OPERAND (function, 0);
-       function = TREE_OPERAND (function, 1);
- 
-       if (TREE_CODE (function) == OVERLOAD
-  	  && TREE_TYPE (function) != unknown_type_node)
-  	/* It was a conversion operator. We can't use DECL_NAME, as
-  	   that might refer to a templated function.  */
- 	function = mangle_conv_op_name_for_type (TREE_TYPE (function));
-       else if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
- 	{
- 	  my_friendly_assert (!template_id, 20011228);
- 
- 	  template_id = function;
- 	}
-       else
- 	{
- 	  function = DECL_NAME (OVL_CURRENT (function));
- 
- 	  if (template_id)
- 	    {
- 	      TREE_OPERAND (template_id, 0) = function;
- 	      function = template_id;
- 	    }
- 	}
- 
-       return build_method_call (decl, function, params,
- 				NULL_TREE, LOOKUP_NORMAL);
-     }
-   else if (really_overloaded_fn (function))
-     {
-       if (OVL_FUNCTION (function) == NULL_TREE)
- 	{
- 	  error ("function `%D' declared overloaded, but no definitions appear with which to resolve it?!?",
- 		    TREE_PURPOSE (function));
- 	  return error_mark_node;
- 	}
-       else
- 	{
- 	  /* Put back explicit template arguments, if any.  */
- 	  if (template_id)
- 	    function = template_id;
- 	  return build_new_function_call (function, params);
- 	}
-     }
-   else
-     /* Remove a potential OVERLOAD around it */
-     function = OVL_CURRENT (function);
- 
-  do_x_function:
-   if (TREE_CODE (function) == OFFSET_REF)
-     {
-       /* If the component is a data element (or a virtual function), we play
- 	 games here to make things work.  */
-       tree decl_addr;
- 
-       if (TREE_OPERAND (function, 0))
- 	decl = TREE_OPERAND (function, 0);
-       else
- 	decl = current_class_ref;
- 
-       decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
- 
-       /* Sigh.  OFFSET_REFs are being used for too many things.
- 	 They're being used both for -> and ->*, and we want to resolve
- 	 the -> cases here, but leave the ->*.  We could use
- 	 resolve_offset_ref for those, too, but it would call
-          get_member_function_from_ptrfunc and decl_addr wouldn't get
-          updated properly.  Nasty.  */
-       if (TREE_CODE (TREE_OPERAND (function, 1)) == FIELD_DECL)
- 	function = resolve_offset_ref (function);
-       else
- 	function = TREE_OPERAND (function, 1);
- 
-       function = get_member_function_from_ptrfunc (&decl_addr, function);
-       params = tree_cons (NULL_TREE, decl_addr, params);
-       return build_function_call (function, params);
-     }
- 
-   type = TREE_TYPE (function);
-   if (type != error_mark_node)
-     {
-       if (TREE_CODE (type) == REFERENCE_TYPE)
- 	type = TREE_TYPE (type);
- 
-       if (IS_AGGR_TYPE (type))
- 	return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE);
-     }
- 
-   if (is_method)
-     {
-       tree fntype = TREE_TYPE (function);
-       tree ctypeptr = NULL_TREE;
- 
-       /* Explicitly named method?  */
-       if (TREE_CODE (function) == FUNCTION_DECL)
- 	ctypeptr = build_pointer_type (DECL_CLASS_CONTEXT (function));
-       /* Expression with ptr-to-method type?  It could either be a plain
- 	 usage, or it might be a case where the ptr-to-method is being
- 	 passed in as an argument.  */
-       else if (TYPE_PTRMEMFUNC_P (fntype))
- 	{
- 	  tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE
- 					   (TYPE_PTRMEMFUNC_FN_TYPE (fntype)));
- 	  ctypeptr = build_pointer_type (rec);
- 	}
-       /* Unexpected node type?  */
-       else
- 	abort ();
-       if (decl == NULL_TREE)
- 	{
- 	  if (current_function_decl
- 	      && DECL_STATIC_FUNCTION_P (current_function_decl))
- 	    error ("invalid call to member function needing `this' in static member function scope");
- 	  else
- 	    error ("pointer to member function called, but not in class scope");
- 	  return error_mark_node;
- 	}
-       if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
- 	  && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)))
- 	{
- 	  tree binfo = lookup_base (TREE_TYPE (decl), TREE_TYPE (ctypeptr),
- 				    ba_check, NULL);
- 	  
- 	  decl = build_unary_op (ADDR_EXPR, decl, 0);
- 	  decl = build_base_path (PLUS_EXPR, decl, binfo, 1);
- 	}
-       else
- 	decl = build_c_cast (ctypeptr, decl);
-       params = tree_cons (NULL_TREE, decl, params);
-     }
- 
-   return build_function_call (function, params);
- }
- 
  /* Resolve a pointer to member function.  INSTANCE is the object
     instance to use, if the member points to a virtual member.
  
--- 2455,2460 ----
*************** build_static_cast (type, expr)
*** 4928,4934 ****
  				   LOOKUP_COMPLAIN, NULL_TREE)));
  
    if (IS_AGGR_TYPE (type))
!     return build_cplus_new (type, (build_method_call
  				   (NULL_TREE, complete_ctor_identifier, 
  				    build_tree_list (NULL_TREE, expr),
  				    TYPE_BINFO (type), LOOKUP_NORMAL)));
--- 4625,4631 ----
  				   LOOKUP_COMPLAIN, NULL_TREE)));
  
    if (IS_AGGR_TYPE (type))
!     return build_cplus_new (type, (build_special_member_call
  				   (NULL_TREE, complete_ctor_identifier, 
  				    build_tree_list (NULL_TREE, expr),
  				    TYPE_BINFO (type), LOOKUP_NORMAL)));
*************** build_modify_expr (lhs, modifycode, rhs)
*** 5431,5439 ****
  	/* Do the default thing */;
        else
  	{
! 	  result = build_method_call (lhs, complete_ctor_identifier,
! 				      build_tree_list (NULL_TREE, rhs),
! 				      TYPE_BINFO (lhstype), LOOKUP_NORMAL);
  	  if (result == NULL_TREE)
  	    return error_mark_node;
  	  return result;
--- 5128,5137 ----
  	/* Do the default thing */;
        else
  	{
! 	  result = build_special_member_call (lhs, complete_ctor_identifier,
! 					      build_tree_list (NULL_TREE, rhs),
! 					      TYPE_BINFO (lhstype), 
! 					      LOOKUP_NORMAL);
  	  if (result == NULL_TREE)
  	    return error_mark_node;
  	  return result;
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.124
diff -c -p -r1.124 typeck2.c
*** cp/typeck2.c	2 Jul 2002 16:06:49 -0000	1.124
--- cp/typeck2.c	1 Aug 2002 04:43:52 -0000
*************** build_functional_cast (exp, parms)
*** 1309,1316 ****
        return get_target_expr (exp);
      }
  
!   exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms,
! 			   TYPE_BINFO (type), LOOKUP_NORMAL);
  
    if (exp == error_mark_node)
      return error_mark_node;
--- 1309,1316 ----
        return get_target_expr (exp);
      }
  
!   exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
! 				   TYPE_BINFO (type), LOOKUP_NORMAL);
  
    if (exp == error_mark_node)
      return error_mark_node;
Index: testsuite/g++.dg/inherit/operator1.C
===================================================================
RCS file: testsuite/g++.dg/inherit/operator1.C
diff -N testsuite/g++.dg/inherit/operator1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/inherit/operator1.C	1 Aug 2002 04:43:55 -0000
***************
*** 0 ****
--- 1,34 ----
+ // Test that conversions to base classes happen when calling
+ // operators.
+ 
+ // { dg-do run }
+ 
+ extern "C" void abort ();
+ 
+ struct B1;
+ struct B2;
+ 
+ B2* p;
+ B1* p2;
+ 
+ struct B1 {
+   virtual void f () {}
+ };
+ 
+ struct B2 {
+   int i;
+   bool operator!() { if (this != p) abort (); return true; }
+   operator void*() { if (this != p) abort (); return this; }
+ };
+ 
+ struct B3 : public B1, public B2 {
+ };
+ 
+ int main () {
+   B3 b;
+   p = (B2*) &b;
+   p2 = (B1*) &b;
+   bool b1 = b;
+   bool b2 = !b;
+ }
+ 
Index: testsuite/g++.dg/lookup/disamb1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/lookup/disamb1.C,v
retrieving revision 1.1
diff -c -p -r1.1 disamb1.C
*** testsuite/g++.dg/lookup/disamb1.C	6 Apr 2002 16:15:19 -0000	1.1
--- testsuite/g++.dg/lookup/disamb1.C	1 Aug 2002 04:43:55 -0000
***************
*** 1,5 ****
  // PR c++/525
! // Bug: With -pedantic, we weren't converting this to D1* for the call.
  
  struct A
  {
--- 1,5 ----
  // PR c++/525
! // Bug: With -pedantic, we weren't converting this to B1* for the call.
  
  struct A
  {
Index: testsuite/g++.dg/other/error1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/other/error1.C,v
retrieving revision 1.1
diff -c -p -r1.1 error1.C
*** testsuite/g++.dg/other/error1.C	19 Dec 2001 11:52:59 -0000	1.1
--- testsuite/g++.dg/other/error1.C	1 Aug 2002 04:43:55 -0000
***************
*** 1,6 ****
  // { dg-do compile }
  
! // Copyright (C) 2001 Free Software Foundation, Inc.
  // Contributed by Nathan Sidwell 18 Dec 2001 <nathan@nathan@codesourcery.com>
  
  // PR 90, stupid error message `(this + 160)'
--- 1,6 ----
  // { dg-do compile }
  
! // Copyright (C) 2001, 2002 Free Software Foundation, Inc.
  // Contributed by Nathan Sidwell 18 Dec 2001 <nathan@nathan@codesourcery.com>
  
  // PR 90, stupid error message `(this + 160)'
*************** class foo {
*** 10,15 ****
    int fudge[40];
    int bar [40];
    inline int access(int i) {
!     return bar(i);  // { dg-error "`this->foo::bar' cannot" "" }
    }
  };
--- 10,15 ----
    int fudge[40];
    int bar [40];
    inline int access(int i) {
!     return bar(i);  // { dg-error "call to non-function `foo::bar'" "" }
    }
  };
Index: testsuite/g++.dg/template/conv4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/conv4.C,v
retrieving revision 1.1
diff -c -p -r1.1 conv4.C
*** testsuite/g++.dg/template/conv4.C	16 Mar 2002 18:30:16 -0000	1.1
--- testsuite/g++.dg/template/conv4.C	1 Aug 2002 04:43:55 -0000
***************
*** 1,6 ****
  // { dg-do compile }
  
! // Copyright (C) 2001 Free Software Foundation, Inc.
  // Contributed by Nathan Sidwell 29 Dec 2001 <nathan@codesourcery.com>
  
  // PR 4361. Template conversion operators were not overloaded.
--- 1,6 ----
  // { dg-do compile }
  
! // Copyright (C) 2001, 2002 Free Software Foundation, Inc.
  // Contributed by Nathan Sidwell 29 Dec 2001 <nathan@codesourcery.com>
  
  // PR 4361. Template conversion operators were not overloaded.
*************** struct D
*** 21,27 ****
  {
    int Foo ()
    {
!     return operator int (); // { dg-error "no matching function" "" }
    }
  };
  
--- 21,27 ----
  {
    int Foo ()
    {
!     return operator int (); // { dg-error "not defined" "" }
    }
  };
  


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