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: Remove build_component_ref


This is another patch that separates name-lookup (which is supposed to
be done by the parser) from semantic analysis.  The new parser really
wants to be involved only in parsing, and it wants nice interfaces to
call when its done parsing that make the right thing happen.

As a side-effect, this patch gets rid of some more places where we
were looking up the same name multiple times rather than simply
remembering the answer the first time we looked it up.

Bootstrapped, tested on i686-pc-linux-gnu, applied on the mainline and
on the branch.

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

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

	Rework build_component_ref.
	* call.c (build_vfield_ref): Do not go through build_component_ref.
	(build_field_call): Use build_class_member_access_expr.
	(build_user_type_conversion_1): Use BASELINK_FUNCTIONS.
	(build_object_call): Likewise.
	* class.c (convert_to_base): New function.
	(type_requires_array_cookie): Use BASELINK_FUNCTIONS.
	(instantiate_type): Handle BASELINKs.
	* cp-tree.def (BASELINK): New tree code.
	* cp-tree.h (BASELINK_P): Reimplement.
	(SET_BASELINK_P): Remove.
	(BASELINK_BINFO): Reimplement.
	(BASELINK_FUNCTIONS): Likewise.
	(BASELINK_ACCESS_BINFO): Likewise.
	(BASELINK_OPTYPE): Likewise.
	(convert_to_base): New function.
	(name_p): Likewise.
	(build_object_ref): Remove.
	(build_component_ref_1): Likewise.
	(build_component_ref): Likewise.
	(build_x_component_ref): Likewise.
	(build_class_member_access_expr): New function.
	(finish_class_member_access_expr): Likewise.
	(build_ptrmemfunc_access_expr): Likewise.
	* decl.c (grokdeclarator): Handle BASELINKs.
	* decl2. (build_expr_from_tree): Handle COMPONENT_REFs by using
	finish_class_member_access_expr.
	(arg_assoc): Handle BASELINKs.
	(do_class_using_decl): Likewise.
	* error.c (dump_decl): Likewise.
	(dump_expr): Use build_ptrmemfunc_access_expr.
	* except.c (dtor_nothrow): Use CLASSTYPE_DESTRUCTORS to find
	destructors.
	(build_throw): Use BASELINK_FUNCTIONS.
	* init.c (perform_member_init): Use
	build_class_member_access_expr.
	(build_offset_ref): Handle BASELINKs.  Use
	build_class_member_access_expr.
	* method.c (hack_identifier): Likewise.
	* parse.y (do_id): Use BASELINK, not TREE_LIST.
	(primary): Remove uses of build_object_ref.
	* pt.c (lookup_template_function): Handle BASELINKs.
	(resolve_overloaded_unification): Likewise.
	* search.c (build_baselink): Build a BASELINK, not a TREE_LIST.
	(lookup_field): Use BASELINK, not TREE_LIST.
	(lookup_fnfiels): Likewise.
	(setup_class_bindings): Likewise.
	* semantics.c (finish_object_call_expr): Do not use
	build_method_call when we already know what function is being
	called.
	* spew.c (identifier_type): Use BASELINK, not TREE_LIST.
	* tree.c (really_overloaded_fn): Use OVL_CHAIN for OVERLOADs, not
	TREE_CHAIN.
	(name_p): New function.
	* typeck.c (build_object_ref): Remove.
	(build_component_ref_1): Likewise.
	(build_x_component_ref): Likewise.
	(build_class_member_access_expr): New function.
	(finish_class_member_access_expr): Likewise.
	(build_ptrmemfunc_access_expr): Likewise.
	(get_member_function_from_ptrfunc): Use
	build_ptrmemfunc_access_expr.
	(build_binary_op): Likewise.
	(build_unary_op): Likewise.
	(build_ptrmemfunc): Likewise.
	(pfn_from_ptrmemfunc): Likewise.
	* typeck2.c (build_m_component_ref): Adjust comment.
	
2002-08-07  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/abi/offsetof.C: Tweak error messages.
	* g++.old-deja/g++.mike/p10769a.C: Likewise.
	
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.324
diff -c -p -r1.324 call.c
*** cp/call.c	1 Aug 2002 04:46:18 -0000	1.324
--- cp/call.c	8 Aug 2002 05:22:39 -0000
*************** tree
*** 106,126 ****
  build_vfield_ref (datum, type)
       tree datum, type;
  {
-   tree rval;
- 
    if (datum == error_mark_node)
      return error_mark_node;
  
    if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
      datum = convert_from_reference (datum);
  
!   if (! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type))
!     rval = build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
! 		  datum, TYPE_VFIELD (type));
!   else
!     rval = build_component_ref (datum, DECL_NAME (TYPE_VFIELD (type)), NULL_TREE, 0);
  
!   return rval;
  }
  
  /* Build a call to a member of an object.  I.e., one that overloads
--- 106,123 ----
  build_vfield_ref (datum, type)
       tree datum, type;
  {
    if (datum == error_mark_node)
      return error_mark_node;
  
    if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
      datum = convert_from_reference (datum);
  
!   if (TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)
!       && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
!     datum = convert_to_base (datum, type, /*check_access=*/false);
  
!   return build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
! 		datum, TYPE_VFIELD (type));
  }
  
  /* Build a call to a member of an object.  I.e., one that overloads
*************** build_field_call (tree instance_ptr, tre
*** 139,145 ****
        /* 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;
--- 136,144 ----
        /* 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_class_member_access_expr (instance, decl, 
! 						 /*access_path=*/NULL_TREE,
! 						 /*preserve_reference=*/false);
  
        if (instance == error_mark_node)
  	return error_mark_node;
*************** build_user_type_conversion_1 (totype, ex
*** 2494,2500 ****
      {
        tree t;
  
!       ctors = TREE_VALUE (ctors);
  
        t = build_int_2 (0, 0);
        TREE_TYPE (t) = build_pointer_type (totype);
--- 2493,2499 ----
      {
        tree t;
  
!       ctors = BASELINK_FUNCTIONS (ctors);
  
        t = build_int_2 (0, 0);
        TREE_TYPE (t) = build_pointer_type (totype);
*************** build_object_call (obj, args)
*** 2790,2799 ****
  
    if (fns)
      {
!       tree base = BINFO_TYPE (TREE_PURPOSE (fns));
        mem_args = tree_cons (NULL_TREE, build_this (obj), args);
  
!       for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  if (TREE_CODE (fn) == TEMPLATE_DECL)
--- 2789,2798 ----
  
    if (fns)
      {
!       tree base = BINFO_TYPE (BASELINK_BINFO (fns));
        mem_args = tree_cons (NULL_TREE, build_this (obj), args);
  
!       for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  if (TREE_CODE (fn) == TEMPLATE_DECL)
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.458
diff -c -p -r1.458 class.c
*** cp/class.c	23 Jul 2002 06:22:03 -0000	1.458
--- cp/class.c	8 Aug 2002 05:22:39 -0000
*************** build_base_path (code, expr, binfo, nonn
*** 361,366 ****
--- 361,384 ----
    return expr;
  }
  
+ /* Convert OBJECT to the base TYPE.  If CHECK_ACCESS is true, an error
+    message is emitted if TYPE is inaccessible.  OBJECT is assumed to
+    be non-NULL.  */
+ 
+ tree
+ convert_to_base (tree object, tree type, bool check_access)
+ {
+   tree binfo;
+ 
+   binfo = lookup_base (TREE_TYPE (object), type, 
+ 		       check_access ? ba_check : ba_ignore, 
+ 		       NULL);
+   if (!binfo || TREE_CODE (binfo) == error_mark_node)
+     return error_mark_node;
+ 
+   return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
+ }
+ 
  
  /* Virtual function things.  */
  
*************** type_requires_array_cookie (type)
*** 4260,4266 ****
    if (!fns || fns == error_mark_node)
      return false;
    /* Loop through all of the functions.  */
!   for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
      {
        tree fn;
        tree second_parm;
--- 4278,4284 ----
    if (!fns || fns == error_mark_node)
      return false;
    /* Loop through all of the functions.  */
!   for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
      {
        tree fn;
        tree second_parm;
*************** instantiate_type (lhstype, rhs, flags)
*** 6079,6084 ****
--- 6097,6105 ----
  		  TREE_TYPE (rhs), lhstype);
        return error_mark_node;
      }
+ 
+   if (TREE_CODE (rhs) == BASELINK)
+     rhs = BASELINK_FUNCTIONS (rhs);
  
    /* We don't overwrite rhs if it is an overloaded function.
       Copying it would destroy the tree link.  */
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.64
diff -c -p -r1.64 cp-tree.def
*** cp/cp-tree.def	1 Aug 2002 04:46:18 -0000	1.64
--- cp/cp-tree.def	8 Aug 2002 05:22:40 -0000
*************** DEFTREECODE (THROW_EXPR, "throw_expr", '
*** 89,94 ****
--- 89,108 ----
     these to avoid actually creating instances of the empty classes.  */
  DEFTREECODE (EMPTY_CLASS_EXPR, "empty_class_expr", 'e', 0)
  
+ /* A reference to a member function or member functions from a base
+    class.  BASELINK_FUNCTIONS gives the FUNCTION_DECL,
+    TEMPLATE_DECL, OVERLOAD, or TEMPLATE_ID_EXPR corresponding to the
+    functions.  BASELINK_BINFO gives the base from which the functions
+    come, i.e., the base to which the `this' pointer must be converted
+    before the functions are called.  BASELINK_ACCESS_BINFO gives the
+    base used to name the functions.  
+ 
+    A BASELINK is an expression; the TREE_TYPE of the BASELINK gives
+    the type of the expression.  This type is either a FUNCTION_TYPE,
+    METHOD_TYPE, or `unknown_type_node' indicating that the function is
+    overloaded. */
+ DEFTREECODE (BASELINK, "baselink", 'e', 3)
+ 
  /* Template definition.  The following fields have the specified uses,
     although there are other macros in cp-tree.h that should be used for
     accessing this data.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.739
diff -c -p -r1.739 cp-tree.h
*** cp/cp-tree.h	1 Aug 2002 04:46:18 -0000	1.739
--- cp/cp-tree.h	8 Aug 2002 05:22:41 -0000
*************** struct diagnostic_context;
*** 57,63 ****
        (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
        TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
        INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
-       BASELINK_P (in TREE_LIST)
        ICS_ELLIPSIS_FLAG (in _CONV)
        BINFO_ACCESS (in BINFO)
     2: IDENTIFIER_OPNAME_P.
--- 57,62 ----
*************** struct tree_overload GTY(())
*** 378,409 ****
    tree function;
  };
  
! /* A `baselink' is a TREE_LIST whose TREE_PURPOSE is a BINFO
!    indicating a particular base class, and whose TREE_VALUE is a
!    (possibly overloaded) function from that base class.  */
  #define BASELINK_P(NODE) \
!   (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)
  
--- 377,404 ----
    tree function;
  };
  
! /* Returns true iff NODE is a BASELINK.  */
  #define BASELINK_P(NODE) \
!   (TREE_CODE (NODE) == BASELINK)
! /* The BINFO indicating the base from which the BASELINK_FUNCTIONS came.  */
  #define BASELINK_BINFO(NODE) \
!   (TREE_OPERAND (BASELINK_CHECK (NODE), 0))
! /* The functions referred to by the BASELINK; either a FUNCTION_DECL,
!    a TEMPLATE_DECL, an OVERLOAD, or a TEMPLATE_ID_EXPR.  */
  #define BASELINK_FUNCTIONS(NODE) \
!   (TREE_OPERAND (BASELINK_CHECK (NODE), 1))
  /* 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_OPERAND (BASELINK_CHECK (NODE), 2))
  /* 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 (BASELINK_CHECK (NODE)))
  
  #define WRAPPER_ZC(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c)
  
*************** extern tree perform_implicit_conversion 
*** 3713,3718 ****
--- 3708,3714 ----
  
  /* in class.c */
  extern tree build_base_path			PARAMS ((enum tree_code, tree, tree, int));
+ extern tree convert_to_base                     (tree, tree, bool);
  extern tree build_vbase_path			PARAMS ((enum tree_code, tree, tree, tree, int));
  extern tree build_vtbl_ref			PARAMS ((tree, tree));
  extern tree build_vfn_ref			PARAMS ((tree, tree));
*************** extern tree cp_build_qualified_type_real
*** 4427,4432 ****
--- 4423,4429 ----
    cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning)
  extern tree build_shared_int_cst                PARAMS ((int));
  extern special_function_kind special_function_p PARAMS ((tree));
+ extern bool name_p                              (tree);
  extern int count_trees                          PARAMS ((tree));
  extern int char_type_p                          PARAMS ((tree));
  extern void verify_stmt_tree                    PARAMS ((tree));
*************** extern tree cxx_sizeof_or_alignof_type  
*** 4466,4475 ****
  #define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
  extern tree inline_conversion			PARAMS ((tree));
  extern tree decay_conversion			PARAMS ((tree));
! extern tree build_object_ref			PARAMS ((tree, tree, tree));
! extern tree build_component_ref_1		PARAMS ((tree, tree, int));
! extern tree build_component_ref			PARAMS ((tree, tree, tree, int));
! extern tree build_x_component_ref		PARAMS ((tree, tree, tree));
  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));
--- 4463,4470 ----
  #define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
  extern tree inline_conversion			PARAMS ((tree));
  extern tree decay_conversion			PARAMS ((tree));
! extern tree build_class_member_access_expr      (tree, tree, tree, bool);
! extern tree finish_class_member_access_expr     (tree, tree);
  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 check_return_expr           
*** 4510,4515 ****
--- 4505,4511 ----
    build_binary_op(code, arg1, arg2, 1)
  #define cxx_sizeof(T)  cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
  #define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true)
+ extern tree build_ptrmemfunc_access_expr       (tree, tree);
  
  /* in typeck2.c */
  extern void cxx_incomplete_type_diagnostic	PARAMS ((tree, tree, int));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.925
diff -c -p -r1.925 decl.c
*** cp/decl.c	28 Jul 2002 05:34:04 -0000	1.925
--- cp/decl.c	8 Aug 2002 05:22:44 -0000
*************** grokdeclarator (declarator, declspecs, d
*** 10026,10031 ****
--- 10026,10035 ----
  	    next = 0;
  	    break;
  
+ 	  case BASELINK:
+ 	    next = &BASELINK_FUNCTIONS (decl);
+ 	    break;
+ 	    
  	  default:
  	    internal_error ("`%D' as declarator", decl);
  	  }
*************** grokdeclarator (declarator, declspecs, d
*** 11156,11161 ****
--- 11160,11169 ----
  
  	case BIT_NOT_EXPR:
  	  declarator = TREE_OPERAND (declarator, 0);
+ 	  break;
+ 
+ 	case BASELINK:
+ 	  declarator = BASELINK_FUNCTIONS (declarator);
  	  break;
  
  	case RECORD_TYPE:
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.553
diff -c -p -r1.553 decl2.c
*** cp/decl2.c	1 Aug 2002 04:46:18 -0000	1.553
--- cp/decl2.c	8 Aug 2002 05:22:45 -0000
*************** build_expr_from_tree (t)
*** 3943,3959 ****
      case COMPONENT_REF:
        {
  	tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
! 	tree field = TREE_OPERAND (t, 1);
! 	
! 	/* We use a COMPONENT_REF to indicate things of the form `x.b'
! 	   and `x.A::b'.  We must distinguish between those cases
! 	   here.  */
! 	if (TREE_CODE (field) == SCOPE_REF)
! 	  return build_object_ref (object, 
! 				   TREE_OPERAND (field, 0),
! 				   TREE_OPERAND (field, 1));
! 	else
! 	  return build_x_component_ref (object, field, NULL_TREE);
        }
  
      case THROW_EXPR:
--- 3943,3950 ----
      case COMPONENT_REF:
        {
  	tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
! 	return finish_class_member_access_expr (object, 
! 						TREE_OPERAND (t, 1));
        }
  
      case THROW_EXPR:
*************** arg_assoc (k, n)
*** 4858,4863 ****
--- 4849,4856 ----
      n = TREE_OPERAND (n, 1);
    while (TREE_CODE (n) == TREE_LIST)
      n = TREE_VALUE (n);
+   if (TREE_CODE (n) == BASELINK)
+     n = BASELINK_FUNCTIONS (n);
  
    if (TREE_CODE (n) == FUNCTION_DECL)
      return arg_assoc_type (k, TREE_TYPE (n));
*************** do_class_using_decl (decl)
*** 5222,5227 ****
--- 5215,5227 ----
      }
    if (TREE_CODE (name) == TYPE_DECL || TREE_CODE (name) == TEMPLATE_DECL)
      name = DECL_NAME (name);
+   else if (BASELINK_P (name))
+     {
+       name = BASELINK_FUNCTIONS (name);
+       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ 	name = TREE_OPERAND (name, 0);
+       name = DECL_NAME (get_first_fn (name));
+     }
  
    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
  
Index: cp/error.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.183
diff -c -p -r1.183 error.c
*** cp/error.c	25 Jul 2002 21:13:36 -0000	1.183
--- cp/error.c	8 Aug 2002 05:22:46 -0000
*************** dump_decl (t, flags)
*** 991,996 ****
--- 991,1000 ----
        print_tree_identifier (scratch_buffer, DECL_NAME (t));
        break;
  
+     case BASELINK:
+       dump_decl (BASELINK_FUNCTIONS (t), flags);
+       break;
+ 
      default:
        sorry_for_unsupported_tree (t);
        /* Fallthrough to error.  */
*************** dump_expr (t, flags)
*** 1827,1833 ****
      case CONSTRUCTOR:
        if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
  	{
! 	  tree idx = build_component_ref (t, pfn_identifier, NULL_TREE, 0);
  
  	  if (integer_zerop (idx))
  	    {
--- 1831,1837 ----
      case CONSTRUCTOR:
        if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
  	{
! 	  tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
  
  	  if (integer_zerop (idx))
  	    {
Index: cp/except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/except.c,v
retrieving revision 1.142
diff -c -p -r1.142 except.c
*** cp/except.c	1 Apr 2002 20:26:13 -0000	1.142
--- cp/except.c	8 Aug 2002 05:22:46 -0000
*************** static int
*** 175,191 ****
  dtor_nothrow (type)
       tree type;
  {
-   tree fn;
- 
    if (type == NULL_TREE)
      return 0;
  
    if (! TYPE_HAS_DESTRUCTOR (type))
      return 1;
  
!   fn = lookup_member (type, dtor_identifier, 0, 0);
!   fn = TREE_VALUE (fn);
!   return TREE_NOTHROW (fn);
  }
  
  /* Build up a call to __cxa_end_catch, to destroy the exception object
--- 175,187 ----
  dtor_nothrow (type)
       tree type;
  {
    if (type == NULL_TREE)
      return 0;
  
    if (! TYPE_HAS_DESTRUCTOR (type))
      return 1;
  
!   return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
  }
  
  /* Build up a call to __cxa_end_catch, to destroy the exception object
*************** build_throw (exp)
*** 754,760 ****
  	{
  	  cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
  				     complete_dtor_identifier, 0);
! 	  cleanup = TREE_VALUE (cleanup);
  	  mark_used (cleanup);
  	  cxx_mark_addressable (cleanup);
  	  /* Pretend it's a normal function.  */
--- 750,756 ----
  	{
  	  cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
  				     complete_dtor_identifier, 0);
! 	  cleanup = BASELINK_FUNCTIONS (cleanup);
  	  mark_used (cleanup);
  	  cxx_mark_addressable (cleanup);
  	  /* Pretend it's a normal function.  */
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.287
diff -c -p -r1.287 init.c
*** cp/init.c	1 Aug 2002 04:46:19 -0000	1.287
--- cp/init.c	8 Aug 2002 05:22:47 -0000
*************** perform_member_init (member, init, expli
*** 232,239 ****
    tree decl;
    tree type = TREE_TYPE (member);
  
!   decl = build_component_ref (current_class_ref, member, NULL_TREE, explicit);
! 
    if (decl == error_mark_node)
      return;
  
--- 232,240 ----
    tree decl;
    tree type = TREE_TYPE (member);
  
!   decl = build_class_member_access_expr (current_class_ref, member,
! 					 /*access_path=*/NULL_TREE,
! 					 /*preserve_reference=*/true);
    if (decl == error_mark_node)
      return;
  
*************** perform_member_init (member, init, expli
*** 305,312 ****
      {
        tree expr;
  
!       expr = build_component_ref (current_class_ref, member, NULL_TREE,
! 				  explicit);
        expr = build_delete (type, expr, sfk_complete_destructor,
  			   LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
  
--- 306,314 ----
      {
        tree expr;
  
!       expr = build_class_member_access_expr (current_class_ref, member,
! 					     /*access_path=*/NULL_TREE,
! 					     /*preserve_reference=*/false);
        expr = build_delete (type, expr, sfk_complete_destructor,
  			   LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
  
*************** build_offset_ref (type, name)
*** 1661,1670 ****
  
    decl = maybe_dummy_object (type, &basebinfo);
  
!   member = lookup_member (basebinfo, name, 1, 0);
! 
!   if (member == error_mark_node)
!     return error_mark_node;
  
    /* A lot of this logic is now handled in lookup_member.  */
    if (member && BASELINK_P (member))
--- 1663,1677 ----
  
    decl = maybe_dummy_object (type, &basebinfo);
  
!   if (BASELINK_P (name))
!     member = name;
!   else
!     {
!       member = lookup_member (basebinfo, name, 1, 0);
!       
!       if (member == error_mark_node)
! 	return error_mark_node;
!     }
  
    /* A lot of this logic is now handled in lookup_member.  */
    if (member && BASELINK_P (member))
*************** build_offset_ref (type, name)
*** 1696,1702 ****
  	  return t;
  	}
  
!       if (!really_overloaded_fn (t))
  	{
  	  /* Get rid of a potential OVERLOAD around it */
  	  t = OVL_CURRENT (t);
--- 1703,1709 ----
  	  return t;
  	}
  
!       if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
  	{
  	  /* Get rid of a potential OVERLOAD around it */
  	  t = OVL_CURRENT (t);
*************** resolve_offset_ref (exp)
*** 1841,1847 ****
        if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
  	base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
  
!       return build_component_ref (base, member, binfo, 1);
      }
  
    /* Ensure that we have an object.  */
--- 1848,1856 ----
        if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
  	base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
  
!       return build_class_member_access_expr (base, member,
! 					     /*access_path=*/NULL_TREE,
! 					     /*preserve_reference=*/false);
      }
  
    /* Ensure that we have an object.  */
*************** push_base_cleanups ()
*** 3325,3333 ****
  	continue;
        if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
  	{
! 	  tree this_member = (build_component_ref
! 			      (current_class_ref, DECL_NAME (member),
! 			       NULL_TREE, 0));
  	  tree this_type = TREE_TYPE (member);
  	  expr = build_delete (this_type, this_member,
  			       sfk_complete_destructor,
--- 3334,3343 ----
  	continue;
        if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
  	{
! 	  tree this_member = (build_class_member_access_expr 
! 			      (current_class_ref, member, 
! 			       /*access_path=*/NULL_TREE,
! 			       /*preserve_reference=*/false));
  	  tree this_type = TREE_TYPE (member);
  	  expr = build_delete (this_type, this_member,
  			       sfk_complete_destructor,
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.226
diff -c -p -r1.226 method.c
*** cp/method.c	1 Aug 2002 04:46:19 -0000	1.226
--- cp/method.c	8 Aug 2002 05:22:47 -0000
*************** hack_identifier (value, name)
*** 162,173 ****
  	  return error_mark_node;
  	}
        TREE_USED (current_class_ptr) = 1;
  
!       /* Mark so that if we are in a constructor, and then find that
! 	 this field was initialized by a base initializer,
! 	 we can emit an error message.  */
!       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))
--- 162,187 ----
  	  return error_mark_node;
  	}
        TREE_USED (current_class_ptr) = 1;
+       if (processing_template_decl)
+ 	value = build_min_nt (COMPONENT_REF, current_class_ref, name);
+       else
+ 	{
+ 	  tree access_type = current_class_type;
+ 	  
+ 	  while (!DERIVED_FROM_P (context_for_name_lookup (value), 
+ 				  access_type))
+ 	    {
+ 	      access_type = TYPE_CONTEXT (access_type);
+ 	      while (DECL_P (access_type))
+ 		access_type = DECL_CONTEXT (access_type);
+ 	    }
  
! 	  enforce_access (access_type, value);
! 	  value 
! 	    = build_class_member_access_expr (current_class_ref, value,
! 					      /*access_path=*/NULL_TREE,
! 					      /*preserve_reference=*/false);
! 	}
      }
    else if ((TREE_CODE (value) == FUNCTION_DECL
  	    && DECL_FUNCTION_MEMBER_P (value))
*************** hack_identifier (value, name)
*** 180,186 ****
  	value = OVL_CURRENT (value);
  
        decl = maybe_dummy_object (DECL_CONTEXT (value), 0);
!       value = build_component_ref (decl, name, NULL_TREE, 1);
      }
    else if (really_overloaded_fn (value))
      ;
--- 194,200 ----
  	value = OVL_CURRENT (value);
  
        decl = maybe_dummy_object (DECL_CONTEXT (value), 0);
!       value = finish_class_member_access_expr (decl, name);
      }
    else if (really_overloaded_fn (value))
      ;
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parse.y,v
retrieving revision 1.273
diff -c -p -r1.273 parse.y
*** cp/parse.y	1 Aug 2002 04:46:19 -0000	1.273
--- cp/parse.y	8 Aug 2002 05:22:48 -0000
*************** notype_unqualified_id:
*** 1522,1532 ****
  
  do_id:
  		{
! 		  /* If lastiddecl is a TREE_LIST, it's a baselink, which
! 		     means that we're in an expression like S::f<int>, so
! 		     don't do_identifier; we only do that for unqualified
  		     identifiers.  */
! 	          if (!lastiddecl || TREE_CODE (lastiddecl) != TREE_LIST)
  		    $$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
  		  else
  		    $$ = $<ttype>-1;
--- 1522,1532 ----
  
  do_id:
  		{
! 		  /* If lastiddecl is a BASELINK we're in an
! 		     expression like S::f<int>, so don't
! 		     do_identifier; we only do that for unqualified
  		     identifiers.  */
! 	          if (!lastiddecl || !BASELINK_P (lastiddecl))
  		    $$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
  		  else
  		    $$ = $<ttype>-1;
*************** primary:
*** 1720,1739 ****
  	| 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);
! 		}
          | object object_template_id '(' nonnull_exprlist ')'
                  { $$ = finish_object_call_expr ($2, $1, $4); }
  	| object object_template_id LEFT_RIGHT
                  { $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
  	| object unqualified_id  %prec UNARY
! 		{ $$ = build_x_component_ref ($$, $2, NULL_TREE); }
  	| object overqualified_id  %prec UNARY
! 		{ if (processing_template_decl)
! 		    $$ = build_min_nt (COMPONENT_REF, $1, $2);
! 		  else
! 		    $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
  	| object unqualified_id '(' nonnull_exprlist ')'
                  { $$ = finish_object_call_expr ($2, $1, $4); }
  	| object unqualified_id LEFT_RIGHT
--- 1720,1734 ----
  	| overqualified_id LEFT_RIGHT
  		{ $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
          | object object_template_id %prec UNARY
!                 { $$ = finish_class_member_access_expr ($$, $2); }
          | object object_template_id '(' nonnull_exprlist ')'
                  { $$ = finish_object_call_expr ($2, $1, $4); }
  	| object object_template_id LEFT_RIGHT
                  { $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
  	| object unqualified_id  %prec UNARY
! 		{ $$ = finish_class_member_access_expr ($$, $2); }
  	| object overqualified_id  %prec UNARY
!                 { $$ = finish_class_member_access_expr ($1, $2); }
  	| object unqualified_id '(' nonnull_exprlist ')'
                  { $$ = finish_object_call_expr ($2, $1, $4); }
  	| object unqualified_id LEFT_RIGHT
*************** parse_finish_call_expr (tree fn, tree ar
*** 4149,4162 ****
  	      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))
--- 4144,4163 ----
  	      else 
  		template_id = NULL_TREE;
  
! 	      if (BASELINK_P (name))
! 		fn = name;
! 	      else 
! 		{
! 		  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))
*************** parse_finish_call_expr (tree fn, tree ar
*** 4218,4226 ****
  
  	      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))
--- 4219,4237 ----
  
  	      if (DERIVED_FROM_P (scope, current_class_type)
  		  && current_class_ref)
! 		{
! 		  fn = build_baselink (lookup_base (current_class_type,
! 						    scope,
! 						    ba_any,
! 						    NULL),
! 				       TYPE_BINFO (current_class_type),
! 				       fn,
! 				       /*optype=*/NULL_TREE);
! 		  return finish_object_call_expr (fn,
! 						  current_class_ref,
! 						  args);
! 		}
! 
  
  	      access_scope = current_class_type;
  	      while (!DERIVED_FROM_P (scope, access_scope))
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.606
diff -c -p -r1.606 pt.c
*** cp/pt.c	1 Aug 2002 04:46:19 -0000	1.606
--- cp/pt.c	8 Aug 2002 05:22:49 -0000
*************** lookup_template_function (fns, arglist)
*** 3835,3844 ****
--- 3835,3854 ----
  
    my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
  		      || TREE_CODE (fns) == OVERLOAD
+ 		      || BASELINK_P (fns)
  		      || TREE_CODE (fns) == IDENTIFIER_NODE
  		      || TREE_CODE (fns) == LOOKUP_EXPR,
  		      20020730);
  
+   if (BASELINK_P (fns))
+     {
+       BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
+ 					unknown_type_node,
+ 					BASELINK_FUNCTIONS (fns),
+ 					arglist);
+       return fns;
+     }
+ 
    type = TREE_TYPE (fns);
    if (TREE_CODE (fns) == OVERLOAD || !type)
      type = unknown_type_node;
*************** resolve_overloaded_unification (tparms, 
*** 8195,8202 ****
      arg = TREE_OPERAND (arg, 1);
  
    /* Strip baselink information.  */
!   while (TREE_CODE (arg) == TREE_LIST)
!     arg = TREE_VALUE (arg);
  
    if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
      {
--- 8205,8212 ----
      arg = TREE_OPERAND (arg, 1);
  
    /* Strip baselink information.  */
!   if (BASELINK_P (arg))
!     arg = BASELINK_FUNCTIONS (arg);
  
    if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
      {
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.233
diff -c -p -r1.233 search.c
*** cp/search.c	1 Aug 2002 04:46:20 -0000	1.233
--- cp/search.c	8 Aug 2002 05:22:50 -0000
*************** lookup_base_r (binfo, base, access, with
*** 300,307 ****
     canonical).  If KIND_PTR is non-NULL, fill with information about
     what kind of base we discovered.
  
!    If ba_quiet bit is set in ACCESS, then do not issue an error, and
!    return NULL_TREE for failure.  */
  
  tree
  lookup_base (t, base, access, kind_ptr)
--- 300,309 ----
     canonical).  If KIND_PTR is non-NULL, fill with information about
     what kind of base we discovered.
  
!    If the base is inaccessible, or ambiguous, and the ba_quiet bit is
!    not set in ACCESS, then an error is issued and error_mark_node is
!    returned.  If the ba_quiet bit is set, then no error is issued and
!    NULL_TREE is returned.  */
  
  tree
  lookup_base (t, base, access, kind_ptr)
*************** build_baselink (tree binfo, tree access_
*** 1385,1393 ****
  		      || 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;
--- 1387,1396 ----
  		      || TREE_CODE (functions) == OVERLOAD,
  		      20020730);
    my_friendly_assert (!optype || TYPE_P (optype), 20020730);
+   my_friendly_assert (TREE_TYPE (functions), 20020805);
  
!   baselink = build (BASELINK, TREE_TYPE (functions), NULL_TREE,
! 		    NULL_TREE, NULL_TREE);
    BASELINK_BINFO (baselink) = binfo;
    BASELINK_ACCESS_BINFO (baselink) = access_binfo;
    BASELINK_FUNCTIONS (baselink) = functions;
*************** lookup_field (xbasetype, name, protect, 
*** 1522,1528 ****
    tree rval = lookup_member (xbasetype, name, protect, want_type);
    
    /* Ignore functions.  */
!   if (rval && TREE_CODE (rval) == TREE_LIST)
      return NULL_TREE;
  
    return rval;
--- 1525,1531 ----
    tree rval = lookup_member (xbasetype, name, protect, want_type);
    
    /* Ignore functions.  */
!   if (rval && BASELINK_P (rval))
      return NULL_TREE;
  
    return rval;
*************** lookup_fnfields (xbasetype, name, protec
*** 1539,1545 ****
    tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
  
    /* Ignore non-functions.  */
!   if (rval && TREE_CODE (rval) != TREE_LIST)
      return NULL_TREE;
  
    return rval;
--- 1542,1548 ----
    tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
  
    /* Ignore non-functions.  */
!   if (rval && !BASELINK_P (rval))
      return NULL_TREE;
  
    return rval;
*************** setup_class_bindings (name, type_binding
*** 2436,2442 ****
  	{
  	  if (BASELINK_P (value_binding))
  	    /* NAME is some overloaded functions.  */
! 	    value_binding = TREE_VALUE (value_binding);
  	  pushdecl_class_level (value_binding);
  	}
      }
--- 2439,2445 ----
  	{
  	  if (BASELINK_P (value_binding))
  	    /* NAME is some overloaded functions.  */
! 	    value_binding = BASELINK_FUNCTIONS (value_binding);
  	  pushdecl_class_level (value_binding);
  	}
      }
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.270
diff -c -p -r1.270 semantics.c
*** cp/semantics.c	1 Aug 2002 04:46:20 -0000	1.270
--- cp/semantics.c	8 Aug 2002 05:22:51 -0000
*************** finish_object_call_expr (fn, object, arg
*** 1400,1406 ****
  	}
      }
    
!   return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
  }
  
  /* Finish a qualified member function call using OBJECT and ARGS as
--- 1400,1409 ----
  	}
      }
    
!   if (name_p (fn))
!     return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
!   else
!     return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
  }
  
  /* Finish a qualified member function call using OBJECT and ARGS as
Index: cp/spew.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/spew.c,v
retrieving revision 1.70
diff -c -p -r1.70 spew.c
*** cp/spew.c	29 Jul 2002 10:37:25 -0000	1.70
--- cp/spew.c	8 Aug 2002 05:22:51 -0000
*************** identifier_type (decl)
*** 595,602 ****
    if (looking_for_template && really_overloaded_fn (decl))
      {
        /* See through a baselink.  */
!       if (TREE_CODE (decl) == TREE_LIST)
! 	decl = TREE_VALUE (decl);
  
        for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
  	if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
--- 595,602 ----
    if (looking_for_template && really_overloaded_fn (decl))
      {
        /* See through a baselink.  */
!       if (TREE_CODE (decl) == BASELINK)
! 	decl = BASELINK_FUNCTIONS (decl);
  
        for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
  	if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.290
diff -c -p -r1.290 tree.c
*** cp/tree.c	24 Jul 2002 23:01:07 -0000	1.290
--- cp/tree.c	8 Aug 2002 05:22:51 -0000
*************** really_overloaded_fn (x)
*** 965,971 ****
    if (BASELINK_P (x))
      x = BASELINK_FUNCTIONS (x);
    return (TREE_CODE (x) == OVERLOAD 
! 	  && (TREE_CHAIN (x) != NULL_TREE
  	      || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
  }
  
--- 965,971 ----
    if (BASELINK_P (x))
      x = BASELINK_FUNCTIONS (x);
    return (TREE_CODE (x) == OVERLOAD 
! 	  && (OVL_CHAIN (x)
  	      || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
  }
  
*************** cxx_unsave_expr_now (tp)
*** 2447,2454 ****
  }
  
  /* Returns the kind of special function that DECL (a FUNCTION_DECL)
!    is.  Note that this sfk_none is zero, so this function can be used
!    as a predicate to test whether or not DECL is a special function.  */
  
  special_function_kind
  special_function_p (decl)
--- 2447,2454 ----
  }
  
  /* Returns the kind of special function that DECL (a FUNCTION_DECL)
!    is.  Note that sfk_none is zero, so this function can be used as a
!    predicate to test whether or not DECL is a special function.  */
  
  special_function_kind
  special_function_p (decl)
*************** special_function_p (decl)
*** 2475,2480 ****
--- 2475,2496 ----
      return sfk_conversion;
  
    return sfk_none;
+ }
+ 
+ /* Returns true if and only if NODE is a name, i.e., a node created
+    by the parser when processing an id-expression.  */
+ 
+ bool
+ name_p (tree node)
+ {
+   if (TREE_CODE (node) == TEMPLATE_ID_EXPR)
+     node = TREE_OPERAND (node, 0);
+   return (/* An ordinary unqualified name.  */
+ 	  TREE_CODE (node) == IDENTIFIER_NODE
+ 	  /* A destructor name.  */
+ 	  || TREE_CODE (node) == BIT_NOT_EXPR
+ 	  /* A qualified name.  */
+ 	  || TREE_CODE (node) == SCOPE_REF);
  }
  
  /* Returns non-zero if TYPE is a character type, including wchar_t.  */
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.414
diff -c -p -r1.414 typeck.c
*** cp/typeck.c	1 Aug 2002 04:46:20 -0000	1.414
--- cp/typeck.c	8 Aug 2002 05:22:53 -0000
*************** string_conv_p (totype, exp, warn)
*** 1758,1802 ****
  
    return 1;
  }
- 
- tree
- build_object_ref (datum, basetype, field)
-      tree datum, basetype, field;
- {
-   tree dtype;
-   if (datum == error_mark_node)
-     return error_mark_node;
- 
-   dtype = TREE_TYPE (datum);
-   if (TREE_CODE (dtype) == REFERENCE_TYPE)
-     dtype = TREE_TYPE (dtype);
-   if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))
-     {
-       error ("request for member `%T::%D' in expression of non-aggregate type `%T'",
- 		basetype, field, dtype);
-       return error_mark_node;
-     }
-   else if (is_aggr_type (basetype, 1))
-     {
-       tree binfo = NULL_TREE;
-       datum = build_scoped_ref (datum, basetype, &binfo);
-       return build_x_component_ref (datum, field, binfo);
-     }
-   return error_mark_node;
- }
- 
- /* Like `build_component_ref, but uses an already found field, and converts
-    from a reference.  Must compute access for current_class_ref.
-    Otherwise, ok.  */
- 
- tree
- build_component_ref_1 (datum, field, protect)
-      tree datum, field;
-      int protect;
- {
-   return convert_from_reference
-     (build_component_ref (datum, field, NULL_TREE, protect));
- }
  
  /* Given a COND_EXPR, MIN_EXPR, or MAX_EXPR in T, return it in a form that we
     can, for example, use as an lvalue.  This code used to be in
--- 1758,1763 ----
*************** lookup_anon_field (t, type)
*** 1868,2209 ****
    return NULL_TREE;
  }
  
! /* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT.
!    COMPONENT can be an IDENTIFIER_NODE that is the name of the member
!    that we are interested in, or it can be a FIELD_DECL.  */
! 
! tree
! build_component_ref (datum, component, basetype_path, protect)
!      tree datum, component, basetype_path;
!      int protect;
! {
!   register tree basetype;
!   register enum tree_code code;
!   register tree field = NULL;
!   register tree ref;
!   tree field_type;
!   int type_quals;
!   tree old_datum;
!   tree old_basetype;
  
!   if (processing_template_decl)
!     return build_min_nt (COMPONENT_REF, datum, component);
!   
!   if (datum == error_mark_node 
!       || TREE_TYPE (datum) == error_mark_node)
      return error_mark_node;
  
!   /* BASETYPE holds the type of the class containing the COMPONENT.  */
!   basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
!     
!   /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
!      inside it.  */
!   switch (TREE_CODE (datum))
!     {
!     case COMPOUND_EXPR:
!       {
! 	tree value = build_component_ref (TREE_OPERAND (datum, 1), component,
! 					  basetype_path, protect);
! 	return build (COMPOUND_EXPR, TREE_TYPE (value),
! 		      TREE_OPERAND (datum, 0), value);
!       }
!     case COND_EXPR:
!       return build_conditional_expr
! 	(TREE_OPERAND (datum, 0),
! 	 build_component_ref (TREE_OPERAND (datum, 1), component,
! 			      basetype_path, protect),
! 	 build_component_ref (TREE_OPERAND (datum, 2), component,
! 			      basetype_path, protect));
! 
!     case TEMPLATE_DECL:
!       error ("invalid use of `%D'", datum);
!       datum = error_mark_node;
!       break;
! 
!     default:
!       break;
!     }
  
!   code = TREE_CODE (basetype);
  
!   if (code == REFERENCE_TYPE)
!     {
!       datum = convert_from_reference (datum);
!       basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
!       code = TREE_CODE (basetype);
!     }
!   if (TREE_CODE (datum) == OFFSET_REF)
      {
!       datum = resolve_offset_ref (datum);
!       basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
!       code = TREE_CODE (basetype);
      }
  
!   /* First, see if there is a field or component with name COMPONENT.  */
!   if (TREE_CODE (component) == TREE_LIST)
!     {
!       /* I could not trigger this code. MvL */
!       abort ();
! #ifdef DEAD
!       my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE
! 		&& DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
! #endif
!       return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
      }
! 
!   if (! IS_AGGR_TYPE_CODE (code))
      {
!       if (code != ERROR_MARK)
! 	error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
! 		  component, datum, basetype);
        return error_mark_node;
      }
  
!   if (!complete_type_or_else (basetype, datum))
!     return error_mark_node;
  
!   if (TREE_CODE (component) == BIT_NOT_EXPR)
!     {
!       if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0))
  	{
! 	  error ("destructor specifier `%T::~%T' must have matching names",
! 		    basetype, TREE_OPERAND (component, 0));
! 	  return error_mark_node;
  	}
!       if (! TYPE_HAS_DESTRUCTOR (basetype))
  	{
! 	  error ("type `%T' has no destructor", basetype);
  	  return error_mark_node;
  	}
-       return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1);
-     }
  
!   /* Look up component name in the structure type definition.  */
!   if (TYPE_VFIELD (basetype)
!       && DECL_NAME (TYPE_VFIELD (basetype)) == component)
!     /* Special-case this because if we use normal lookups in an ambiguous
!        hierarchy, the compiler will abort (because vptr lookups are
!        not supposed to be ambiguous.  */
!     field = TYPE_VFIELD (basetype);
!   else if (TREE_CODE (component) == FIELD_DECL)
!     field = component;
!   else if (TREE_CODE (component) == TYPE_DECL)
!     {
!       error ("invalid use of type decl `%#D' as expression", component);
!       return error_mark_node;
      }
!   else if (TREE_CODE (component) == TEMPLATE_DECL)
      {
!       error ("invalid use of template `%#D' as expression", component);
        return error_mark_node;
      }
-   else
-     {
-       tree name = component;
-       
-       if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
- 	name = TREE_OPERAND (component, 0);
-       else if (TREE_CODE (component) == VAR_DECL)
- 	name = DECL_NAME (component);
-       if (TREE_CODE (component) == NAMESPACE_DECL)
-         /* Source is in error, but produce a sensible diagnostic.  */
-         name = DECL_NAME (component);
-       if (basetype_path == NULL_TREE)
- 	basetype_path = TYPE_BINFO (basetype);
-       field = lookup_field (basetype_path, name,
- 			    protect && !VFIELD_NAME_P (name), 0);
-       if (field == error_mark_node)
- 	return error_mark_node;
  
!       if (field == NULL_TREE)
! 	{
! 	  /* Not found as a data field, look for it as a method.  If found,
! 	     then if this is the only possible one, return it, else
! 	     report ambiguity error.  */
! 	  tree fndecls = lookup_fnfields (basetype_path, name, 1);
! 	  if (fndecls == error_mark_node)
! 	    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)
! 		{
! 		  if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
! 		    {
! 		      tree fndecl = TREE_VALUE (fndecls);
! 		      enforce_access (basetype_path, fndecl);
! 		      mark_used (fndecl);
! 		      return fndecl;
! 		    }
! 		  else
! 		    {
! 		      /* A unique non-static member function.  Other parts
! 			 of the compiler expect something with
! 			 unknown_type_node to be really overloaded, so
! 			 let's oblige.  */
! 		      TREE_VALUE (fndecls)
! 			= ovl_cons (TREE_VALUE (fndecls), NULL_TREE);
! 		    }
! 		}
  
! 	      fndecls = TREE_VALUE (fndecls);
! 	      
!  	      if (IDENTIFIER_TYPENAME_P (name))
!  		{
!  		  /* We want for a conversion op. We need to remember
!  		     the actual type we wanted, in case we got a set of
!  		     templated conversion operators back.  */
!  		  fndecls = ovl_cons (OVL_CURRENT (fndecls),
!  				      OVL_NEXT (fndecls));
!  		  TREE_TYPE (fndecls) = TREE_TYPE (name);
!  		}
! 	      else if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
! 		fndecls = build_nt (TEMPLATE_ID_EXPR,
! 				    fndecls, TREE_OPERAND (component, 1));
! 	      
! 	      ref = build (COMPONENT_REF, unknown_type_node,
! 			   datum, fndecls);
! 	      return ref;
! 	    }
  
! 	  error ("`%#T' has no member named `%D'", basetype, name);
! 	  return error_mark_node;
! 	}
!       else if (TREE_TYPE (field) == error_mark_node)
! 	return error_mark_node;
  
!       if (TREE_CODE (field) != FIELD_DECL)
! 	{
! 	  if (TREE_CODE (field) == TYPE_DECL)
! 	    pedwarn ("invalid use of type decl `%#D' as expression", field);
! 	  else if (DECL_RTL (field) != 0)
! 	    mark_used (field);
! 	  else
! 	    TREE_USED (field) = 1;
  
! 	  /* Do evaluate the object when accessing a static member.  */
! 	  if (TREE_SIDE_EFFECTS (datum))
! 	    field = build (COMPOUND_EXPR, TREE_TYPE (field), datum, field);
  
! 	  return field;
! 	}
      }
  
!   if (TREE_DEPRECATED (field))
!     warn_deprecated_use (field);
  
!   old_datum = datum;
!   old_basetype = basetype;
  
!   /* See if we have to do any conversions so that we pick up the field from the
!      right context.  */
!   if (DECL_FIELD_CONTEXT (field) != basetype)
!     {
!       tree context = DECL_FIELD_CONTEXT (field);
!       tree base = context;
!       while (!same_type_p (base, basetype) && TYPE_NAME (base)
! 	     && ANON_AGGR_TYPE_P (base))
! 	base = TYPE_CONTEXT (base);
  
!       /* Handle base classes here...  */
!       if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
  	{
! 	  base_kind kind;
!  	  tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, &kind);
  
! 	  /* Complain about use of offsetof which will break.  */
! 	  if (TREE_CODE (datum) == INDIRECT_REF
! 	      && integer_zerop (TREE_OPERAND (datum, 0))
! 	      && kind == bk_via_virtual)
! 	    {
! 	      error ("\
! invalid offsetof from non-POD type `%#T'; use pointer to member instead",
! 		     basetype);
  	      return error_mark_node;
  	    }
!  	  datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
! 	  if (datum == error_mark_node)
  	    return error_mark_node;
  	}
!       basetype = base;
!  
!       /* Handle things from anon unions here...  */
!       if (TYPE_NAME (context) && ANON_AGGR_TYPE_P (context))
! 	{
! 	  tree subfield = lookup_anon_field (basetype, context);
! 	  tree subdatum = build_component_ref (datum, subfield,
! 					       basetype_path, protect);
! 	  return build_component_ref (subdatum, field, basetype_path, protect);
  	}
      }
  
!   /* Complain about other invalid uses of offsetof, even though they will
!      give the right answer.  Note that we complain whether or not they
!      actually used the offsetof macro, since there's no way to know at this
!      point.  So we just give a warning, instead of a pedwarn.  */
!   if (protect
!       && CLASSTYPE_NON_POD_P (old_basetype)
!       && TREE_CODE (old_datum) == INDIRECT_REF
!       && integer_zerop (TREE_OPERAND (old_datum, 0)))
!     warning ("\
! invalid offsetof from non-POD type `%#T'; use pointer to member instead",
! 	     basetype);
! 
!   /* Compute the type of the field, as described in [expr.ref].  */
!   type_quals = TYPE_UNQUALIFIED;
!   field_type = TREE_TYPE (field);
!   if (TREE_CODE (field_type) == REFERENCE_TYPE)
!     /* The standard says that the type of the result should be the
!        type referred to by the reference.  But for now, at least, we
!        do the conversion from reference type later.  */
!     ;
!   else
!     {
!       type_quals = (cp_type_quals (field_type)  
! 		    | cp_type_quals (TREE_TYPE (datum)));
! 
!       /* A field is const (volatile) if the enclosing object, or the
! 	 field itself, is const (volatile).  But, a mutable field is
! 	 not const, even within a const object.  */
!       if (DECL_MUTABLE_P (field))
! 	type_quals &= ~TYPE_QUAL_CONST;
!       field_type = cp_build_qualified_type (field_type, type_quals);
!     }
! 
!   ref = fold (build (COMPONENT_REF, field_type, datum, field));
! 
!   /* Mark the expression const or volatile, as appropriate.  Even
!      though we've dealt with the type above, we still have to mark the
!      expression itself.  */
!   if (type_quals & TYPE_QUAL_CONST)
!     TREE_READONLY (ref) = 1;
!   else if (type_quals & TYPE_QUAL_VOLATILE)
!     TREE_THIS_VOLATILE (ref) = 1;
! 
!   return ref;
  }
  
! /* Variant of build_component_ref for use in expressions, which should
!    never have REFERENCE_TYPE.  */
! 
! tree
! build_x_component_ref (datum, component, basetype_path)
!      tree datum, component, basetype_path;
! {
!   tree t = build_component_ref (datum, component, basetype_path, 
! 				/*protect=*/1);
! 
!   if (! processing_template_decl)
!     t = convert_from_reference (t);
! 
!   return t;
  }
! 
  /* Given an expression PTR for a pointer, return an expression
     for the value pointed to.
     ERRORSTRING is the name of the operator to appear in error messages.
--- 1829,2234 ----
    return NULL_TREE;
  }
  
! /* Build an expression representing OBJECT.MEMBER.  OBJECT is an
!    expression; MEMBER is a DECL or baselink.  If ACCESS_PATH is
!    non-NULL, it indicates the path to the base used to name MEMBER.
!    If PRESERVE_REFERENCE is true, the expression returned will have
!    REFERENCE_TYPE if the MEMBER does.  Otherwise, the expression
!    returned will have the type referred to by the reference. 
! 
!    This function does not perform access control; that is either done
!    earlier by the parser when the name of MEMBER is resolved to MEMBER
!    itself, or later when overload resolution selects one of the
!    functions indicated by MEMBER.  */
! 
! tree
! build_class_member_access_expr (tree object, tree member, 
! 				tree access_path, bool preserve_reference)
! {
!   tree object_type;
!   tree member_scope;
!   tree result = NULL_TREE;
  
!   if (object == error_mark_node || member == error_mark_node)
      return error_mark_node;
  
!   my_friendly_assert (DECL_P (member) || BASELINK_P (member),
! 		      20020801);
  
!   /* [expr.ref]
  
!      The type of the first expression shall be "class object" (of a
!      complete type).  */
!   object_type = TREE_TYPE (object);
!   if (!complete_type_or_else (object_type, object))
!     return error_mark_node;
!   if (!CLASS_TYPE_P (object_type))
      {
!       error ("request for member `%D' in `%E', which is of non-class type `%T'", 
! 	     member, object, object_type);
!       return error_mark_node;
      }
  
!   /* The standard does not seem to actually say that MEMBER must be a
!      member of OBJECT_TYPE.  However, that is clearly what is
!      intended.  */
!   if (DECL_P (member))
!     {
!       member_scope = DECL_CLASS_CONTEXT (member);
!       mark_used (member);
!       if (TREE_DEPRECATED (member))
! 	warn_deprecated_use (member);
      }
!   else
!     member_scope = BINFO_TYPE (BASELINK_BINFO (member));
!   /* If MEMBER is from an anonymous aggregate, MEMBER_SCOPE will
!      presently be the anonymous union.  Go outwards until we find a
!      type related to OBJECT_TYPE.  */
!   while (ANON_AGGR_TYPE_P (member_scope)
! 	 && !same_type_ignoring_top_level_qualifiers_p (member_scope,
! 							object_type))
!     member_scope = TYPE_CONTEXT (member_scope);
!   if (!member_scope || !DERIVED_FROM_P (member_scope, object_type))
      {
!       error ("`%D' is not a member of `%T'", member, object_type);
        return error_mark_node;
      }
  
!   /* In [expr.ref], there is an explicit list of the valid choices for
!      MEMBER.  We check for each of those cases here.  */
!   if (TREE_CODE (member) == VAR_DECL)
!     {
!       /* A static data member.  */
!       result = member;
!       /* If OBJECT has side-effects, they are supposed to occur.  */
!       if (TREE_SIDE_EFFECTS (object))
! 	result = build (COMPOUND_EXPR, TREE_TYPE (result), object, result);
!     }
!   else if (TREE_CODE (member) == FIELD_DECL)
!     {
!       /* A non-static data member.  */
!       bool null_object_p;
!       int type_quals;
!       tree member_type;
  
!       null_object_p = (TREE_CODE (object) == INDIRECT_REF
! 		       && integer_zerop (TREE_OPERAND (object, 0)));
! 
!       /* Convert OBJECT to the type of MEMBER.  */
!       if (!same_type_p (object_type, member_scope))
  	{
! 	  tree binfo;
! 	  base_kind kind;
! 
! 	  binfo = lookup_base (access_path ? access_path : object_type,
! 			       member_scope, ba_ignore,  &kind);
! 	  if (binfo == error_mark_node)
! 	    return error_mark_node;
! 
! 	  /* It is invalid to use to try to get to a virtual base of a
! 	     NULL object.  The most common cause is invalid use of
! 	     offsetof macro.  */
! 	  if (null_object_p && kind == bk_via_virtual)
! 	    {
! 	      error ("invalid access to non-static data member `%D' of NULL object",
! 		     member);
! 	      error ("(perhaps the `offsetof' macro was used incorrectly)");
! 	      return error_mark_node;
! 	    }
! 
! 	  /* Convert to the base.  */
! 	  object = build_base_path (PLUS_EXPR, object, binfo, 
! 				    /*nonnull=*/1);
! 	  /* If we found the base successfully then we should be able
! 	     to convert to it successfully.  */
! 	  my_friendly_assert (object != error_mark_node,
! 			      20020801);
  	}
!       
!       /* Issue a warning about access a member of a NULL object.  */
!       if (null_object_p && CLASSTYPE_NON_POD_P (object_type))
  	{
! 	  warning ("invalid access to non-static data member `%D' of NULL object", 
! 		   member);
! 	  warning  ("(perhaps the `offsetof' macro was used incorrectly)");
  	  return error_mark_node;
  	}
  
!       /* If MEMBER is from an anonymous aggregate, we have converted
! 	 OBJECT so that it refers to the class containing the
! 	 anonymous union.  Generate a reference to the anonymous union
! 	 itself, and recur to find MEMBER.  */
!       if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member)))
! 	{
! 	  tree anonymous_union;
! 
! 	  anonymous_union = lookup_anon_field (TREE_TYPE (object),
! 					       DECL_CONTEXT (member));
! 	  object = build_class_member_access_expr (object,
! 						   anonymous_union,
! 						   /*access_path=*/NULL_TREE,
! 						   preserve_reference);
! 	}
! 
!       /* Compute the type of the field, as described in [expr.ref].  */
!       type_quals = TYPE_UNQUALIFIED;
!       member_type = TREE_TYPE (member);
!       if (TREE_CODE (member_type) != REFERENCE_TYPE)
! 	{
! 	  type_quals = (cp_type_quals (member_type)  
! 			| cp_type_quals (object_type));
! 	  
! 	  /* A field is const (volatile) if the enclosing object, or the
! 	     field itself, is const (volatile).  But, a mutable field is
! 	     not const, even within a const object.  */
! 	  if (DECL_MUTABLE_P (member))
! 	    type_quals &= ~TYPE_QUAL_CONST;
! 	  member_type = cp_build_qualified_type (member_type, type_quals);
! 	}
! 
!       result = fold (build (COMPONENT_REF, member_type, object, member));
! 
!       /* Mark the expression const or volatile, as appropriate.  Even
! 	 though we've dealt with the type above, we still have to mark the
! 	 expression itself.  */
!       if (type_quals & TYPE_QUAL_CONST)
! 	TREE_READONLY (result) = 1;
!       else if (type_quals & TYPE_QUAL_VOLATILE)
! 	TREE_THIS_VOLATILE (result) = 1;
!     }
!   else if (BASELINK_P (member))
!     {
!       /* The member is a (possibly overloaded) member function.  */
!       tree functions;
! 
!       /* If the MEMBER is exactly one static member function, then we
! 	 know the type of the expression.  Otherwise, we must wait
! 	 until overload resolution has been performed.  */
!       functions = BASELINK_FUNCTIONS (member);
!       if (TREE_CODE (functions) == FUNCTION_DECL
! 	  && DECL_STATIC_FUNCTION_P (functions))
! 	{
! 	  /* A static member function.  */
! 	  result = functions;
! 	  mark_used (result);
! 	  /* If OBJECT has side-effects, they are supposed to occur.  */
! 	  if (TREE_SIDE_EFFECTS (object))
! 	    result = build (COMPOUND_EXPR, TREE_TYPE (result),
! 			    object, result);
! 	}
!       else
! 	/* Note that we do not convert OBJECT to the BASELINK_BINFO
! 	   base.  That will happen when the function is called.  */
! 	result = build (COMPONENT_REF, unknown_type_node, object, member);
!     }
!   else if (TREE_CODE (member) == CONST_DECL)
!     {
!       /* The member is an enumerator.  */
!       result = member;
!       /* If OBJECT has side-effects, they are supposed to occur.  */
!       if (TREE_SIDE_EFFECTS (object))
! 	result = build (COMPOUND_EXPR, TREE_TYPE (result),
! 			object, result);
      }
!   else
      {
!       error ("invalid use of `%D'", member);
        return error_mark_node;
      }
  
!   if (!preserve_reference)
!     /* [expr.ref]
!        
!        If E2 is declared to have type "reference to T", then ... the
!        type of E1.E2 is T.  */
!     result = convert_from_reference (result);
  
!   return result;
! }
  
! /* This function is called by the parser to process a class member
!    access expression of the form OBJECT.NAME.  NAME is a node used by
!    the parser to represent a name; it is not yet a DECL.  It may,
!    however, be a BASELINK where the BASELINK_FUNCTIONS is a
!    TEMPLATE_ID_EXPR.  Templates must be looked up by the parser, and
!    there is no reason to do the lookup twice, so the parser keeps the
!    BASELINK.  */
  
! tree
! finish_class_member_access_expr (tree object, tree name)
! {
!   tree object_type;
!   tree member;
!   tree access_path = NULL_TREE;
  
!   if (object == error_mark_node || name == error_mark_node)
!     return error_mark_node;
  
!   if (processing_template_decl)
!     return build_min_nt (COMPONENT_REF, object, name);
!   
!   if (TREE_CODE (object) == OFFSET_REF)
!     object = resolve_offset_ref (object);
! 
!   object_type = TREE_TYPE (object);
!   if (TREE_CODE (object_type) == REFERENCE_TYPE)
!     {
!       object = convert_from_reference (object);
!       object_type = TREE_TYPE (object);
      }
  
!   /* [expr.ref]
  
!      The type of the first expression shall be "class object" (of a
!      complete type).  */
!   if (!complete_type_or_else (object_type, object))
!     return error_mark_node;
!   if (!CLASS_TYPE_P (object_type))
!     {
!       error ("request for member `%D' in `%E', which is of non-class type `%T'", 
! 	     name, object, object_type);
!       return error_mark_node;
!     }
  
!   if (BASELINK_P (name))
!     {
!       /* A member function that has already been looked up.  */
!       my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name)) 
! 			   == TEMPLATE_ID_EXPR), 
! 			  20020805);
!       member = name;
!     }
!   else
!     {
!       bool is_template_id = false;
!       tree template_args = NULL_TREE;
  
!       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
  	{
! 	  is_template_id = true;
! 	  template_args = TREE_OPERAND (name, 1);
! 	  name = TREE_OPERAND (name, 0);
! 	}
! 
!       if (TREE_CODE (name) == SCOPE_REF)
! 	{
! 	  tree scope;
! 
! 	  /* A qualified name.  The qualifying class or namespace `S' has
! 	     already been looked up; it is either a TYPE or a
! 	     NAMESPACE_DECL.  The member name is either an IDENTIFIER_NODE
! 	     or a BIT_NOT_EXPR.  */
! 	  scope = TREE_OPERAND (name, 0);
! 	  name = TREE_OPERAND (name, 1);
! 	  my_friendly_assert ((CLASS_TYPE_P (scope) 
! 			       || TREE_CODE (scope) == NAMESPACE_DECL),
! 			      20020804);
! 	  my_friendly_assert ((TREE_CODE (name) == IDENTIFIER_NODE
! 			       || TREE_CODE (name) == BIT_NOT_EXPR),
! 			      20020804);
! 
! 	  /* If SCOPE is a namespace, then the qualified name does not
! 	     name a member of OBJECT_TYPE.  */
! 	  if (TREE_CODE (scope) == NAMESPACE_DECL)
! 	    {
! 	      error ("`%D::%D' is not a member of `%T'", 
! 		     scope, member, object_type);
! 	      return error_mark_node;
! 	    }
! 
! 	  /* Find the base of OBJECT_TYPE corresponding to SCOPE.  */
! 	  access_path = lookup_base (object_type, scope, ba_check, NULL);
! 	  if (!access_path || access_path == error_mark_node)
! 	    return error_mark_node;
  
! 	  /* Look up the member.  */
! 	  member = lookup_member (access_path, name, /*protect=*/1, 
! 				  /*want_type=*/0);
! 	  if (member == error_mark_node)
! 	    return error_mark_node;
! 	}
!       else if (TREE_CODE (name) == BIT_NOT_EXPR)
! 	{
! 	  /* A destructor.  */
! 	  if (TYPE_IDENTIFIER (object_type) != TREE_OPERAND (name, 0))
! 	    {
! 	      error ("destructor specifier `%T::~%T' must have matching names",
! 		     object_type, TREE_OPERAND (name, 0));
  	      return error_mark_node;
  	    }
! 	  if (! TYPE_HAS_DESTRUCTOR (object_type))
! 	    {
! 	      error ("type `%T' has no destructor", object_type);
! 	      return error_mark_node;
! 	    }
! 	  member = CLASSTYPE_DESTRUCTORS (object_type);
! 	}
!       else if (TREE_CODE (name) == IDENTIFIER_NODE)
! 	{
! 	  /* An unqualified name.  */
! 	  member = lookup_member (object_type, name, /*protect=*/1, 
! 				  /*want_type=*/0);
! 	  if (member == error_mark_node)
  	    return error_mark_node;
  	}
!       else
! 	{
! 	  /* The YACC parser sometimes gives us things that are not names.
! 	     These always indicate errors.  The recursive-descent parser
! 	     does not do this, so this code can go away once that parser
! 	     replaces the YACC parser.  */
! 	  error ("invalid use of `%D'", name);
! 	  return error_mark_node;
! 	}
!       
!       if (is_template_id)
! 	{
! 	  tree template = member;
! 	  
! 	  if (BASELINK_P (template))
! 	    BASELINK_FUNCTIONS (template) 
! 	      = build_nt (TEMPLATE_ID_EXPR,
! 			  BASELINK_FUNCTIONS (template),
! 			  template_args);
! 	  else
! 	    {
! 	      error ("`%D' is not a member template function", name);
! 	      return error_mark_node;
! 	    }
  	}
      }
  
!   return build_class_member_access_expr (object, member, access_path,
! 					 /*preserve_reference=*/false);
  }
  
! /* Return an expression for the MEMBER_NAME field in the internal
!    representation of PTRMEM, a pointer-to-member function.  (Each
!    pointer-to-member function type gets its own RECORD_TYPE so it is
!    more convenient to access the fields by name than by FIELD_DECL.)
!    This routine converts the NAME to a FIELD_DECL and then creates the
!    node for the complete expression.  */
! 
! tree
! build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
! {
!   tree ptrmem_type;
!   tree member;
!   tree member_type;
! 
!   /* This code is a stripped down version of
!      build_class_member_access_expr.  It does not work to use that
!      routine directly because it expects the object to be of class
!      type.  */
!   ptrmem_type = TREE_TYPE (ptrmem);
!   my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
!   member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
! 			  /*want_type=*/0);
!   member_type = cp_build_qualified_type (TREE_TYPE (member),
! 					 cp_type_quals (ptrmem_type));
!   return fold (build (COMPONENT_REF, member_type, ptrmem, member));
  }
! 
  /* Given an expression PTR for a pointer, return an expression
     for the value pointed to.
     ERRORSTRING is the name of the operator to appear in error messages.
*************** get_member_function_from_ptrfunc (instan
*** 2505,2511 ****
  
        /* Start by extracting all the information from the PMF itself.  */
        e3 = PFN_FROM_PTRMEMFUNC (function);
!       delta = build_component_ref (function, delta_identifier, NULL_TREE, 0);
        idx = build1 (NOP_EXPR, vtable_index_type, e3);
        switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
  	{
--- 2530,2536 ----
  
        /* Start by extracting all the information from the PMF itself.  */
        e3 = PFN_FROM_PTRMEMFUNC (function);
!       delta = build_ptrmemfunc_access_expr (function, delta_identifier);
        idx = build1 (NOP_EXPR, vtable_index_type, e3);
        switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
  	{
*************** build_binary_op (code, orig_op0, orig_op
*** 3219,3225 ****
  	}
        else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
  	{
! 	  op0 = build_component_ref (op0, pfn_identifier, NULL_TREE, 0);
  	  op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
  	  result_type = TREE_TYPE (op0);
  	}
--- 3244,3250 ----
  	}
        else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
  	{
! 	  op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
  	  op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
  	  result_type = TREE_TYPE (op0);
  	}
*************** build_binary_op (code, orig_op0, orig_op
*** 3253,3262 ****
  	     DELTA field is unspecified.  */
  	  pfn0 = pfn_from_ptrmemfunc (op0);
  	  pfn1 = pfn_from_ptrmemfunc (op1);
! 	  delta0 = build_component_ref (op0, delta_identifier,
! 					NULL_TREE, 0);
! 	  delta1 = build_component_ref (op1, delta_identifier,
! 					NULL_TREE, 0);
  	  e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
  	  e2 = cp_build_binary_op (EQ_EXPR, 
  				   pfn0,
--- 3278,3287 ----
  	     DELTA field is unspecified.  */
  	  pfn0 = pfn_from_ptrmemfunc (op0);
  	  pfn1 = pfn_from_ptrmemfunc (op1);
! 	  delta0 = build_ptrmemfunc_access_expr (op0,
! 						 delta_identifier);
! 	  delta1 = build_ptrmemfunc_access_expr (op1,
! 						 delta_identifier);
  	  e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
  	  e2 = cp_build_binary_op (EQ_EXPR, 
  				   pfn0,
*************** build_unary_op (code, xarg, noconvert)
*** 4172,4178 ****
  	}
  
        if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
!           && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
          {
  	  /* They're trying to take the address of a unique non-static
  	     member function.  This is ill-formed (except in MS-land),
--- 4197,4203 ----
  	}
  
        if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
! 	  && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
          {
  	  /* They're trying to take the address of a unique non-static
  	     member function.  This is ill-formed (except in MS-land),
*************** build_unary_op (code, xarg, noconvert)
*** 4185,4191 ****
  	     a useful error here.  */
  
  	  tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
! 	  tree name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
  
  	  if (! flag_ms_extensions)
  	    {
--- 4210,4216 ----
  	     a useful error here.  */
  
  	  tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
! 	  tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1)));
  
  	  if (! flag_ms_extensions)
  	    {
*************** build_ptrmemfunc (type, pfn, force)
*** 5578,5585 ****
  	expand_ptrmemfunc_cst (pfn, &delta, &npfn);
        else
  	{
! 	  npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0);
! 	  delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0);
  	}
  
        /* Just adjust the DELTA field.  */
--- 5603,5610 ----
  	expand_ptrmemfunc_cst (pfn, &delta, &npfn);
        else
  	{
! 	  npfn = build_ptrmemfunc_access_expr (pfn, pfn_identifier);
! 	  delta = build_ptrmemfunc_access_expr (pfn, delta_identifier);
  	}
  
        /* Just adjust the DELTA field.  */
*************** pfn_from_ptrmemfunc (t)
*** 5694,5700 ****
  	return pfn;
      }
  
!   return build_component_ref (t, pfn_identifier, NULL_TREE, 0);
  }
  
  /* Expression EXPR is about to be implicitly converted to TYPE.  Warn
--- 5719,5725 ----
  	return pfn;
      }
  
!   return build_ptrmemfunc_access_expr (t, pfn_identifier);
  }
  
  /* Expression EXPR is about to be implicitly converted to TYPE.  Warn
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.125
diff -c -p -r1.125 typeck2.c
*** cp/typeck2.c	1 Aug 2002 04:46:21 -0000	1.125
--- cp/typeck2.c	8 Aug 2002 05:22:53 -0000
*************** build_m_component_ref (datum, component)
*** 1196,1203 ****
  			| cp_type_quals (TREE_TYPE (datum)));
  
  	  /* There's no such thing as a mutable pointer-to-member, so
! 	     we don't need to deal with that here like we do in
! 	     build_component_ref.  */
  	  field_type = cp_build_qualified_type (field_type, type_quals);
  	}
      }
--- 1196,1203 ----
  			| cp_type_quals (TREE_TYPE (datum)));
  
  	  /* There's no such thing as a mutable pointer-to-member, so
! 	     things are not as complex as they are for references to
! 	     non-static data members.  */
  	  field_type = cp_build_qualified_type (field_type, type_quals);
  	}
      }
Index: testsuite/g++.dg/abi/offsetof.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/abi/offsetof.C,v
retrieving revision 1.2
diff -c -p -r1.2 offsetof.C
*** testsuite/g++.dg/abi/offsetof.C	4 Feb 2002 18:27:59 -0000	1.2
--- testsuite/g++.dg/abi/offsetof.C	8 Aug 2002 05:22:53 -0000
*************** struct C: public B { };
*** 18,22 ****
  
  int main ()
  {
!   return ((unsigned long) &((C*)0)->i) != sizeof(void*); // { dg-warning "offsetof" "" }
  }
--- 18,22 ----
  
  int main ()
  {
!   return ((unsigned long) &((C*)0)->i) != sizeof(void*); // { dg-warning "offsetof|invalid" "" }
  }
Index: testsuite/g++.old-deja/g++.mike/p10769a.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C,v
retrieving revision 1.7
diff -c -p -r1.7 p10769a.C
*** testsuite/g++.old-deja/g++.mike/p10769a.C	26 Jul 1999 08:18:05 -0000	1.7
--- testsuite/g++.old-deja/g++.mike/p10769a.C	8 Aug 2002 05:22:54 -0000
*************** class A {
*** 9,15 ****
  public:
    void f1a() { ok += 3; }
    void f1b() { ok += 5; }
!   void f2a() { ok += 7; }	// gets bogus error XFAIL *-*-*
    void f2b() { }
    static void (*table[2][2])();
    void main();
--- 9,15 ----
  public:
    void f1a() { ok += 3; }
    void f1b() { ok += 5; }
!   void f2a() { ok += 7; }
    void f2b() { }
    static void (*table[2][2])();
    void main();


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