This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

(C++) patch to overhaul method reference handling


Applied.  In push_class_decls, we store one function out of however many
there are with the same name in the IDENTIFIER_CLASS_VALUE for that name.
Previously, we would sometimes use that function directly instead of doing
overload resolution; this patch causes us to build up a COMPONENT_REF
immediately, and fixes the code for doing that.

Fixes g++.bugs/900213_03.C, g++.other/pmf2.C, g++.robertl/eb131.C.

1998-10-19  Jason Merrill  <jason@yorick.cygnus.com>

	Revamp references to member functions.
	* method.c (hack_identifier): Call build_component_ref for a
	reference to a member function.
	* typeck.c (build_component_ref): Only return a single function 
	if it's static.  Otherwise, return a COMPONENT_REF.
	(build_x_function_call): Handle a COMPONENT_REF.
	(build_unary_op): Handle all unknown-type things.
	* decl2.c (arg_assoc): Handle COMPONENT_REF.
	* class.c (instantiate_type): Complain if the function we get is a
	nonstatic member function.  Remove code for finding "compatible"
	functions.
	* pt.c (tsubst_copy): Handle NOP_EXPR.
	* tree.c (build_dummy_object): New fn.
	(maybe_dummy_object): New fn.
	(is_dummy_object): New fn.
	* cp-tree.h: Declare them.
	* cvt.c (cp_convert_to_pointer): Use maybe_dummy_object.
	* error.c (dump_expr, case OFFSET_REF): Use is_dummy_object.
	* init.c (build_member_call): Use maybe_dummy_object and
	is_dummy_object.
	(build_offset_ref): Use maybe_dummy_object.
	(resolve_offset_ref): Use is_dummy_object.
	* typeck.c (build_x_function_call): Call build_dummy_object.
	(unary_complex_lvalue): Call is_dummy_object.

	* typeck.c (build_component_addr): Make sure field is a field.

	* call.c (build_new_op): Delete obsolete code.

Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.113
diff -c -p -r1.113 call.c
*** call.c	1998/10/09 00:10:54	1.113
--- call.c	1998/10/20 03:02:56
*************** build_new_op (code, flags, arg1, arg2, a
*** 2513,2585 ****
      {
      case NEW_EXPR:
      case VEC_NEW_EXPR:
-       {
- 	tree rval;
- 
- 	arglist = scratch_tree_cons (NULL_TREE, arg2, arg3);
- 	if (flags & LOOKUP_GLOBAL)
- 	  return build_new_function_call
- 	    (lookup_function_nonclass (fnname, arglist), arglist);
- 
- 	/* FIXME */
- 	rval = build_method_call
- 	  (build_indirect_ref (build1 (NOP_EXPR, arg1, error_mark_node),
- 			       "new"),
- 	   fnname, arglist, NULL_TREE, flags);
- 	if (rval == error_mark_node)
- 	  /* User might declare fancy operator new, but invoke it
- 	     like standard one.  */
- 	  return rval;
- 
- 	TREE_TYPE (rval) = arg1;
- 	return rval;
-       }
- 
      case VEC_DELETE_EXPR:
      case DELETE_EXPR:
!       {
! 	tree rval;
! 
! 	if (flags & LOOKUP_GLOBAL)
! 	  {
! 	    arglist = build_scratch_list (NULL_TREE, arg1);
! 	    return build_new_function_call
! 	      (lookup_function_nonclass (fnname, arglist), arglist);
! 	  }    
! 
! 	arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2));
! 
! 	arg1 = TREE_TYPE (arg1);
! 
! 	/* This handles the case where we're trying to delete
! 	   X (*a)[10];
! 	   a=new X[5][10];
! 	   delete[] a; */
! 	   
! 	if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
! 	  {
! 	    /* Strip off the pointer and the array.  */
! 	    arg1 = TREE_TYPE (TREE_TYPE (arg1));
! 
! 	    while (TREE_CODE (arg1) == ARRAY_TYPE)
! 		arg1 = (TREE_TYPE (arg1));
! 
! 	    arg1 = build_pointer_type (arg1);
! 	  }
! 
! 	/* FIXME */
! 	rval = build_method_call
! 	  (build_indirect_ref (build1 (NOP_EXPR, arg1,
! 				       error_mark_node),
! 			       NULL_PTR),
! 	   fnname, arglist, NULL_TREE, flags);
! #if 0
! 	/* This can happen when operator delete is protected.  */
! 	my_friendly_assert (rval != error_mark_node, 250);
! 	TREE_TYPE (rval) = void_type_node;
! #endif
! 	return rval;
!       }
  
      case CALL_EXPR:
        return build_object_call (arg1, arg2);
--- 2513,2522 ----
      {
      case NEW_EXPR:
      case VEC_NEW_EXPR:
      case VEC_DELETE_EXPR:
      case DELETE_EXPR:
!       /* Use build_op_new_call and build_op_delete_call instead. */
!       my_friendly_abort (981018);
  
      case CALL_EXPR:
        return build_object_call (arg1, arg2);
*************** build_op_new_call (code, type, args, fla
*** 2898,2907 ****
    if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
        && (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
      {
!       tree dummy = build1 (NOP_EXPR, build_pointer_type (type),
! 			   error_mark_node);
!       dummy = build_indirect_ref (dummy, "new");
!       return build_method_call (dummy, fnname, args, NULL_TREE, flags);
      }
    else
      return build_new_function_call 
--- 2835,2842 ----
    if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
        && (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
      {
!       return build_method_call (build_dummy_object (type),
! 				fnname, args, NULL_TREE, flags);
      }
    else
      return build_new_function_call 
*************** build_new_method_call (instance, name, a
*** 3716,3723 ****
        && value_member (cand->fn, get_abstract_virtuals (basetype)))
      cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
    if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
!       && TREE_CODE (instance_ptr) == NOP_EXPR
!       && TREE_OPERAND (instance_ptr, 0) == error_mark_node)
      cp_error ("cannot call member function `%D' without object", cand->fn);
  
    if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
--- 3651,3657 ----
        && value_member (cand->fn, get_abstract_virtuals (basetype)))
      cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
    if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
!       && is_dummy_object (instance_ptr))
      cp_error ("cannot call member function `%D' without object", cand->fn);
  
    if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
Index: class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.96
diff -c -p -r1.96 class.c
*** class.c	1998/10/17 20:33:40	1.96
--- class.c	1998/10/20 03:02:56
*************** instantiate_type (lhstype, rhs, complain
*** 5045,5061 ****
  	    if (function == error_mark_node)
  	      return error_mark_node;
  	    my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
! 	    if (DECL_VINDEX (function))
! 	      {
! 		tree base = TREE_OPERAND (rhs, 0);
! 		tree base_ptr = build_unary_op (ADDR_EXPR, base, 0);
! 		if (base_ptr == error_mark_node)
! 		  return error_mark_node;
! 		base_ptr = convert_pointer_to (DECL_CONTEXT (function), base_ptr);
! 		if (base_ptr == error_mark_node)
! 		  return error_mark_node;
! 		return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
! 	      }
  	    mark_used (function);
  	    return function;
  	  }
--- 5045,5055 ----
  	    if (function == error_mark_node)
  	      return error_mark_node;
  	    my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
! 
! 	    if (! DECL_STATIC_FUNCTION_P (function))
! 	      cp_error ("reference to `%D' can only be used in a call",
! 			function);
! 
  	    mark_used (function);
  	    return function;
  	  }
*************** instantiate_type (lhstype, rhs, complain
*** 5293,5341 ****
  		elem = OVL_NEXT (elem);
  	  }
  
! 	/* No exact match found, look for a compatible method.  */
! 	for (baselink = rhs; baselink;
! 	     baselink = next_baselink (baselink))
! 	  {
! 	    elem = TREE_VALUE (baselink);
! 	    for (; elem; elem = OVL_NEXT (elem))
! 	      if (comp_target_types (lhstype, 
! 				     TREE_TYPE (OVL_CURRENT (elem)), 1) > 0)
! 		break;
! 	    if (elem)
! 	      {
! 		tree save_elem = OVL_CURRENT (elem);
! 		for (elem = OVL_NEXT (elem); elem; elem = OVL_NEXT (elem))
! 		  if (comp_target_types (lhstype, 
! 					 TREE_TYPE (OVL_CURRENT (elem)), 0) > 0)
! 		    break;
! 		if (elem)
! 		  {
! 		    if (complain)
! 		      error ("ambiguous overload for overloaded method requested");
! 		    return error_mark_node;
! 		  }
! 		mark_used (save_elem);
! 		return save_elem;
! 	      }
! 	    name = rhs;
! 	    while (TREE_CODE (name) == TREE_LIST)
! 	      name = TREE_VALUE (name);
! 	    name = DECL_NAME (OVL_CURRENT (name));
! #if 0
! 	    if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0)
! 	      {
! 		/* Try to instantiate from non-member functions.  */
! 		rhs = lookup_name_nonclass (name);
! 		if (rhs && TREE_CODE (rhs) == TREE_LIST)
! 		  {
! 		    /* This code seems to be missing a `return'.  */
! 		    my_friendly_abort (4);
! 		    instantiate_type (lhstype, rhs, complain);
! 		  }
! 	      }
! #endif
! 	  }
  	if (complain)
  	  cp_error ("no compatible member functions named `%D'", name);
  	return error_mark_node;
--- 5287,5297 ----
  		elem = OVL_NEXT (elem);
  	  }
  
! 	name = rhs;
! 	while (TREE_CODE (name) == TREE_LIST)
! 	  name = TREE_VALUE (name);
! 	name = DECL_NAME (OVL_CURRENT (name));
! 
  	if (complain)
  	  cp_error ("no compatible member functions named `%D'", name);
  	return error_mark_node;
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.155
diff -c -p -r1.155 cp-tree.h
*** cp-tree.h	1998/10/16 03:37:36	1.155
--- cp-tree.h	1998/10/20 03:02:56
*************** cp-tree.h				PROTO((tree, tree 
*** 3084,3089 ****
--- 3084,3092 ----
  extern tree no_linkage_check			PROTO((tree));
  extern void debug_binfo				PROTO((tree));
  extern void push_expression_obstack		PROTO((void));
+ extern tree build_dummy_object			PROTO((tree));
+ extern tree maybe_dummy_object			PROTO((tree, tree *));
+ extern int is_dummy_object			PROTO((tree));
  #define scratchalloc expralloc
  #define scratch_tree_cons expr_tree_cons
  #define build_scratch_list build_expr_list
Index: cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.36
diff -c -p -r1.36 cvt.c
*** cvt.c	1998/10/16 03:37:37	1.36
--- cvt.c	1998/10/20 03:02:56
*************** cp_convert_to_pointer (type, expr)
*** 107,127 ****
  	 functions.  */
        if (TYPE_PTRMEMFUNC_P (intype))
  	{
- 	  tree decl, basebinfo;
  	  tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
! 	  tree t = TYPE_METHOD_BASETYPE (fntype);
! 
! 	  if (current_class_type == 0
! 	      || get_base_distance (t, current_class_type, 0, &basebinfo)
! 	      == -1)
! 	    {
! 	      decl = build1 (NOP_EXPR, t, error_mark_node);
! 	    }
! 	  else if (current_class_ptr == 0)
! 	    decl = build1 (NOP_EXPR, t, error_mark_node);
! 	  else
! 	    decl = current_class_ref;
! 
  	  expr = build (OFFSET_REF, fntype, decl, expr);
  	}
  
--- 107,114 ----
  	 functions.  */
        if (TYPE_PTRMEMFUNC_P (intype))
  	{
  	  tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
! 	  tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
  	  expr = build (OFFSET_REF, fntype, decl, expr);
  	}
  
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.146
diff -c -p -r1.146 decl2.c
*** decl2.c	1998/10/18 09:21:17	1.146
--- decl2.c	1998/10/20 03:02:57
*************** arg_assoc (k, n)
*** 4539,4547 ****
--- 4539,4551 ----
  
    if (TREE_CODE (n) == ADDR_EXPR)
      n = TREE_OPERAND (n, 0);
+   if (TREE_CODE (n) == COMPONENT_REF)
+     n = TREE_OPERAND (n, 1);
    while (TREE_CODE (n) == TREE_LIST)
      n = TREE_VALUE (n);
  
+   if (TREE_CODE (n) == FUNCTION_DECL)
+     return arg_assoc_type (k, TREE_TYPE (n));
    if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
      {
        /* [basic.lookup.koenig]
*************** arg_assoc (k, n)
*** 4604,4610 ****
        my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
        
        for (; n; n = OVL_CHAIN (n))
! 	if (arg_assoc (k, OVL_FUNCTION (n)))
  	  return 1;
      }
  
--- 4608,4614 ----
        my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
        
        for (; n; n = OVL_CHAIN (n))
! 	if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
  	  return 1;
      }
  
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.55
diff -c -p -r1.55 error.c
*** error.c	1998/10/06 14:19:54	1.55
--- error.c	1998/10/20 03:02:57
*************** dump_expr (t, nop)
*** 1577,1584 ****
      case OFFSET_REF:
        {
  	tree ob = TREE_OPERAND (t, 0);
! 	if (TREE_CODE (ob) == NOP_EXPR
! 	    && TREE_OPERAND (ob, 0) == error_mark_node)
  	  {
  	    if (TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
  	      /* A::f */
--- 1577,1583 ----
      case OFFSET_REF:
        {
  	tree ob = TREE_OPERAND (t, 0);
! 	if (is_dummy_object (ob))
  	  {
  	    if (TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
  	      /* A::f */
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.69
diff -c -p -r1.69 init.c
*** init.c	1998/10/16 03:37:40	1.69
--- init.c	1998/10/20 03:02:57
*************** build_member_call (type, name, parmlist)
*** 1359,1365 ****
    tree t;
    tree method_name;
    int dtor = 0;
-   int dont_use_this = 0;
    tree basetype_path, decl;
  
    if (TREE_CODE (name) == TEMPLATE_ID_EXPR
--- 1359,1364 ----
*************** build_member_call (type, name, parmlist)
*** 1415,1438 ****
        return error_mark_node;
      }
  
!   /* No object?  Then just fake one up, and let build_method_call
!      figure out what to do.  */
!   if (current_class_type == 0
!       || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)
!     dont_use_this = 1;
  
!   if (dont_use_this)
      {
-       basetype_path = TYPE_BINFO (type);
-       decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
-     }
-   else if (current_class_ptr == 0)
-     {
-       dont_use_this = 1;
-       decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
-     }
-   else
-     {
        tree olddecl = current_class_ptr;
        tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
        if (oldtype != type)
--- 1414,1425 ----
        return error_mark_node;
      }
  
!   decl = maybe_dummy_object (type, &basetype_path);
  
!   /* Convert 'this' to the specified type to disambiguate conversion
!      to the function's context.  */
!   if (decl == current_class_ref)
      {
        tree olddecl = current_class_ptr;
        tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
        if (oldtype != type)
*************** build_member_call (type, name, parmlist)
*** 1440,1452 ****
  	  tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
  					     TYPE_VOLATILE (oldtype));
  	  decl = convert_force (build_pointer_type (newtype), olddecl, 0);
  	}
-       else
- 	decl = olddecl;
      }
  
-   decl = build_indirect_ref (decl, NULL_PTR);
- 
    if (method_name == constructor_name (type)
        || method_name == constructor_name_full (type))
      return build_functional_cast (type, parmlist);
--- 1427,1436 ----
  	  tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
  					     TYPE_VOLATILE (oldtype));
  	  decl = convert_force (build_pointer_type (newtype), olddecl, 0);
+ 	  decl = build_indirect_ref (decl, NULL_PTR);
  	}
      }
  
    if (method_name == constructor_name (type)
        || method_name == constructor_name_full (type))
      return build_functional_cast (type, parmlist);
*************** build_member_call (type, name, parmlist)
*** 1463,1469 ****
  	return error_mark_node;
        if (TREE_CODE (t) == FIELD_DECL)
  	{
! 	  if (dont_use_this)
  	    {
  	      cp_error ("invalid use of non-static field `%D'", t);
  	      return error_mark_node;
--- 1447,1453 ----
  	return error_mark_node;
        if (TREE_CODE (t) == FIELD_DECL)
  	{
! 	  if (is_dummy_object (decl))
  	    {
  	      cp_error ("invalid use of non-static field `%D'", t);
  	      return error_mark_node;
*************** build_offset_ref (type, name)
*** 1569,1584 ****
        return error_mark_node;
      }
  
!   if (current_class_type == 0
!       || get_base_distance (type, current_class_type, 0, &basebinfo) == -1)
!     {
!       basebinfo = TYPE_BINFO (type);
!       decl = build1 (NOP_EXPR, type, error_mark_node);
!     }
!   else if (current_class_ptr == 0)
!     decl = build1 (NOP_EXPR, type, error_mark_node);
!   else
!     decl = current_class_ref;
  
    fnfields = lookup_fnfields (basebinfo, name, 1);
    fields = lookup_field (basebinfo, name, 0, 0);
--- 1553,1559 ----
        return error_mark_node;
      }
  
!   decl = maybe_dummy_object (type, &basebinfo);
  
    fnfields = lookup_fnfields (basebinfo, name, 1);
    fields = lookup_field (basebinfo, name, 0, 0);
*************** resolve_offset_ref (exp)
*** 1771,1779 ****
  
    /* The first case is really just a reference to a member of `this'.  */
    if (TREE_CODE (member) == FIELD_DECL
!       && (base == current_class_ref
! 	  || (TREE_CODE (base) == NOP_EXPR
! 	      && TREE_OPERAND (base, 0) == error_mark_node)))
      {
        tree basetype_path;
        tree access;
--- 1746,1752 ----
  
    /* The first case is really just a reference to a member of `this'.  */
    if (TREE_CODE (member) == FIELD_DECL
!       && (base == current_class_ref || is_dummy_object (base)))
      {
        tree basetype_path;
        tree access;
*************** resolve_offset_ref (exp)
*** 1815,1822 ****
      }
  
    /* Ensure that we have an object.  */
!   if (TREE_CODE (base) == NOP_EXPR
!       && TREE_OPERAND (base, 0) == error_mark_node)
      addr = error_mark_node;
    else
      /* If this is a reference to a member function, then return the
--- 1788,1794 ----
      }
  
    /* Ensure that we have an object.  */
!   if (is_dummy_object (base))
      addr = error_mark_node;
    else
      /* If this is a reference to a member function, then return the
Index: method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.79
diff -c -p -r1.79 method.c
*** method.c	1998/10/16 12:07:58	1.79
--- method.c	1998/10/20 03:02:57
*************** hack_identifier (value, name)
*** 1866,1871 ****
--- 1866,1882 ----
        TREE_USED (value) = 1;
        value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
      }
+   else if (TREE_CODE (value) == FUNCTION_DECL
+ 	   && DECL_FUNCTION_MEMBER_P (value))
+     {
+       tree decl;
+ 
+       if (IS_SIGNATURE (DECL_CLASS_CONTEXT (value)))
+ 	return value;
+ 
+       decl = maybe_dummy_object (DECL_CLASS_CONTEXT (value), 0);
+       value = build_component_ref (decl, name, NULL_TREE, 1);
+     }
    else if (really_overloaded_fn (value))
      {
  #if 0
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.217
diff -c -p -r1.217 pt.c
*** pt.c	1998/10/17 20:33:43	1.217
--- pt.c	1998/10/20 03:02:57
*************** tsubst_copy (t, args, in_decl)
*** 5990,5995 ****
--- 5992,5998 ----
      case CONST_CAST_EXPR:
      case STATIC_CAST_EXPR:
      case DYNAMIC_CAST_EXPR:
+     case NOP_EXPR:
        return build1
  	(code, tsubst (TREE_TYPE (t), args, in_decl),
  	 tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.71
diff -c -p -r1.71 tree.c
*** tree.c	1998/10/17 20:33:45	1.71
--- tree.c	1998/10/20 03:02:58
*************** member_p (decl)
*** 2629,2631 ****
--- 2629,2684 ----
    tree ctx = DECL_CONTEXT (decl);
    return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't');
  }
+ 
+ /* Create a placeholder for member access where we don't actually have an
+    object that the access is against.  */
+ 
+ tree
+ build_dummy_object (type)
+      tree type;
+ {
+   tree decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
+   return build_indirect_ref (decl, NULL_PTR);
+ }
+ 
+ /* We've gotten a reference to a member of TYPE.  Return *this if appropriate,
+    or a dummy object otherwise.  If BINFOP is non-0, it is filled with the
+    binfo path from current_class_type to TYPE, or 0.  */
+ 
+ tree
+ maybe_dummy_object (type, binfop)
+      tree type;
+      tree *binfop;
+ {
+   tree decl, context;
+ 
+   if (current_class_type
+       && get_base_distance (type, current_class_type, 0, binfop) != -1)
+     context = current_class_type;
+   else
+     {
+       /* Reference from a nested class member function.  */
+       context = type;
+       if (binfop)
+ 	*binfop = TYPE_BINFO (type);
+     }
+ 
+   if (current_class_ref && context == current_class_type)
+     decl = current_class_ref;
+   else
+     decl = build_dummy_object (context);
+ 
+   return decl;
+ }
+ 
+ /* Returns 1 if OB is a placeholder object, or a pointer to one.  */
+ 
+ int
+ is_dummy_object (ob)
+      tree ob;
+ {
+   if (TREE_CODE (ob) == INDIRECT_REF)
+     ob = TREE_OPERAND (ob, 0);
+   return (TREE_CODE (ob) == NOP_EXPR
+ 	  && TREE_OPERAND (ob, 0) == error_mark_node);
+ }
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.116
diff -c -p -r1.116 typeck.c
*** typeck.c	1998/10/16 03:37:41	1.116
--- typeck.c	1998/10/20 03:02:58
*************** build_component_ref (datum, component, b
*** 2078,2134 ****
  	    return error_mark_node;
  	  if (fndecls)
  	    {
  	      if (TREE_CHAIN (fndecls) == NULL_TREE
! 		  && TREE_CODE (TREE_VALUE (fndecls)) != OVERLOAD)
  		{
! 		  tree access, fndecl;
  
- 		  /* Unique, so use this one now.  */
  		  basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls));
  		  fndecl = TREE_VALUE (fndecls);
! 		  access = compute_access (TREE_PURPOSE (fndecls), fndecl);
! 		  if (access == access_public_node)
! 		    {
! 		      if (DECL_VINDEX (fndecl)
! 			  && ! resolves_to_fixed_type_p (datum, 0))
! 			{
! 			  tree addr = build_unary_op (ADDR_EXPR, datum, 0);
! 			  tree fntype = TREE_TYPE (fndecl);
! 
! 			  addr = convert_pointer_to (DECL_CONTEXT (fndecl),
! 						     addr);
! 			  datum = build_indirect_ref (addr, NULL_PTR);
! 			  my_friendly_assert (datum != error_mark_node, 310);
! 			  fndecl = build_vfn_ref (&addr, datum,
! 						  DECL_VINDEX (fndecl));
! 			  /* The type of fndecl is a function type,
! 			     not a pointer-to-function type, since
! 			     build_vfn_ref returns not the correct
! 			     vtable slot, but the indirection of the
! 			     correct vtable slot.  */
! 			  TREE_TYPE (fndecl) = fntype;
! 			}
! 		      else
! 			mark_used (fndecl);
! 		      return build (OFFSET_REF, TREE_TYPE (fndecl),
! 				    datum, fndecl);
! 		    }
! 		  if (access == access_protected_node)
! 		    cp_error ("member function `%D' is protected", fndecl);
! 		  else
! 		    cp_error ("member function `%D' is private", fndecl);
! 		  return error_mark_node;
  		}
  	      else
  		{
! 		  /* Just act like build_offset_ref, since the object does
!                      not matter unless we're actually calling the function.  */
! 		  tree t;
! 
! 		  t = build_tree_list (error_mark_node, fndecls);
! 		  TREE_TYPE (t) = build_offset_type (basetype,
! 						     unknown_type_node);
! 		  return t;
  		}
  	    }
  
--- 2078,2104 ----
  	    return error_mark_node;
  	  if (fndecls)
  	    {
+ 	      /* If the function is unique and static, we can resolve it
+ 		 now.  Otherwise, we have to wait and see what context it is
+ 		 used in; a component_ref involving a non-static member
+ 		 function can only be used in a call (expr.ref).  */
  	      if (TREE_CHAIN (fndecls) == NULL_TREE
! 		  && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL
! 		  && DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
  		{
! 		  tree fndecl;
  
  		  basetype = TYPE_MAIN_VARIANT (TREE_PURPOSE (fndecls));
  		  fndecl = TREE_VALUE (fndecls);
! 		  enforce_access (TREE_PURPOSE (fndecls), fndecl);
! 		  mark_used (fndecl);
! 		  return fndecl;
  		}
  	      else
  		{
! 		  ref = build (COMPONENT_REF, unknown_type_node,
! 			       datum, fndecls);
! 		  return ref;
  		}
  	    }
  
*************** build_x_function_call (function, params,
*** 2622,2630 ****
  	      return error_mark_node;
  	    }
  	  /* Yow: call from a static member function.  */
! 	  decl = build1 (NOP_EXPR, build_pointer_type (current_class_type),
! 			 error_mark_node);
! 	  decl = build_indirect_ref (decl, NULL_PTR);
  	}
  
        /* Put back explicit template arguments, if any.  */
--- 2592,2598 ----
  	      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.  */
*************** build_x_function_call (function, params,
*** 2636,2647 ****
    else if (TREE_CODE (function) == COMPONENT_REF
  	   && type == unknown_type_node)
      {
!       /* Should we undo what was done in build_component_ref? */
!       if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC)
! 	/* Get the name that build_component_ref hid.  */
! 	function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1)));
!       else
! 	function = TREE_PURPOSE (TREE_OPERAND (function, 1));
        return build_method_call (decl, function, params,
  				NULL_TREE, LOOKUP_NORMAL);
      }
--- 2604,2613 ----
    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);
!       function = DECL_NAME (OVL_CURRENT (TREE_VALUE (function)));
        return build_method_call (decl, function, params,
  				NULL_TREE, LOOKUP_NORMAL);
      }
*************** build_component_addr (arg, argtype, msg)
*** 4248,4253 ****
--- 4214,4221 ----
    tree basetype = decl_type_context (field);
    tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
  
+   my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 981018);
+ 
    if (DECL_C_BIT_FIELD (field))
      {
        error (msg, IDENTIFIER_POINTER (DECL_NAME (field)));
*************** build_unary_op (code, xarg, noconvert)
*** 4665,4689 ****
  	  return build1 (ADDR_EXPR, unknown_type_node, arg);
  	}
  
!       if (TREE_CODE (arg) == OVERLOAD 
! 	  || (TREE_CODE (arg) == OFFSET_REF
! 	      && TREE_CODE (TREE_OPERAND (arg, 1)) == TEMPLATE_ID_EXPR))
! 	return build1 (ADDR_EXPR, unknown_type_node, arg);
!       else if (TREE_CODE (arg) == TREE_LIST)
  	{
- 	  if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL)
- 	    /* Unique overloaded non-member function.  */
- 	    return build_unary_op (ADDR_EXPR, TREE_VALUE (arg), 0);
- 	  if (TREE_CHAIN (arg) == NULL_TREE
- 	      && TREE_CODE (TREE_VALUE (arg)) == TREE_LIST
- 	      && TREE_CODE (TREE_VALUE (TREE_VALUE (arg))) != OVERLOAD)
- 	    /* Unique overloaded member function.  */
- 	    return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)),
- 				   0);
- 	  return build1 (ADDR_EXPR, unknown_type_node, arg);
- 	}
-       else if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
- 	{
  	  tree targs;
  	  tree fn;
  	  
--- 4633,4640 ----
  	  return build1 (ADDR_EXPR, unknown_type_node, arg);
  	}
  
!       if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
  	{
  	  tree targs;
  	  tree fn;
  	  
*************** build_unary_op (code, xarg, noconvert)
*** 4705,4710 ****
--- 4656,4663 ----
  
  	  return build1 (ADDR_EXPR, unknown_type_node, arg);
  	}
+       else if (type_unknown_p (arg))
+ 	return build1 (ADDR_EXPR, unknown_type_node, arg);
  
        /* Handle complex lvalues (when permitted)
  	 by reduction to simpler cases.  */
*************** unary_complex_lvalue (code, arg)
*** 4890,4898 ****
  	  tree type;
  
  	  if (TREE_OPERAND (arg, 0)
! 	      && (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
! 		  || (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)
! 		      != error_mark_node))
  	      && TREE_CODE (t) != FIELD_DECL)
  	    {
  	      cp_error ("taking address of bound pointer-to-member expression");
--- 4843,4849 ----
  	  tree type;
  
  	  if (TREE_OPERAND (arg, 0)
! 	      && ! is_dummy_object (TREE_OPERAND (arg, 0))
  	      && TREE_CODE (t) != FIELD_DECL)
  	    {
  	      cp_error ("taking address of bound pointer-to-member expression");


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