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]

[PATCH]: Change base access representation, [c++]share virtual binfos


Hi,
this patch does two things
1) changes the representation of access to base binfos from
TREE_VIA_{public,private,protected}, to use a vector of base access nodes
in the derived binfo. This affects the common code, java & c++ frontends.

2) (c++) Use a single binfo for a virtual base, rather than unshared
duplicates for each instance of a virtual base. Thus the data structure
more closely matches language concepts. We get rid of all the
canonical_binfo crud.

booted & tested on i686-pc-linux-gnu, ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
         The voices in my head said this was stupid too
nathan at codesourcery dot com : http://www.cs.bris.ac.uk/~nathan/ : nathan at acm dot org

2003-02-18  Nathan Sidwell  <nathan at codesourcery dot com>

	Change base class access representation.
	* tree.h (TREE_VIA_PUBLIC, TREE_VIA_PROTECTED,
	TREE_VIA_PRIVATE): Remove.
	(BINFO_BASEACCESSES): New binfo elt.
	(BINFO_BASEACCESS): New accessor.
	(BINFO_ELTS): Increase.
	(TI_ACCESS_PUBLIC, TI_ACCESS_PROTECTED, TI_ACCESS_PRIVATE): New.
	(access_public_node, access_protected_node,
	access_private_node): New global nodes.
	* tree.c (build_common_tree_nodes_2): Initialize access nodes.
	* dbxout.c (dbxout_type): Adjust.
	* dwarf2out.c (gen_inheritance_die): Add access parameter.
	(gen_member_die): Adjust.
	* dwarfout.c (output_inheritance_die): ARG is array of two trees.
	(output_type): Adjust.
	* tree-dump.c (dequeue_and_dump): Adjust binfo dumping.

	Change base class access representation. Share virtual base
	binfos.
	* cp/call.c (build_special_member_call): Remove binfo_for_vbase
	call.
	* cp/class.c (build_base_path): Likewise.
	(build_primary_vtable): Adjust BINFO_NEW_VTABLE_MARKED use.
	(build_secondary_vtable): Remove FOR_TYPE arg. Adjust.
	(make_new_vtable): Adjust.
	(force_canonical_binfo_r): Delete.
	(force_canonical_binfo): Delete.
	(mark_primary_virtual_base): Delete.
	(dfs_unshared_virtual_bases): Delete.
	(mark_primary_bases): Adjust.
	(maybe_warn_about_overly_private_class): Adjust.
	(dfs_base_derived_from): Delete.
	(base_derived_from): Follow the inheritance chain.
	(struct find_final_overrider_data): Add vpath member.
	(dfs_find_final_overrider): Adjust.
	(dfs_find_final_overrider_q, dfs_find_final_overrider_post): New.
	(find_final_overrider): Adjust.
	(update_vtable_entry_for_fn): Adjust.
	(modify_all_vtables): Adjust.
	(walk_subobject_offsets): Adjust.
	(layout_nonempty_base_or_field): Adjust.
	(layout_empty_base): Remove last parameter. Adjust.
	(build_base_field): Adjust.
	(build_base_fields): Adjust.
	(propagate_binfo_offsets): Remove last parameter. Adjust.
	(dfs_set_offset_for_unshared_vbases): Delete.
	(layout_virtual_bases): Adjust.
	(finish_struct_1): Adjust.
	(init_class_processing): Don't init access nodes.
	(dfs_get_primary_binfo): Delete.
	(get_primary_binfo): Adjust.
	(dump_class_hierarchy_r): Remove most derived arg, add IGO
	parameter. Adjust.
	(dump_class_hierarchy): Adjust.
	(finish_vtbls): Adjust.
	(get_original_base): Delete.
	(build_vtt_inits): Adjust.
	(dfs_build_secondary_vptr_vtt_inits): Adjust.
	(dfs_ctor_vtable_bases_queue_p): Adjust.
	(build_ctor_vtbl_group): Adjust.
	(dfs_accumulate_vtbl_inits): Adjust.
	(build_vtbl_initializer): Adjust.
	(build_vbase_offset_vtbl_entries): Adjust.
	(add_vcall_offset_vtbl_entries_1): Adjust.
	* cp/cp-tree.h (CPTI_ACCESS_*): Remove.
	(access_*_node): Remove.
	(CANONICAL_BINFO): Delete.
	(BINFO_UNSHARED_MARKED): Remove.
	(BINFO_MARKED): Set LANG_FLAG_0 directly.
	(SET_BINFO_MARKED, CLEAR_BINFO_MARKED): Delete.
	(BINFO_VTABLE_PATH_MARKED): Set LANG_FLAG_3 directly.
	(SET_BINFO_VTABLE_PATH_MARKED, CLEAR_BINFO_VTABLE_PATH_MARKED):
	Delete.
	(BINFO_NEW_VTABLE_MARKED): Set LANG_FLAG_4 directly.
	(SET_BINFO_NEW_VTABLE_MARKED): Adjust.
	(SET_BINFO_PUSHDECLS_MARKED, CLEAR_BINFO_PUSHDECLS_MARKED):
	Delete.
	(BINFO_DEPENDENT_BASE_P): New.
	(dfs_walk, dfs_walk_real): Queue function takes derived binfo and
	index.
	(markedp, unmarkedp): Adjust.
	(dfs_unmarked_real_bases_queue_p, dfs_marked_real_bases_queue_p,
	dfs_skip_vbases, marked_vtable_pathp, unmarked_vtable_pathp,
	find_vbase_instance, binfo_for_vbase): Delete.
	(copied_binfo, original_binfo): Declare.
	(finish_base_specifier): Add virtual_p arg.
	(unshare_base_binfos): Delete.
	(copy_base_binfos): Declare.
	(reverse_path): Delete.
	* cp/decl.c (xref_basetypes): Access and virtuality passed
	differently. Don't copy direct base binfos here. Call
	copy_base_binfos.
	* cp/init.c (dfs_initialize_vtbl_ptrs): Adjust.
	(initialize_vtbl_ptrs): Adjust.
	(expand_member_init): Adjust.
	* cp/parser.c (cp_parser_base_specifier): Adjust.
	* cp/pt.c (instantiate_class_template): Adjust.
	(get_template_base_recursive): Adjust.
	* cp/rtti.c (get_pseudo_ti_init): Adjust.
	(get_pseudo_ti_desc): Adjust.
	* cp/tree.c (unshare_base_binfos): Rename to ...
	(copy_base_binfos): ... here, reimplement.
	(make_binfo): Set BINFO_DEPENDENT_BASE_P.
	(reverse_path): Remove.
	* cp/typeck.c (get_delta_difference): Adjust error messages.
	* cp/semantics.c (finish_base_specifier): Add virtual arg, adjust.

	* cp/search.c (lookup_base_r): Adjust.
	(dynamic_cast_base_recurse): Adjust.
	(canonical_binfo): Remove.
	(dfs_canonical_queue): Remove.
	(dfs_assert_unmarked_p): Remove.
	(assert_canonical_unmarked): Remove.
	(shared_marked_p, shared_unmarked_p): Remove.
	(BINFO_ACCESS, SET_BINFO_ACCESS): Use TREE_PUBLIC & TREE_PRIVATE.
	(dfs_access_in_type): Adjust.
	(access_in_type): Adjust.
	(dfs_accessible_queue_p): Adjust.
	(dfs_accessible_p): Adjust.
	(is_subobject_of_p_1, is_subobject_of_p): Remove.
	(struct lookup_field_info): Remove from_dep_base_p field.
	(lookup_field_queue_p): Adjust, test BINFO_DEPENDENT_BASE_P.
	(lookup_field_r): Remove dependent base code.
	(lookup_member): Likewise.
	(dfs_walk, dfs_walk_real): Add access arg to queue fn.
	(dfs_unmarked_real_bases_queue_p): Remove.
	(dfs_marked_real_bases_queue_p): Remove.
	(dfs_skip_vbases): Remove.
	(dfs_get_pure_virtuals): Adjust.
	(markedp, unmarkedp): Adjust.
	(marked_vtable_pathp, unmarked_vtable_pathp): Remove.
	(marked_pushdecls_p, unmarked_pushdecls_p): Adjust.
	(dfs_unmark): Adjust.
	(dfs_get_vbase_types):Remove.
	(dfs_build_inheritance_graph_order): Remove.
	(get_vbase_types): Remove
	(dfs_find_vbase_instance): Remove.
	(find_vbase_instance): Remove.
	(dfs_debug_unmarkedp): Adjust.
	(dependent_base_p): Remove.
	(dfs_push_type_decls): Adjust.
	(dfs_push_decls): Adjust.
	(dfs_no_overlap_yet): Adjust.
	(copied_binfo): New function.
	(original_binfo): New function.
	(binfo_for_vbase): Remove.

	Change base class access representation.
	* java/class.c (set_super_info): Don't set TREE_VIA_PUBLIC.
	(add_interface_do): Likewise.

Index: dbxout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dbxout.c,v
retrieving revision 1.133
diff -c -3 -p -r1.133 dbxout.c
*** dbxout.c	16 Jan 2003 15:37:53 -0000	1.133
--- dbxout.c	17 Feb 2003 19:34:29 -0000
***************
*** 1,6 ****
  /* Output dbx-format symbol table information from GNU compiler.
     Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
--- 1,6 ----
  /* Output dbx-format symbol table information from GNU compiler.
     Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
*************** dbxout_type (type, full)
*** 1577,1591 ****
  	  }
  	for (i = 0; i < n_baseclasses; i++)
  	  {
! 	    tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);
! 
  	    if (use_gnu_debug_info_extensions)
  	      {
  		have_used_extensions = 1;
  		putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile);
! 		putc (TREE_VIA_PUBLIC (child) ? '2' : '0', asmfile);
  		CHARS (2);
! 		if (TREE_VIA_VIRTUAL (child) && strcmp (lang_hooks.name, "GNU C++") == 0)
  		  /* For a virtual base, print the (negative) offset within
  		     the vtable where we must look to find the necessary
  		     adjustment.  */
--- 1577,1595 ----
  	  }
  	for (i = 0; i < n_baseclasses; i++)
  	  {
! 	    tree binfo = TYPE_BINFO (type);
! 	    tree child = BINFO_BASETYPE (binfo, i);
! 	    tree access = (BINFO_BASEACCESSES (binfo)
! 			   ? BINFO_BASEACCESS (binfo, i) : access_public_node);
! 	    
  	    if (use_gnu_debug_info_extensions)
  	      {
  		have_used_extensions = 1;
  		putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile);
! 		putc (access == access_public_node ? '2' : '0', asmfile);
  		CHARS (2);
! 		if (TREE_VIA_VIRTUAL (child)
! 		    && strcmp (lang_hooks.name, "GNU C++") == 0)
  		  /* For a virtual base, print the (negative) offset within
  		     the vtable where we must look to find the necessary
  		     adjustment.  */
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.400
diff -c -3 -p -r1.400 dwarf2out.c
*** dwarf2out.c	6 Feb 2003 01:23:39 -0000	1.400
--- dwarf2out.c	17 Feb 2003 19:35:18 -0000
*************** static void gen_field_die		PARAMS ((tree
*** 3818,3824 ****
  static void gen_ptr_to_mbr_type_die	PARAMS ((tree, dw_die_ref));
  static dw_die_ref gen_compile_unit_die	PARAMS ((const char *));
  static void gen_string_type_die		PARAMS ((tree, dw_die_ref));
! static void gen_inheritance_die		PARAMS ((tree, dw_die_ref));
  static void gen_member_die		PARAMS ((tree, dw_die_ref));
  static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
  static void gen_subroutine_type_die	PARAMS ((tree, dw_die_ref));
--- 3818,3824 ----
  static void gen_ptr_to_mbr_type_die	PARAMS ((tree, dw_die_ref));
  static dw_die_ref gen_compile_unit_die	PARAMS ((const char *));
  static void gen_string_type_die		PARAMS ((tree, dw_die_ref));
! static void gen_inheritance_die		PARAMS ((tree, tree, dw_die_ref));
  static void gen_member_die		PARAMS ((tree, dw_die_ref));
  static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
  static void gen_subroutine_type_die	PARAMS ((tree, dw_die_ref));
*************** gen_string_type_die (type, context_die)
*** 11363,11370 ****
  /* Generate the DIE for a base class.  */
  
  static void
! gen_inheritance_die (binfo, context_die)
!      tree binfo;
       dw_die_ref context_die;
  {
    dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
--- 11363,11370 ----
  /* Generate the DIE for a base class.  */
  
  static void
! gen_inheritance_die (binfo, access, context_die)
!      tree binfo, access;
       dw_die_ref context_die;
  {
    dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
*************** gen_inheritance_die (binfo, context_die)
*** 11375,11383 ****
    if (TREE_VIA_VIRTUAL (binfo))
      add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
  
!   if (TREE_VIA_PUBLIC (binfo))
      add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public);
!   else if (TREE_VIA_PROTECTED (binfo))
      add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected);
  }
  
--- 11375,11383 ----
    if (TREE_VIA_VIRTUAL (binfo))
      add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
  
!   if (access == access_public_node)
      add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public);
!   else if (access == access_protected_node)
      add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected);
  }
  
*************** gen_member_die (type, context_die)
*** 11389,11394 ****
--- 11389,11395 ----
       dw_die_ref context_die;
  {
    tree member;
+   tree binfo = TYPE_BINFO (type);
    dw_die_ref child;
  
    /* If this is not an incomplete type, output descriptions of each of its
*************** gen_member_die (type, context_die)
*** 11404,11417 ****
       the TREE node representing the appropriate (containing) type.  */
  
    /* First output info about the base classes.  */
!   if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
      {
!       tree bases = TYPE_BINFO_BASETYPES (type);
        int n_bases = TREE_VEC_LENGTH (bases);
        int i;
  
        for (i = 0; i < n_bases; i++)
! 	gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die);
      }
  
    /* Now output info about the data members and type members.  */
--- 11405,11421 ----
       the TREE node representing the appropriate (containing) type.  */
  
    /* First output info about the base classes.  */
!   if (binfo && BINFO_BASETYPES (binfo))
      {
!       tree bases = BINFO_BASETYPES (binfo);
!       tree accesses = BINFO_BASEACCESSES (binfo);
        int n_bases = TREE_VEC_LENGTH (bases);
        int i;
  
        for (i = 0; i < n_bases; i++)
! 	gen_inheritance_die (TREE_VEC_ELT (bases, i),
! 			     (accesses ? TREE_VEC_ELT (accesses, i)
! 			      : access_public_node), context_die);
      }
  
    /* Now output info about the data members and type members.  */
Index: dwarfout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarfout.c,v
retrieving revision 1.120
diff -c -3 -p -r1.120 dwarfout.c
*** dwarfout.c	6 Feb 2003 01:23:39 -0000	1.120
--- dwarfout.c	17 Feb 2003 19:35:59 -0000
*************** static void
*** 4179,4185 ****
  output_inheritance_die (arg)
       void *arg;
  {
!   tree binfo = arg;
  
    ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inheritance);
    sibling_attribute ();
--- 4179,4186 ----
  output_inheritance_die (arg)
       void *arg;
  {
!   tree binfo = ((tree *)arg)[0];
!   tree access = ((tree *)arg)[1];
  
    ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inheritance);
    sibling_attribute ();
*************** output_inheritance_die (arg)
*** 4190,4201 ****
        ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
        ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
      }
!   if (TREE_VIA_PUBLIC (binfo))
      {
        ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
        ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
      }
!   else if (TREE_VIA_PROTECTED (binfo))
      {
        ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
        ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
--- 4191,4202 ----
        ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
        ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
      }
!   if (access == access_public_node)
      {
        ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
        ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
      }
!   else if (access == access_protected_node)
      {
        ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
        ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
*************** output_type (type, containing_scope)
*** 4896,4913 ****
  
  	if (COMPLETE_TYPE_P (type))
  	  {
  	    /* First output info about the base classes.  */
! 	    if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
  	      {
! 		register tree bases = TYPE_BINFO_BASETYPES (type);
! 		register int n_bases = TREE_VEC_LENGTH (bases);
  		register int i;
  
  		for (i = 0; i < n_bases; i++)
  		  {
! 		    tree binfo = TREE_VEC_ELT (bases, i);
  		    output_type (BINFO_TYPE (binfo), containing_scope);
! 		    output_die (output_inheritance_die, binfo);
  		  }
  	      }
  
--- 4897,4921 ----
  
  	if (COMPLETE_TYPE_P (type))
  	  {
+ 	    tree binfo = TYPE_BINFO (type);
+ 	    
  	    /* First output info about the base classes.  */
! 	    if (binfo)
  	      {
! 		tree bases = BINFO_BASETYPES (binfo);
! 		tree accesses = BINFO_BASEACCESSES (binfo);
! 		register int n_bases = BINFO_N_BASETYPES (binfo);
  		register int i;
  
  		for (i = 0; i < n_bases; i++)
  		  {
! 		    tree arg[2];
! 
! 		    arg[0] = TREE_VEC_ELT (bases, i);
! 		    arg[1] = (accesses ? TREE_VEC_ELT (accesses, i)
! 			      : access_public_node);
  		    output_type (BINFO_TYPE (binfo), containing_scope);
! 		    output_die (output_inheritance_die, arg);
  		  }
  	      }
  
Index: tree-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dump.c,v
retrieving revision 1.9
diff -c -3 -p -r1.9 tree-dump.c
*** tree-dump.c	16 Dec 2002 18:20:00 -0000	1.9
--- tree-dump.c	17 Feb 2003 19:36:04 -0000
***************
*** 1,5 ****
  /* Tree-dumping functionality for intermediate representation.
!    Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
     Written by Mark Mitchell <mark at codesourcery dot com>
  
  This file is part of GCC.
--- 1,5 ----
  /* Tree-dumping functionality for intermediate representation.
!    Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
     Written by Mark Mitchell <mark at codesourcery dot com>
  
  This file is part of GCC.
*************** dequeue_and_dump (di)
*** 273,290 ****
       more informative.  */
    if (dni->binfo_p)
      {
!       if (TREE_VIA_PUBLIC (t))
! 	dump_string (di, "pub");
!       else if (TREE_VIA_PROTECTED (t))
! 	dump_string (di, "prot");
!       else if (TREE_VIA_PRIVATE (t))
! 	dump_string (di, "priv");
        if (TREE_VIA_VIRTUAL (t))
  	dump_string (di, "virt");
  
!       dump_child ("type", BINFO_TYPE (t));
!       dump_child ("base", BINFO_BASETYPES (t));
  
        goto done;
      }
  
--- 273,309 ----
       more informative.  */
    if (dni->binfo_p)
      {
!       unsigned ix;
!       tree bases = BINFO_BASETYPES (t);
!       unsigned n_bases = bases ? TREE_VEC_LENGTH (bases): 0;
!       tree accesses = BINFO_BASEACCESSES (t);
!       
!       dump_child ("type", BINFO_TYPE (t));
! 
        if (TREE_VIA_VIRTUAL (t))
  	dump_string (di, "virt");
  
!       dump_int (di, "bases", n_bases);
!       for (ix = 0; ix != n_bases; ix++)
! 	{
! 	  tree base = TREE_VEC_ELT (bases, ix);
! 	  tree access = (accesses ? TREE_VEC_ELT (accesses, ix)
! 			 : access_public_node);
! 	  const char *string = NULL;
  
+ 	  if (access == access_public_node)
+ 	    string = "pub";
+ 	  else if (access == access_protected_node)
+ 	    string = "prot";
+ 	  else if (access == access_private_node)
+ 	    string = "priv";
+ 	  else
+ 	    abort ();
+ 	  
+ 	  dump_string (di, string);
+ 	  queue_and_dump_index (di, "binf", base, DUMP_BINFO);
+ 	}
+       
        goto done;
      }
  
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.381
diff -c -3 -p -r1.381 tree.h
*** tree.h	12 Feb 2003 21:48:58 -0000	1.381
--- tree.h	17 Feb 2003 19:36:44 -0000
***************
*** 1,6 ****
  /* Front-end tree definitions for GNU compiler.
     Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
!    2001, 2002 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
--- 1,6 ----
  /* Front-end tree definitions for GNU compiler.
     Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
!    2001, 2002, 2003 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
*************** struct tree_common GTY(())
*** 192,206 ****
             INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST
         TREE_PUBLIC in
             VAR_DECL or FUNCTION_DECL or IDENTIFIER_NODE
-        TREE_VIA_PUBLIC in
-            TREE_LIST or TREE_VEC
         EXPR_WFL_EMIT_LINE_NOTE in
             EXPR_WITH_FILE_LOCATION
  
     private_flag:
  
-        TREE_VIA_PRIVATE in
-            TREE_LIST or TREE_VEC
         TREE_PRIVATE in
             ..._DECL
         CALL_EXPR_HAS_RETURN_SLOT_ADDR in
--- 192,202 ----
*************** struct tree_common GTY(())
*** 208,216 ****
  
     protected_flag:
  
-        TREE_VIA_PROTECTED in
-            TREE_LIST
- 	   TREE_VEC
         TREE_PROTECTED in
             BLOCK
  	   ..._DECL
--- 204,209 ----
*************** extern void tree_vec_elt_check_failed PA
*** 565,584 ****
     for this name in an inner scope.  */
  #define TREE_PUBLIC(NODE) ((NODE)->common.public_flag)
  
- /* Nonzero for TREE_LIST or TREE_VEC node means that the path to the
-    base class is via a `public' declaration, which preserves public
-    fields from the base class as public.  */
- #define TREE_VIA_PUBLIC(NODE) ((NODE)->common.public_flag)
- 
- /* Ditto, for `private' declarations.  */
- #define TREE_VIA_PRIVATE(NODE) ((NODE)->common.private_flag)
- 
- /* Nonzero for TREE_LIST or TREE_VEC node means that the path to the
-    base class is via a `protected' declaration, which preserves
-    protected fields from the base class as protected.
-    OVERLOADED.  */
- #define TREE_VIA_PROTECTED(NODE) ((NODE)->common.protected_flag)
- 
  /* In any expression, nonzero means it has side effects or reevaluation
     of the whole expression could produce a different value.
     This is set if any subexpression is a function call, a side effect
--- 558,563 ----
*************** struct tree_type GTY(())
*** 1362,1368 ****
     vtable where the offset to the virtual base can be found.  */
  #define BINFO_VPTR_FIELD(NODE) TREE_VEC_ELT (NODE, 5)
  
! #define BINFO_ELTS 6
  
  /* Slot used to build a chain that represents a use of inheritance.
     For example, if X is derived from Y, and Y is derived from Z,
--- 1341,1356 ----
     vtable where the offset to the virtual base can be found.  */
  #define BINFO_VPTR_FIELD(NODE) TREE_VEC_ELT (NODE, 5)
  
! /* Indicates the accesses this binfo has to its bases. The values are
!    access_public_node, access_protected_node or access_private_node.
!    If this array is not present, public access is implied.  */
! #define BINFO_BASEACCESSES(NODE) TREE_VEC_ELT ((NODE), 6)
! #define BINFO_BASEACCESS(NODE,N) TREE_VEC_ELT (BINFO_BASEACCESSES(NODE), (N))
! 
! /* Number of language independent elements in a binfo.  Languages may
!    add additional trailing elements.  */
! 
! #define BINFO_ELTS 7
  
  /* Slot used to build a chain that represents a use of inheritance.
     For example, if X is derived from Y, and Y is derived from Z,
*************** extern GTY(()) tree global_trees[TI_MAX]
*** 2027,2032 ****
--- 2015,2025 ----
  #define bitsize_zero_node		global_trees[TI_BITSIZE_ZERO]
  #define bitsize_one_node		global_trees[TI_BITSIZE_ONE]
  #define bitsize_unit_node		global_trees[TI_BITSIZE_UNIT]
+ 
+ /* Base access nodes.  */
+ #define access_public_node		NULL_TREE
+ #define access_protected_node		size_zero_node
+ #define access_private_node		size_one_node
  
  #define null_pointer_node		global_trees[TI_NULL_POINTER]
  
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.356
diff -c -3 -p -r1.356 call.c
*** cp/call.c	15 Feb 2003 18:03:21 -0000	1.356
--- cp/call.c	17 Feb 2003 19:43:08 -0000
*************** build_special_member_call (tree instance
*** 4653,4660 ****
  			  current_in_charge_parm, integer_zero_node),
  		   current_vtt_parm,
  		   vtt);
-       if (TREE_VIA_VIRTUAL (binfo))
- 	binfo = binfo_for_vbase (class_type, current_class_type);
        my_friendly_assert (BINFO_SUBVTT_INDEX (binfo), 20010110);
        sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
  		       BINFO_SUBVTT_INDEX (binfo));
--- 4653,4658 ----
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.519
diff -c -3 -p -r1.519 class.c
*** cp/class.c	15 Feb 2003 18:03:21 -0000	1.519
--- cp/class.c	17 Feb 2003 19:43:36 -0000
*************** static void finish_struct_anon (tree);
*** 110,116 ****
  static tree get_vtable_name (tree);
  static tree get_basefndecls (tree, tree);
  static int build_primary_vtable (tree, tree);
! static int build_secondary_vtable (tree, tree);
  static void finish_vtbls (tree);
  static void modify_vtable_entry (tree, tree, tree, tree, tree *);
  static tree delete_duplicate_fields_1 (tree, tree);
--- 110,116 ----
  static tree get_vtable_name (tree);
  static tree get_basefndecls (tree, tree);
  static int build_primary_vtable (tree, tree);
! static int build_secondary_vtable (tree);
  static void finish_vtbls (tree);
  static void modify_vtable_entry (tree, tree, tree, tree, tree *);
  static tree delete_duplicate_fields_1 (tree, tree);
*************** static void layout_class_type (tree, tre
*** 152,160 ****
  static void fixup_pending_inline (tree);
  static void fixup_inline_methods (tree);
  static void set_primary_base (tree, tree);
! static void propagate_binfo_offsets (tree, tree, tree);
  static void layout_virtual_bases (record_layout_info, splay_tree);
- static tree dfs_set_offset_for_unshared_vbases (tree, void *);
  static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *);
  static void add_vcall_offset_vtbl_entries_r (tree, vtbl_init_data *);
  static void add_vcall_offset_vtbl_entries_1 (tree, vtbl_init_data *);
--- 152,159 ----
  static void fixup_pending_inline (tree);
  static void fixup_inline_methods (tree);
  static void set_primary_base (tree, tree);
! static void propagate_binfo_offsets (tree, tree);
  static void layout_virtual_bases (record_layout_info, splay_tree);
  static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *);
  static void add_vcall_offset_vtbl_entries_r (tree, vtbl_init_data *);
  static void add_vcall_offset_vtbl_entries_1 (tree, vtbl_init_data *);
*************** static void build_vcall_offset_vtbl_entr
*** 162,171 ****
  static void add_vcall_offset (tree, tree, vtbl_init_data *);
  static void layout_vtable_decl (tree, int);
  static tree dfs_find_final_overrider (tree, void *);
  static tree find_final_overrider (tree, tree, tree);
  static int make_new_vtable (tree, tree);
  static int maybe_indent_hierarchy (FILE *, int, int);
! static void dump_class_hierarchy_r (FILE *, int, tree, tree, int);
  static void dump_class_hierarchy (tree);
  static void dump_array (FILE *, tree);
  static void dump_vtable (tree, tree, tree);
--- 161,172 ----
  static void add_vcall_offset (tree, tree, vtbl_init_data *);
  static void layout_vtable_decl (tree, int);
  static tree dfs_find_final_overrider (tree, void *);
+ static tree dfs_find_final_overrider_post (tree, void *);
+ static tree dfs_find_final_overrider_q (tree, int, void *);
  static tree find_final_overrider (tree, tree, tree);
  static int make_new_vtable (tree, tree);
  static int maybe_indent_hierarchy (FILE *, int, int);
! static tree dump_class_hierarchy_r (FILE *, int, tree, tree, int);
  static void dump_class_hierarchy (tree);
  static void dump_array (FILE *, tree);
  static void dump_vtable (tree, tree, tree);
*************** static void initialize_array (tree, tree
*** 176,193 ****
  static void layout_nonempty_base_or_field (record_layout_info,
  						   tree, tree, splay_tree);
  static tree end_of_class (tree, int);
! static bool layout_empty_base (tree, tree, splay_tree, tree);
  static void accumulate_vtbl_inits (tree, tree, tree, tree, tree);
  static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree,
  					       tree);
  static void build_rtti_vtbl_entries (tree, vtbl_init_data *);
  static void build_vcall_and_vbase_vtbl_entries (tree, 
  							vtbl_init_data *);
- static void force_canonical_binfo_r (tree, tree, tree, tree);
- static void force_canonical_binfo (tree, tree, tree, tree);
- static tree dfs_unshared_virtual_bases (tree, void *);
  static void mark_primary_bases (tree);
- static tree mark_primary_virtual_base (tree, tree);
  static void clone_constructors_and_destructors (tree);
  static tree build_clone (tree, tree);
  static void update_vtable_entry_for_fn (tree, tree, tree, tree *, unsigned);
--- 177,190 ----
  static void layout_nonempty_base_or_field (record_layout_info,
  						   tree, tree, splay_tree);
  static tree end_of_class (tree, int);
! static bool layout_empty_base (tree, tree, splay_tree);
  static void accumulate_vtbl_inits (tree, tree, tree, tree, tree);
  static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree,
  					       tree);
  static void build_rtti_vtbl_entries (tree, vtbl_init_data *);
  static void build_vcall_and_vbase_vtbl_entries (tree, 
  							vtbl_init_data *);
  static void mark_primary_bases (tree);
  static void clone_constructors_and_destructors (tree);
  static tree build_clone (tree, tree);
  static void update_vtable_entry_for_fn (tree, tree, tree, tree *, unsigned);
*************** static void build_vtt (tree);
*** 197,206 ****
  static tree binfo_ctor_vtable (tree);
  static tree *build_vtt_inits (tree, tree, tree *, tree *);
  static tree dfs_build_secondary_vptr_vtt_inits (tree, void *);
! static tree dfs_ctor_vtable_bases_queue_p (tree, void *data);
  static tree dfs_fixup_binfo_vtbls (tree, void *);
- static tree get_original_base (tree, tree);
- static tree dfs_get_primary_binfo (tree, void*);
  static int record_subobject_offset (tree, tree, splay_tree);
  static int check_subobject_offset (tree, tree, splay_tree);
  static int walk_subobject_offsets (tree, subobject_offset_fn,
--- 194,201 ----
  static tree binfo_ctor_vtable (tree);
  static tree *build_vtt_inits (tree, tree, tree *, tree *);
  static tree dfs_build_secondary_vptr_vtt_inits (tree, void *);
! static tree dfs_ctor_vtable_bases_queue_p (tree, int, void *data);
  static tree dfs_fixup_binfo_vtbls (tree, void *);
  static int record_subobject_offset (tree, tree, splay_tree);
  static int check_subobject_offset (tree, tree, splay_tree);
  static int walk_subobject_offsets (tree, subobject_offset_fn,
*************** static int splay_tree_compare_integer_cs
*** 212,218 ****
  static void warn_about_ambiguous_bases (tree);
  static bool type_requires_array_cookie (tree);
  static bool contains_empty_class_p (tree);
- static tree dfs_base_derived_from (tree, void *);
  static bool base_derived_from (tree, tree);
  static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
  static tree end_of_base (tree);
--- 207,212 ----
*************** build_base_path (enum tree_code code,
*** 311,318 ****
        tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
  					TREE_TYPE (TREE_TYPE (expr)));
        
-       v_binfo = binfo_for_vbase (BINFO_TYPE (v_binfo), BINFO_TYPE (d_binfo));
-       
        v_offset = build (PLUS_EXPR, TREE_TYPE (v_offset),
  			v_offset,  BINFO_VPTR_FIELD (v_binfo));
        v_offset = build1 (NOP_EXPR, 
--- 305,310 ----
*************** build_vtbl_ref_1 (tree instance, tree id
*** 443,452 ****
      }
  
    if (!vtbl)
!     {
!       vtbl = build_vfield_ref (instance, basetype);
!     }
! 
    assemble_external (vtbl);
  
    aref = build_array_ref (vtbl, idx);
--- 435,442 ----
      }
  
    if (!vtbl)
!     vtbl = build_vfield_ref (instance, basetype);
!   
    assemble_external (vtbl);
  
    aref = build_array_ref (vtbl, idx);
*************** build_primary_vtable (tree binfo, tree t
*** 592,598 ****
    
    if (binfo)
      {
!       if (BINFO_NEW_VTABLE_MARKED (binfo, type))
  	/* We have already created a vtable for this base, so there's
  	   no need to do it again.  */
  	return 0;
--- 582,588 ----
    
    if (binfo)
      {
!       if (BINFO_NEW_VTABLE_MARKED (binfo))
  	/* We have already created a vtable for this base, so there's
  	   no need to do it again.  */
  	return 0;
*************** build_primary_vtable (tree binfo, tree t
*** 618,624 ****
       on our first approximation.  */
    TYPE_BINFO_VTABLE (type) = decl;
    TYPE_BINFO_VIRTUALS (type) = virtuals;
!   SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type), type);
    return 1;
  }
  
--- 608,614 ----
       on our first approximation.  */
    TYPE_BINFO_VTABLE (type) = decl;
    TYPE_BINFO_VIRTUALS (type) = virtuals;
!   SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type));
    return 1;
  }
  
*************** build_primary_vtable (tree binfo, tree t
*** 637,654 ****
     can result.  */
  
  static int
! build_secondary_vtable (tree binfo, tree for_type)
  {
!   my_friendly_assert (binfo == CANONICAL_BINFO (binfo, for_type), 20010605);
! 
!   if (BINFO_NEW_VTABLE_MARKED (binfo, for_type))
      /* We already created a vtable for this base.  There's no need to
         do it again.  */
      return 0;
  
    /* Remember that we've created a vtable for this BINFO, so that we
       don't try to do so again.  */
!   SET_BINFO_NEW_VTABLE_MARKED (binfo, for_type);
    
    /* Make fresh virtual list, so we can smash it later.  */
    BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
--- 627,642 ----
     can result.  */
  
  static int
! build_secondary_vtable (tree binfo)
  {
!   if (BINFO_NEW_VTABLE_MARKED (binfo))
      /* We already created a vtable for this base.  There's no need to
         do it again.  */
      return 0;
  
    /* Remember that we've created a vtable for this BINFO, so that we
       don't try to do so again.  */
!   SET_BINFO_NEW_VTABLE_MARKED (binfo);
    
    /* Make fresh virtual list, so we can smash it later.  */
    BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
*************** make_new_vtable (tree t, tree binfo)
*** 678,684 ****
         we will fill in all the virtual functions that override the
         virtual functions in these base classes which are not defined
         by the current type.  */
!     return build_secondary_vtable (binfo, t);
  }
  
  /* Make *VIRTUALS, an entry on the BINFO_VIRTUALS list for BINFO
--- 666,672 ----
         we will fill in all the virtual functions that override the
         virtual functions in these base classes which are not defined
         by the current type.  */
!     return build_secondary_vtable (binfo);
  }
  
  /* Make *VIRTUALS, an entry on the BINFO_VIRTUALS list for BINFO
*************** modify_vtable_entry (tree t,
*** 692,698 ****
                       tree binfo, 
                       tree fndecl, 
                       tree delta, 
!                      tree* virtuals)
  {
    tree v;
  
--- 680,686 ----
                       tree binfo, 
                       tree fndecl, 
                       tree delta, 
!                      tree *virtuals)
  {
    tree v;
  
*************** check_bases (tree t,
*** 1296,1465 ****
      }
  }
  
- /* Binfo FROM is within a virtual hierarchy which is being reseated to
-    TO. Move primary information from FROM to TO, and recursively traverse
-    into FROM's bases. The hierarchy is dominated by TYPE.  MAPPINGS is an
-    assoc list of binfos that have already been reseated.  */
- 
- static void
- force_canonical_binfo_r (tree to, tree from, tree type, tree mappings)
- {
-   int i, n_baseclasses = BINFO_N_BASETYPES (from);
- 
-   my_friendly_assert (to != from, 20010905);
-   BINFO_INDIRECT_PRIMARY_P (to)
-           = BINFO_INDIRECT_PRIMARY_P (from);
-   BINFO_INDIRECT_PRIMARY_P (from) = 0;
-   BINFO_UNSHARED_MARKED (to) = BINFO_UNSHARED_MARKED (from);
-   BINFO_UNSHARED_MARKED (from) = 0;
-   BINFO_LOST_PRIMARY_P (to) = BINFO_LOST_PRIMARY_P (from);
-   BINFO_LOST_PRIMARY_P (from) = 0;
-   if (BINFO_PRIMARY_P (from))
-     {
-       tree primary = BINFO_PRIMARY_BASE_OF (from);
-       tree assoc;
-       
-       /* We might have just moved the primary base too, see if it's on our
-          mappings.  */
-       assoc = purpose_member (primary, mappings);
-       if (assoc)
-         primary = TREE_VALUE (assoc);
-       BINFO_PRIMARY_BASE_OF (to) = primary;
-       BINFO_PRIMARY_BASE_OF (from) = NULL_TREE;
-     }
-   my_friendly_assert (same_type_p (BINFO_TYPE (to), BINFO_TYPE (from)),
- 		      20010104);
-   mappings = tree_cons (from, to, mappings);
- 
-   if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (from))
-       && TREE_VIA_VIRTUAL (CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (from))))
-     {
-       tree from_primary = get_primary_binfo (from);
-       
-       if (BINFO_PRIMARY_BASE_OF (from_primary) == from)
- 	force_canonical_binfo (get_primary_binfo (to), from_primary,
- 			       type, mappings);
-     }
-   
-   for (i = 0; i != n_baseclasses; i++)
-     {
-       tree from_binfo = BINFO_BASETYPE (from, i);
-       tree to_binfo = BINFO_BASETYPE (to, i);
- 
-       if (TREE_VIA_VIRTUAL (from_binfo))
-         {
- 	  if (BINFO_PRIMARY_P (from_binfo) &&
- 	      purpose_member (BINFO_PRIMARY_BASE_OF (from_binfo), mappings))
- 	    /* This base is a primary of some binfo we have already
- 	       reseated. We must reseat this one too.  */
-             force_canonical_binfo (to_binfo, from_binfo, type, mappings);
-         }
-       else
-         force_canonical_binfo_r (to_binfo, from_binfo, type, mappings);
-     }
- }
- 
- /* FROM is the canonical binfo for a virtual base. It is being reseated to
-    make TO the canonical binfo, within the hierarchy dominated by TYPE.
-    MAPPINGS is an assoc list of binfos that have already been reseated.
-    Adjust any non-virtual bases within FROM, and also move any virtual bases
-    which are canonical.  This complication arises because selecting primary
-    bases walks in inheritance graph order, but we don't share binfos for
-    virtual bases, hence we can fill in the primaries for a virtual base,
-    and then discover that a later base requires the virtual as its
-    primary.  */
- 
- static void
- force_canonical_binfo (tree to, tree from, tree type, tree mappings)
- {
-   tree assoc = purpose_member (BINFO_TYPE (to),
- 		               CLASSTYPE_VBASECLASSES (type));
-   if (TREE_VALUE (assoc) != to)
-     {
-       TREE_VALUE (assoc) = to;
-       force_canonical_binfo_r (to, from, type, mappings);
-     }
- }
- 
- /* Make BASE_BINFO the a primary virtual base within the hierarchy
-    dominated by TYPE. Returns BASE_BINFO, if it is not already one, NULL
-    otherwise (because something else has already made it primary).  */
- 
- static tree
- mark_primary_virtual_base (tree base_binfo, tree type)
- {
-   tree shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
- 
-   if (BINFO_PRIMARY_P (shared_binfo))
-     {
-       /* It's already allocated in the hierarchy. BINFO won't have a
-          primary base in this hierarchy, even though the complete object
-          BINFO is for, would do.  */
-       return NULL_TREE;
-     }
-      
-   /* We need to make sure that the assoc list
-      CLASSTYPE_VBASECLASSES of TYPE, indicates this particular
-      primary BINFO for the virtual base, as this is the one
-      that'll really exist.  */
-   if (base_binfo != shared_binfo)
-     force_canonical_binfo (base_binfo, shared_binfo, type, NULL);
- 
-   return base_binfo;
- }
- 
- /* If BINFO is an unmarked virtual binfo for a class with a primary virtual
-    base, then BINFO has no primary base in this graph.  Called from
-    mark_primary_bases.  DATA is the most derived type.  */
- 
- static tree
- dfs_unshared_virtual_bases (tree binfo, void* data)
- {
-   tree t = (tree) data;
-   
-   if (!BINFO_UNSHARED_MARKED (binfo)
-       && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
-     {
-       /* This morally virtual base has a primary base when it
-          is a complete object. We need to locate the shared instance
-          of this binfo in the type dominated by T. We duplicate the
-          primary base information from there to here.  */
-       tree vbase;
-       tree unshared_base;
-       
-       for (vbase = binfo; !TREE_VIA_VIRTUAL (vbase);
- 	   vbase = BINFO_INHERITANCE_CHAIN (vbase))
- 	continue;
-       unshared_base = get_original_base (binfo,
- 					 binfo_for_vbase (BINFO_TYPE (vbase),
- 							  t));
-       my_friendly_assert (unshared_base != binfo, 20010612);
-       BINFO_LOST_PRIMARY_P (binfo) = BINFO_LOST_PRIMARY_P (unshared_base);
-       if (!BINFO_LOST_PRIMARY_P (binfo))
- 	BINFO_PRIMARY_BASE_OF (get_primary_binfo (binfo)) = binfo;
-     }
-   
-   if (binfo != TYPE_BINFO (t))
-     /* The vtable fields will have been copied when duplicating the
-        base binfos. That information is bogus, make sure we don't try
-        and use it.  */
-     BINFO_VTABLE (binfo) = NULL_TREE;
- 
-   /* If this is a virtual primary base, make sure its offset matches
-      that which it is primary for.  */
-   if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo) &&
-       binfo_for_vbase (BINFO_TYPE (binfo), t) == binfo)
-     {
-       tree delta = size_diffop (BINFO_OFFSET (BINFO_PRIMARY_BASE_OF (binfo)),
- 				BINFO_OFFSET (binfo));
-       if (!integer_zerop (delta))
- 	propagate_binfo_offsets (binfo, delta, t);
-     }
-   
-   BINFO_UNSHARED_MARKED (binfo) = 0;
-   return NULL;
- }
- 
  /* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy
     dominated by TYPE that are primary bases.  */
  
--- 1284,1289 ----
*************** mark_primary_bases (tree type)
*** 1471,1503 ****
    /* Walk the bases in inheritance graph order.  */
    for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
      {
!       tree base_binfo;
!       
!       if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
!         /* Not a dynamic base.  */
!         continue;
! 
!       base_binfo = get_primary_binfo (binfo);
! 
!       if (TREE_VIA_VIRTUAL (base_binfo))
!         base_binfo = mark_primary_virtual_base (base_binfo, type);
  
!       if (base_binfo)
!         BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
!       else
  	BINFO_LOST_PRIMARY_P (binfo) = 1;
!       
!       BINFO_UNSHARED_MARKED (binfo) = 1;
      }
-   /* There could remain unshared morally virtual bases which were not
-      visited in the inheritance graph walk. These bases will have lost
-      their virtual primary base (should they have one). We must now
-      find them. Also we must fix up the BINFO_OFFSETs of primary
-      virtual bases. We could not do that as we went along, as they
-      were originally copied from the bases we inherited from by
-      unshare_base_binfos. That may have decided differently about
-      where a virtual primary base went.  */
-   dfs_walk (TYPE_BINFO (type), dfs_unshared_virtual_bases, NULL, type);
  }
  
  /* Make the BINFO the primary base of T.  */
--- 1295,1323 ----
    /* Walk the bases in inheritance graph order.  */
    for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
      {
!       tree base_binfo = get_primary_binfo (binfo);
  
!       if (!base_binfo)
! 	/* Not a dynamic base.  */;
!       else if (BINFO_PRIMARY_P (base_binfo))
  	BINFO_LOST_PRIMARY_P (binfo) = 1;
!       else
! 	{
! 	  BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
! 	  /* A virtual binfo might have been copied from within
!   	     another hierarchy. As we're about to use it as a primary
!   	     base, make sure the offsets match.  */
! 	  if (TREE_VIA_VIRTUAL (base_binfo))
! 	    {
! 	      tree delta = size_diffop (convert (ssizetype,
! 						 BINFO_OFFSET (binfo)),
! 					convert (ssizetype,
! 						 BINFO_OFFSET (base_binfo)));
! 	  
! 	      propagate_binfo_offsets (base_binfo, delta);
! 	    }
! 	}
      }
  }
  
  /* Make the BINFO the primary base of T.  */
*************** maybe_warn_about_overly_private_class (t
*** 1802,1811 ****
  	 issues error messages specifically referring to
  	 constructors/destructors.)  */
        int i;
!       tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
!       for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
! 	if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
! 	    || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))
  	  {
  	    has_nonprivate_method = 1;
  	    break;
--- 1622,1631 ----
  	 issues error messages specifically referring to
  	 constructors/destructors.)  */
        int i;
!       tree binfo = TYPE_BINFO (t);
!       
!       for (i = 0; i < BINFO_N_BASETYPES (binfo); i++)
! 	if (BINFO_BASEACCESS (binfo, i) != access_private_node)
  	  {
  	    has_nonprivate_method = 1;
  	    break;
*************** same_signature_p (tree fndecl, tree base
*** 2220,2246 ****
    return 0;
  }
  
- /* Called from base_derived_from via dfs_walk.  */
- 
- static tree
- dfs_base_derived_from (tree binfo, void *data)
- {
-   tree base = (tree) data;
- 
-   if (same_type_p (TREE_TYPE (base), TREE_TYPE (binfo))
-       && tree_int_cst_equal (BINFO_OFFSET (base), BINFO_OFFSET (binfo)))
-     return error_mark_node;
- 
-   return NULL_TREE;
- }
- 
  /* Returns TRUE if DERIVED is a binfo containing the binfo BASE as a
     subobject.  */
   
  static bool
  base_derived_from (tree derived, tree base)
  {
!   return dfs_walk (derived, dfs_base_derived_from, NULL, base) != NULL_TREE;
  }
  
  typedef struct find_final_overrider_data_s {
--- 2040,2066 ----
    return 0;
  }
  
  /* Returns TRUE if DERIVED is a binfo containing the binfo BASE as a
     subobject.  */
   
  static bool
  base_derived_from (tree derived, tree base)
  {
!   tree probe;
! 
!   for (probe = base; probe; probe = BINFO_INHERITANCE_CHAIN (probe))
!     {
!       if (probe == derived)
! 	return true;
!       else if (TREE_VIA_VIRTUAL (probe))
! 	/* If we meet a virtual base, we can't follow the inheritance
! 	   any more.  See if the complete type of DERIVED contains
! 	   such a virtual base.  */
! 	return purpose_member (BINFO_TYPE (probe),
! 			       CLASSTYPE_VBASECLASSES (BINFO_TYPE (derived)))
! 	  != NULL_TREE;
!     }
!   return false;
  }
  
  typedef struct find_final_overrider_data_s {
*************** typedef struct find_final_overrider_data
*** 2252,2257 ****
--- 2072,2079 ----
    tree most_derived_type;
    /* The candidate overriders.  */
    tree candidates;
+   /* Binfos which inherited virtually on the currrent path.  */
+   tree vpath;
  } find_final_overrider_data;
  
  /* Called from find_final_overrider via dfs_walk.  */
*************** dfs_find_final_overrider (tree binfo, vo
*** 2261,2321 ****
  {
    find_final_overrider_data *ffod = (find_final_overrider_data *) data;
  
!   if (same_type_p (BINFO_TYPE (binfo), 
! 		   BINFO_TYPE (ffod->declaring_base))
!       && tree_int_cst_equal (BINFO_OFFSET (binfo),
! 			     BINFO_OFFSET (ffod->declaring_base)))
!     {
!       tree path;
!       tree method;
! 
!       /* We haven't found an overrider yet.  */
!       method = NULL_TREE;
!       /* We've found a path to the declaring base.  Walk down the path
! 	 looking for an overrider for FN.  */
!       path = reverse_path (binfo);
!       while (!same_type_p (BINFO_TYPE (TREE_VALUE (path)),
! 			   ffod->most_derived_type))
! 	path = TREE_CHAIN (path);
!       while (path)
  	{
! 	  method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
! 					    ffod->fn);
  	  if (method)
  	    {
  	      path = TREE_VALUE (path);
  	      break;
  	    }
- 
- 	  path = TREE_CHAIN (path);
  	}
  
!       /* If we found an overrider, record the overriding function, and
! 	 the base from which it came.  */
!       if (path)
! 	{
! 	  tree *candidate;
  
! 	  /* Remove any candidates overridden by this new function.  */
! 	  candidate = &ffod->candidates;
! 	  while (*candidate)
! 	    {
! 	      /* If *CANDIDATE overrides METHOD, then METHOD
! 		 cannot override anything else on the list.  */
! 	      if (base_derived_from (TREE_VALUE (*candidate), path))
! 		  return NULL_TREE;
! 	      /* If METHOD overrides *CANDIDATE, remove *CANDIDATE.  */
! 	      if (base_derived_from (path, TREE_VALUE (*candidate)))
! 		*candidate = TREE_CHAIN (*candidate);
! 	      else
! 		candidate = &TREE_CHAIN (*candidate);
! 	    }
  
! 	  /* Add the new function.  */
! 	  ffod->candidates = tree_cons (method, path, ffod->candidates);
! 	}
!     }
  
    return NULL_TREE;
  }
  
--- 2083,2164 ----
  {
    find_final_overrider_data *ffod = (find_final_overrider_data *) data;
  
!   if (binfo == ffod->declaring_base)
!     {
!       /* We've found a path to the declaring base.  Walk the path from
! 	 derived to base, looking for an overrider for FN.  */
!       tree path, probe, vpath;
! 
!       /* Build the path, using the inheritance chain and record of
! 	 virtual inheritance.  */
!       for (path = NULL_TREE, probe = binfo, vpath = ffod->vpath;;)
  	{
! 	  path = tree_cons (NULL_TREE, probe, path);
! 	  if (same_type_p (BINFO_TYPE (probe), ffod->most_derived_type))
! 	    break;
! 	  if (TREE_VIA_VIRTUAL (probe))
! 	    {
! 	      probe = TREE_VALUE (vpath);
! 	      vpath = TREE_CHAIN (vpath);
! 	    }
! 	  else
! 	    probe = BINFO_INHERITANCE_CHAIN (probe);
! 	}
!       /* Now walk path, looking for overrides.  */
!       for (; path; path = TREE_CHAIN (path))
! 	{
! 	  tree method = look_for_overrides_here
! 	    (BINFO_TYPE (TREE_VALUE (path)), ffod->fn);
! 	  
  	  if (method)
  	    {
+ 	      tree *candidate = &ffod->candidates;
  	      path = TREE_VALUE (path);
+ 
+ 	      /* Remove any candidates overridden by this new function.  */
+ 	      while (*candidate)
+ 		{
+ 		  /* If *CANDIDATE overrides METHOD, then METHOD
+ 		     cannot override anything else on the list.  */
+ 		  if (base_derived_from (TREE_VALUE (*candidate), path))
+ 		    return NULL_TREE;
+ 		  /* If METHOD overrides *CANDIDATE, remove *CANDIDATE.  */
+ 		  if (base_derived_from (path, TREE_VALUE (*candidate)))
+ 		    *candidate = TREE_CHAIN (*candidate);
+ 		  else
+ 		    candidate = &TREE_CHAIN (*candidate);
+ 		}
+ 	      
+ 	      /* Add the new function.  */
+ 	      ffod->candidates = tree_cons (method, path, ffod->candidates);
  	      break;
  	    }
  	}
+     }
  
!   return NULL_TREE;
! }
  
! static tree
! dfs_find_final_overrider_q (tree derived, int ix, void *data)
! {
!   tree binfo = BINFO_BASETYPE (derived, ix);
!   find_final_overrider_data *ffod = (find_final_overrider_data *) data;
  
!   if (TREE_VIA_VIRTUAL (binfo))
!     ffod->vpath = tree_cons (NULL_TREE, derived, ffod->vpath);
!   
!   return binfo;
! }
! 
! static tree
! dfs_find_final_overrider_post (tree binfo, void *data)
! {
!   find_final_overrider_data *ffod = (find_final_overrider_data *) data;
  
+   if (TREE_VIA_VIRTUAL (binfo) && TREE_CHAIN (ffod->vpath))
+     ffod->vpath = TREE_CHAIN (ffod->vpath);
+   
    return NULL_TREE;
  }
  
*************** find_final_overrider (tree derived, tree
*** 2354,2364 ****
    ffod.declaring_base = binfo;
    ffod.most_derived_type = BINFO_TYPE (derived);
    ffod.candidates = NULL_TREE;
  
!   dfs_walk (derived,
! 	    dfs_find_final_overrider,
! 	    NULL,
! 	    &ffod);
  
    /* If there was no winner, issue an error message.  */
    if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
--- 2197,2209 ----
    ffod.declaring_base = binfo;
    ffod.most_derived_type = BINFO_TYPE (derived);
    ffod.candidates = NULL_TREE;
+   ffod.vpath = NULL_TREE;
  
!   dfs_walk_real (derived,
! 		 dfs_find_final_overrider,
! 		 dfs_find_final_overrider_post,
! 		 dfs_find_final_overrider_q,
! 		 &ffod);
  
    /* If there was no winner, issue an error message.  */
    if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
*************** update_vtable_entry_for_fn (tree t, tree
*** 2448,2456 ****
  	{
  	  fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn));
  	  virtual_offset = THUNK_VIRTUAL_OFFSET (fn);
- 	  if (virtual_offset)
- 	    virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset),
- 					      TREE_TYPE (over_return));
  	}
        else
  	fixed_offset = virtual_offset = NULL_TREE;
--- 2293,2298 ----
*************** update_vtable_entry_for_fn (tree t, tree
*** 2477,2487 ****
  		     base and adjust the fixed offset to be from there.  */
  		  while (!TREE_VIA_VIRTUAL (thunk_binfo))
  		    thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
! 	      
! 		  virtual_offset = binfo_for_vbase (BINFO_TYPE (thunk_binfo),
! 						    TREE_TYPE (over_return));
  		  offset = size_binop (MINUS_EXPR, offset,
! 					BINFO_OFFSET (virtual_offset));
  		}
  	      if (fixed_offset)
  		/* There was an existing fixed offset, this must be
--- 2319,2328 ----
  		     base and adjust the fixed offset to be from there.  */
  		  while (!TREE_VIA_VIRTUAL (thunk_binfo))
  		    thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
! 
! 		  virtual_offset = thunk_binfo;
  		  offset = size_binop (MINUS_EXPR, offset,
! 				       BINFO_OFFSET (virtual_offset));
  		}
  	      if (fixed_offset)
  		/* There was an existing fixed offset, this must be
*************** update_vtable_entry_for_fn (tree t, tree
*** 2520,2527 ****
        /* If we find a virtual base, and we haven't yet found the
  	 overrider, then there is a virtual base between the
  	 declaring base (first_defn) and the final overrider.  */
!       if (!virtual_base && TREE_VIA_VIRTUAL (b))
! 	virtual_base = b;
      }
  
    if (overrider_fn != overrider_target && !virtual_base)
--- 2361,2371 ----
        /* If we find a virtual base, and we haven't yet found the
  	 overrider, then there is a virtual base between the
  	 declaring base (first_defn) and the final overrider.  */
!       if (TREE_VIA_VIRTUAL (b))
! 	{
! 	  virtual_base = b;
! 	  break;
! 	}
      }
  
    if (overrider_fn != overrider_target && !virtual_base)
*************** dfs_modify_vtables (tree binfo, void* da
*** 2619,2625 ****
  				    &virtuals, ix);
      }
  
!   SET_BINFO_MARKED (binfo);
  
    return NULL_TREE;
  }
--- 2463,2469 ----
  				    &virtuals, ix);
      }
  
!   BINFO_MARKED (binfo) = 1;
  
    return NULL_TREE;
  }
*************** modify_all_vtables (tree t, tree virtual
*** 2640,2650 ****
    tree *fnsp;
  
    /* Update all of the vtables.  */
!   dfs_walk (binfo, 
! 	    dfs_modify_vtables, 
! 	    dfs_unmarked_real_bases_queue_p,
! 	    t);
!   dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
  
    /* Add virtual functions not already in our primary vtable. These
       will be both those introduced by this class, and those overridden
--- 2484,2491 ----
    tree *fnsp;
  
    /* Update all of the vtables.  */
!   dfs_walk (binfo, dfs_modify_vtables, unmarkedp, t);
!   dfs_walk (binfo, dfs_unmark, markedp, t);
  
    /* Add virtual functions not already in our primary vtable. These
       will be both those introduced by this class, and those overridden
*************** walk_subobject_offsets (tree type, 
*** 3639,3660 ****
  		 virtual.  (If it is non-virtual, then it was walked
  		 above.)  */
  	      vbase = get_primary_binfo (type_binfo);
! 	      if (vbase && TREE_VIA_VIRTUAL (vbase))
  		{
! 		  tree derived = type_binfo;
! 		  while (BINFO_INHERITANCE_CHAIN (derived))
! 		    derived = BINFO_INHERITANCE_CHAIN (derived);
! 		  derived = TREE_TYPE (derived);
! 		  vbase = binfo_for_vbase (TREE_TYPE (vbase), derived);
! 
! 		  if (BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
! 		    {
! 		      r = (walk_subobject_offsets 
! 			   (vbase, f, offset,
! 			    offsets, max_offset, /*vbases_p=*/0));
! 		      if (r)
! 			return r;
! 		    }
  		}
  	    }
  	}
--- 3480,3493 ----
  		 virtual.  (If it is non-virtual, then it was walked
  		 above.)  */
  	      vbase = get_primary_binfo (type_binfo);
! 	      if (vbase && TREE_VIA_VIRTUAL (vbase)
! 		  && BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
  		{
! 		  r = (walk_subobject_offsets 
! 		       (vbase, f, offset,
! 			offsets, max_offset, /*vbases_p=*/0));
! 		  if (r)
! 		    return r;
  		}
  	    }
  	}
*************** layout_nonempty_base_or_field (record_la
*** 3774,3780 ****
  			       tree binfo, 
  			       splay_tree offsets)
  {
-   tree t = rli->t;
    tree offset = NULL_TREE;
    bool field_p;
    tree type;
--- 3607,3612 ----
*************** layout_nonempty_base_or_field (record_la
*** 3855,3862 ****
      propagate_binfo_offsets (binfo, 
  			     size_diffop (convert (ssizetype, offset),
  					  convert (ssizetype, 
! 						   BINFO_OFFSET (binfo))),
! 			     t);
  }
  
  /* Returns true if TYPE is empty and OFFSET is nonzero.  */
--- 3687,3693 ----
      propagate_binfo_offsets (binfo, 
  			     size_diffop (convert (ssizetype, offset),
  					  convert (ssizetype, 
! 						   BINFO_OFFSET (binfo))));
  }
  
  /* Returns true if TYPE is empty and OFFSET is nonzero.  */
*************** empty_base_at_nonzero_offset_p (tree typ
*** 3876,3882 ****
     type.  Return nonzero iff we added it at the end.  */
  
  static bool
! layout_empty_base (tree binfo, tree eoc, splay_tree offsets, tree t)
  {
    tree alignment;
    tree basetype = BINFO_TYPE (binfo);
--- 3707,3713 ----
     type.  Return nonzero iff we added it at the end.  */
  
  static bool
! layout_empty_base (tree binfo, tree eoc, splay_tree offsets)
  {
    tree alignment;
    tree basetype = BINFO_TYPE (binfo);
*************** layout_empty_base (tree binfo, tree eoc,
*** 3903,3909 ****
        /* That didn't work.  Now, we move forward from the next
  	 available spot in the class.  */
        atend = true;
!       propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
        while (1) 
  	{
  	  if (!layout_conflict_p (binfo,
--- 3734,3740 ----
        /* That didn't work.  Now, we move forward from the next
  	 available spot in the class.  */
        atend = true;
!       propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
        while (1) 
  	{
  	  if (!layout_conflict_p (binfo,
*************** layout_empty_base (tree binfo, tree eoc,
*** 3914,3920 ****
  	    break;
  
  	  /* There's overlap here, too.  Bump along to the next spot.  */
! 	  propagate_binfo_offsets (binfo, alignment, t);
  	}
      }
    return atend;
--- 3745,3751 ----
  	    break;
  
  	  /* There's overlap here, too.  Bump along to the next spot.  */
! 	  propagate_binfo_offsets (binfo, alignment);
  	}
      }
    return atend;
*************** build_base_field (record_layout_info rli
*** 3977,3983 ****
  	 byte-aligned.  */
        eoc = round_up (rli_size_unit_so_far (rli),
  		      CLASSTYPE_ALIGN_UNIT (basetype));
!       atend = layout_empty_base (binfo, eoc, offsets, t);
        /* A nearly-empty class "has no proper base class that is empty,
  	 not morally virtual, and at an offset other than zero."  */
        if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
--- 3808,3814 ----
  	 byte-aligned.  */
        eoc = round_up (rli_size_unit_so_far (rli),
  		      CLASSTYPE_ALIGN_UNIT (basetype));
!       atend = layout_empty_base (binfo, eoc, offsets);
        /* A nearly-empty class "has no proper base class that is empty,
  	 not morally virtual, and at an offset other than zero."  */
        if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
*************** build_base_fields (record_layout_info rl
*** 4056,4066 ****
        if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
  	continue;
  
!       /* A primary virtual base class is allocated just like any other
! 	 base class, but a non-primary virtual base is allocated
! 	 later, in layout_virtual_bases.  */
!       if (TREE_VIA_VIRTUAL (base_binfo) 
! 	  && !BINFO_PRIMARY_P (base_binfo))
  	continue;
  
        next_field = build_base_field (rli, base_binfo,
--- 3887,3895 ----
        if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
  	continue;
  
!       /* Virtual bases are added at the end (a primary virtual base
! 	 will have already been added).  */
!       if (TREE_VIA_VIRTUAL (base_binfo))
  	continue;
  
        next_field = build_base_field (rli, base_binfo,
*************** fixup_inline_methods (tree type)
*** 4657,4663 ****
     OFFSET, which is a type offset, is number of bytes.  */
  
  static void
! propagate_binfo_offsets (tree binfo, tree offset, tree t)
  {
    int i;
    tree primary_binfo;
--- 4486,4492 ----
     OFFSET, which is a type offset, is number of bytes.  */
  
  static void
! propagate_binfo_offsets (tree binfo, tree offset)
  {
    int i;
    tree primary_binfo;
*************** propagate_binfo_offsets (tree binfo, tre
*** 4698,4736 ****
  
        /* Skip virtual bases that aren't our canonical primary base.  */
        if (TREE_VIA_VIRTUAL (base_binfo)
! 	  && (BINFO_PRIMARY_BASE_OF (base_binfo) != binfo
! 	      || base_binfo != binfo_for_vbase (BINFO_TYPE (base_binfo), t)))
  	continue;
  
!       propagate_binfo_offsets (base_binfo, offset, t);
      }
  }
  
- /* Called via dfs_walk from layout_virtual bases.  */
- 
- static tree
- dfs_set_offset_for_unshared_vbases (tree binfo, void* data)
- {
-   /* If this is a virtual base, make sure it has the same offset as
-      the shared copy.  If it's a primary base, then we know it's
-      correct.  */
-   if (TREE_VIA_VIRTUAL (binfo))
-     {
-       tree t = (tree) data;
-       tree vbase;
-       tree offset;
-       
-       vbase = binfo_for_vbase (BINFO_TYPE (binfo), t);
-       if (vbase != binfo)
- 	{
- 	  offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
- 	  propagate_binfo_offsets (binfo, offset, t);
- 	}
-     }
- 
-   return NULL_TREE;
- }
- 
  /* Set BINFO_OFFSET for all of the virtual bases for RLI->T.  Update
     TYPE_ALIGN and TYPE_SIZE for T.  OFFSETS gives the location of
     empty subobjects of T.  */
--- 4527,4539 ----
  
        /* Skip virtual bases that aren't our canonical primary base.  */
        if (TREE_VIA_VIRTUAL (base_binfo)
! 	  && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo)
  	continue;
  
!       propagate_binfo_offsets (base_binfo, offset);
      }
  }
  
  /* Set BINFO_OFFSET for all of the virtual bases for RLI->T.  Update
     TYPE_ALIGN and TYPE_SIZE for T.  OFFSETS gives the location of
     empty subobjects of T.  */
*************** dfs_set_offset_for_unshared_vbases (tree
*** 4738,4744 ****
  static void
  layout_virtual_bases (record_layout_info rli, splay_tree offsets)
  {
!   tree vbases;
    tree t = rli->t;
    bool first_vbase = true;
    tree *next_field;
--- 4541,4547 ----
  static void
  layout_virtual_bases (record_layout_info rli, splay_tree offsets)
  {
!   tree vbase;
    tree t = rli->t;
    bool first_vbase = true;
    tree *next_field;
*************** layout_virtual_bases (record_layout_info
*** 4770,4786 ****
    /* Go through the virtual bases, allocating space for each virtual
       base that is not already a primary base class.  These are
       allocated in inheritance graph order.  */
!   for (vbases = TYPE_BINFO (t);
!        vbases; 
!        vbases = TREE_CHAIN (vbases))
      {
!       tree vbase;
! 
!       if (!TREE_VIA_VIRTUAL (vbases))
  	continue;
  
-       vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
- 
        if (!BINFO_PRIMARY_P (vbase))
  	{
  	  tree basetype = TREE_TYPE (vbase);
--- 4573,4583 ----
    /* Go through the virtual bases, allocating space for each virtual
       base that is not already a primary base class.  These are
       allocated in inheritance graph order.  */
!   for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
      {
!       if (!TREE_VIA_VIRTUAL (vbase))
  	continue;
  
        if (!BINFO_PRIMARY_P (vbase))
  	{
  	  tree basetype = TREE_TYPE (vbase);
*************** layout_virtual_bases (record_layout_info
*** 4811,4823 ****
  	  first_vbase = false;
  	}
      }
- 
-   /* Now, go through the TYPE_BINFO hierarchy, setting the
-      BINFO_OFFSETs correctly for all non-primary copies of the virtual
-      bases and their direct and indirect bases.  The ambiguity checks
-      in lookup_base depend on the BINFO_OFFSETs being set
-      correctly.  */
-   dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
  }
  
  /* Returns the offset of the byte just past the end of the base class
--- 4608,4613 ----
*************** finish_struct_1 (tree t)
*** 5378,5384 ****
        /* We must enter these virtuals into the table.  */
        if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
  	build_primary_vtable (NULL_TREE, t);
!       else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
  	/* Here we know enough to change the type of our virtual
  	   function table, but we will wait until later this function.  */
  	build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
--- 5168,5174 ----
        /* We must enter these virtuals into the table.  */
        if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
  	build_primary_vtable (NULL_TREE, t);
!       else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
  	/* Here we know enough to change the type of our virtual
  	   function table, but we will wait until later this function.  */
  	build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
*************** init_class_processing (void)
*** 5716,5730 ****
  				    * sizeof (struct class_stack_node));
    VARRAY_TREE_INIT (local_classes, 8, "local_classes");
  
-   access_default_node = build_int_2 (0, 0);
-   access_public_node = build_int_2 (ak_public, 0);
-   access_protected_node = build_int_2 (ak_protected, 0);
-   access_private_node = build_int_2 (ak_private, 0);
-   access_default_virtual_node = build_int_2 (4, 0);
-   access_public_virtual_node = build_int_2 (4 | ak_public, 0);
-   access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
-   access_private_virtual_node = build_int_2 (4 | ak_private, 0);
- 
    ridpointers[(int) RID_PUBLIC] = access_public_node;
    ridpointers[(int) RID_PRIVATE] = access_private_node;
    ridpointers[(int) RID_PROTECTED] = access_protected_node;
--- 5506,5511 ----
*************** get_vtbl_decl_for_binfo (tree binfo)
*** 6765,6866 ****
    return decl;
  }
  
- /* Called from get_primary_binfo via dfs_walk.  DATA is a TREE_LIST
-    who's TREE_PURPOSE is the TYPE of the required primary base and
-    who's TREE_VALUE is a list of candidate binfos that we fill in.  */
- 
- static tree
- dfs_get_primary_binfo (tree binfo, void* data)
- {
-   tree cons = (tree) data;
-   tree primary_base = TREE_PURPOSE (cons);
- 
-   if (TREE_VIA_VIRTUAL (binfo) 
-       && same_type_p (BINFO_TYPE (binfo), primary_base))
-     /* This is the right type of binfo, but it might be an unshared
-        instance, and the shared instance is later in the dfs walk.  We
-        must keep looking.  */
-     TREE_VALUE (cons) = tree_cons (NULL, binfo, TREE_VALUE (cons));
-   
-   return NULL_TREE;
- }
  
! /* Returns the unshared binfo for the primary base of BINFO.  Note
!    that in a complex hierarchy the resulting BINFO may not actually
!    *be* primary.  In particular if the resulting BINFO is a virtual
!    base, and it occurs elsewhere in the hierarchy, then this
!    occurrence may not actually be a primary base in the complete
!    object.  Check BINFO_PRIMARY_P to be sure.  */
  
  tree
  get_primary_binfo (tree binfo)
  {
    tree primary_base;
!   tree result = NULL_TREE;
!   tree virtuals;
    
    primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
    if (!primary_base)
      return NULL_TREE;
  
!   /* A non-virtual primary base is always a direct base, and easy to
!      find.  */
!   if (!TREE_VIA_VIRTUAL (primary_base))
!     {
!       int i;
! 
!       /* Scan the direct basetypes until we find a base with the same
! 	 type as the primary base.  */
!       for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
! 	{
! 	  tree base_binfo = BINFO_BASETYPE (binfo, i);
! 	  
! 	  if (same_type_p (BINFO_TYPE (base_binfo),
! 			   BINFO_TYPE (primary_base)))
! 	    return base_binfo;
! 	}
! 
!       /* We should always find the primary base.  */
!       abort ();
!     }
! 
!   /* For a primary virtual base, we have to scan the entire hierarchy
!      rooted at BINFO; the virtual base could be an indirect virtual
!      base.  There could be more than one instance of the primary base
!      in the hierarchy, and if one is the canonical binfo we want that
!      one.  If it exists, it should be the first one we find, but as a
!      consistency check we find them all and make sure.  */
!   virtuals = build_tree_list (BINFO_TYPE (primary_base), NULL_TREE);
!   dfs_walk (binfo, dfs_get_primary_binfo, NULL, virtuals);
!   virtuals = TREE_VALUE (virtuals);
!   
!   /* We must have found at least one instance.  */
!   my_friendly_assert (virtuals, 20010612);
! 
!   if (TREE_CHAIN (virtuals))
!     {
!       /* We found more than one instance of the base.  If one is the
! 	 canonical one, choose that one.  */
!       tree complete_binfo;
!       tree canonical;
!       
!       for (complete_binfo = binfo;
! 	   BINFO_INHERITANCE_CHAIN (complete_binfo);
! 	   complete_binfo = BINFO_INHERITANCE_CHAIN (complete_binfo))
! 	continue;
!       canonical = binfo_for_vbase (BINFO_TYPE (primary_base),
! 				   BINFO_TYPE (complete_binfo));
!       
!       for (; virtuals; virtuals = TREE_CHAIN (virtuals))
! 	{
! 	  result = TREE_VALUE (virtuals);
! 
! 	  if (canonical == result)
! 	    break;
! 	}
!     }
!   else
!     result = TREE_VALUE (virtuals);
    return result;
  }
  
--- 6546,6569 ----
    return decl;
  }
  
  
! /* Returns the binfo for the primary base of BINFO.  If the resulting
!    BINFO is a virtual base, and it is inherited elsewhere in the
!    hierarchy, then the returned binfo might not be the primary base of
!    BINFO in the complete object.  Check BINFO_PRIMARY_P or
!    BINFO_LOST_PRIMARY_P to be sure.  */
  
  tree
  get_primary_binfo (tree binfo)
  {
    tree primary_base;
!   tree result;
    
    primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
    if (!primary_base)
      return NULL_TREE;
  
!   result = copied_binfo (primary_base, binfo);
    return result;
  }
  
*************** maybe_indent_hierarchy (FILE * stream, i
*** 6874,6897 ****
    return 1;
  }
  
! /* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
!    dominated by T) to stderr.  INDENT should be zero when called from
!    the top level; it is incremented recursively.  */
  
! static void
! dump_class_hierarchy_r (FILE * stream,
                          int flags,
-                         tree t,
                          tree binfo,
                          int indent)
  {
-   int i;
    int indented = 0;
    
    indented = maybe_indent_hierarchy (stream, indent, 0);
    fprintf (stream, "%s (0x%lx) ",
  	   type_as_string (binfo, TFF_PLAIN_IDENTIFIER),
  	   (unsigned long) binfo);
    fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
  	   tree_low_cst (BINFO_OFFSET (binfo), 0));
    if (is_empty_class (BINFO_TYPE (binfo)))
--- 6577,6608 ----
    return 1;
  }
  
! /* Dump the offsets of all the bases rooted at BINFO to STREAM.
!    INDENT should be zero when called from the top level; it is
!    incremented recursively.  IGO indicates the next expected BINFO in
!    inheritance graph ordering. */
  
! static tree
! dump_class_hierarchy_r (FILE *stream,
                          int flags,
                          tree binfo,
+                         tree igo,
                          int indent)
  {
    int indented = 0;
+   tree base_binfos;
    
    indented = maybe_indent_hierarchy (stream, indent, 0);
    fprintf (stream, "%s (0x%lx) ",
  	   type_as_string (binfo, TFF_PLAIN_IDENTIFIER),
  	   (unsigned long) binfo);
+   if (binfo != igo)
+     {
+       fprintf (stream, "alternative-path\n");
+       return igo;
+     }
+   igo = TREE_CHAIN (binfo);
+   
    fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
  	   tree_low_cst (BINFO_OFFSET (binfo), 0));
    if (is_empty_class (BINFO_TYPE (binfo)))
*************** dump_class_hierarchy_r (FILE * stream,
*** 6899,6913 ****
    else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
      fprintf (stream, " nearly-empty");
    if (TREE_VIA_VIRTUAL (binfo))
!     {
!       tree canonical = binfo_for_vbase (BINFO_TYPE (binfo), t);
! 
!       fprintf (stream, " virtual");
!       if (canonical == binfo)
!         fprintf (stream, " canonical");
!       else
!         fprintf (stream, " non-canonical");
!     }
    fprintf (stream, "\n");
  
    indented = 0;
--- 6610,6616 ----
    else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
      fprintf (stream, " nearly-empty");
    if (TREE_VIA_VIRTUAL (binfo))
!     fprintf (stream, " virtual");
    fprintf (stream, "\n");
  
    indented = 0;
*************** dump_class_hierarchy_r (FILE * stream,
*** 6964,6974 ****
  	fprintf (stream, "\n");
      }
    
  
!   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
!     dump_class_hierarchy_r (stream, flags,
! 			    t, BINFO_BASETYPE (binfo, i),
! 			    indent + 2);
  }
  
  /* Dump the BINFO hierarchy for T.  */
--- 6667,6688 ----
  	fprintf (stream, "\n");
      }
    
+   base_binfos = BINFO_BASETYPES (binfo);
+   if (base_binfos)
+     {
+       int ix, n;
  
!       n = TREE_VEC_LENGTH (base_binfos);
!       for (ix = 0; ix != n; ix++)
! 	{
! 	  tree base_binfo = TREE_VEC_ELT (base_binfos, ix);
! 
! 	  igo = dump_class_hierarchy_r (stream, flags, base_binfo,
! 					igo, indent + 2);
! 	}
!     }
!   
!   return igo;
  }
  
  /* Dump the BINFO hierarchy for T.  */
*************** dump_class_hierarchy (tree t)
*** 6986,6992 ****
    fprintf (stream, "   size=%lu align=%lu\n",
  	   (unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
  	   (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
!   dump_class_hierarchy_r (stream, flags, t, TYPE_BINFO (t), 0);
    fprintf (stream, "\n");
    dump_end (TDI_class, stream);
  }
--- 6700,6711 ----
    fprintf (stream, "   size=%lu align=%lu\n",
  	   (unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
  	   (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
!   fprintf (stream, "   base size=%lu base align=%lu\n",
! 	   (unsigned long)(tree_low_cst (TYPE_SIZE (CLASSTYPE_AS_BASE (t)), 0)
! 			   / BITS_PER_UNIT),
! 	   (unsigned long)(TYPE_ALIGN (CLASSTYPE_AS_BASE (t))
! 			   / BITS_PER_UNIT));
!   dump_class_hierarchy_r (stream, flags, TYPE_BINFO (t), TYPE_BINFO (t), 0);
    fprintf (stream, "\n");
    dump_end (TDI_class, stream);
  }
*************** finish_vtbls (tree t)
*** 7072,7078 ****
  {
    tree list;
    tree vbase;
-   int i;
  
    /* We lay out the primary and secondary vtables in one contiguous
       vtable.  The primary vtable is first, followed by the non-virtual
--- 6791,6796 ----
*************** finish_vtbls (tree t)
*** 7084,7112 ****
    /* Then come the virtual bases, also in inheritance graph order.  */
    for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
      {
-       tree real_base;
- 	  
        if (!TREE_VIA_VIRTUAL (vbase))
  	continue;
!           
!       /* Although we walk in inheritance order, that might not get the
!          canonical base.  */
!       real_base = binfo_for_vbase (BINFO_TYPE (vbase), t);
!           
!       accumulate_vtbl_inits (real_base, real_base,
! 			     TYPE_BINFO (t), t, list);
!     }
! 
!   /* Fill in BINFO_VPTR_FIELD in the immediate binfos for our virtual
!      base classes, for the benefit of the debugging backends.  */
!   for (i = 0; i < BINFO_N_BASETYPES (TYPE_BINFO (t)); ++i)
!     {
!       tree base = BINFO_BASETYPE (TYPE_BINFO (t), i);
!       if (TREE_VIA_VIRTUAL (base))
! 	{
! 	  vbase = binfo_for_vbase (BINFO_TYPE (base), t);
! 	  BINFO_VPTR_FIELD (base) = BINFO_VPTR_FIELD (vbase);
! 	}
      }
  
    if (TYPE_BINFO_VTABLE (t))
--- 6802,6810 ----
    /* Then come the virtual bases, also in inheritance graph order.  */
    for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
      {
        if (!TREE_VIA_VIRTUAL (vbase))
  	continue;
!       accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
      }
  
    if (TYPE_BINFO_VTABLE (t))
*************** build_vtt (tree t)
*** 7186,7216 ****
    dump_vtt (t, vtt);
  }
  
- /* The type corresponding to BASE_BINFO is a base of the type of BINFO, but
-    from within some hierarchy which is inherited from the type of BINFO.
-    Return BASE_BINFO's equivalent binfo from the hierarchy dominated by
-    BINFO.  */
- 
- static tree
- get_original_base (tree base_binfo, tree binfo)
- {
-   tree derived;
-   int ix;
-   
-   if (same_type_p (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo)))
-     return binfo;
-   if (TREE_VIA_VIRTUAL (base_binfo))
-     return binfo_for_vbase (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo));
-   derived = get_original_base (BINFO_INHERITANCE_CHAIN (base_binfo), binfo);
-   
-   for (ix = 0; ix != BINFO_N_BASETYPES (derived); ix++)
-     if (same_type_p (BINFO_TYPE (base_binfo),
-                      BINFO_TYPE (BINFO_BASETYPE (derived, ix))))
-       return BINFO_BASETYPE (derived, ix);
-   abort ();
-   return NULL;
- }
- 
  /* When building a secondary VTT, BINFO_VTABLE is set to a TREE_LIST with
     PURPOSE the RTTI_BINFO, VALUE the real vtable pointer for this binfo,
     and CHAIN the vtable pointer for this binfo after construction is
--- 6884,6889 ----
*************** build_vtt_inits (tree binfo, tree t, tre
*** 7320,7332 ****
    if (top_level_p)
      for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
        {
- 	tree vbase;
- 	
  	if (!TREE_VIA_VIRTUAL (b))
  	  continue;
  	
! 	vbase = binfo_for_vbase (BINFO_TYPE (b), t);
! 	inits = build_vtt_inits (vbase, t, inits, index);
        }
  
    if (!top_level_p)
--- 6993,7002 ----
    if (top_level_p)
      for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
        {
  	if (!TREE_VIA_VIRTUAL (b))
  	  continue;
  	
! 	inits = build_vtt_inits (b, t, inits, index);
        }
  
    if (!top_level_p)
*************** dfs_build_secondary_vptr_vtt_inits (tree
*** 7363,7369 ****
    t = TREE_CHAIN (l);
    top_level_p = VTT_TOP_LEVEL_P (l);
    
!   SET_BINFO_MARKED (binfo);
  
    /* We don't care about bases that don't have vtables.  */
    if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
--- 7033,7039 ----
    t = TREE_CHAIN (l);
    top_level_p = VTT_TOP_LEVEL_P (l);
    
!   BINFO_MARKED (binfo) = 1;
  
    /* We don't care about bases that don't have vtables.  */
    if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
*************** dfs_build_secondary_vptr_vtt_inits (tree
*** 7414,7425 ****
     hierarchy.  */
  
  static tree
! dfs_ctor_vtable_bases_queue_p (tree binfo, void* data)
  {
!   if (TREE_VIA_VIRTUAL (binfo))
!      /* Get the shared version.  */
!     binfo = binfo_for_vbase (BINFO_TYPE (binfo), TREE_PURPOSE ((tree) data));
! 
    if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data))
      return NULL_TREE;
    return binfo;
--- 7084,7094 ----
     hierarchy.  */
  
  static tree
! dfs_ctor_vtable_bases_queue_p (tree derived, int ix,
! 			       void* data)
  {
!   tree binfo = BINFO_BASETYPE (derived, ix);
!   
    if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data))
      return NULL_TREE;
    return binfo;
*************** dfs_ctor_vtable_bases_queue_p (tree binf
*** 7433,7439 ****
  static tree
  dfs_fixup_binfo_vtbls (tree binfo, void* data)
  {
!   CLEAR_BINFO_MARKED (binfo);
  
    /* We don't care about bases that don't have vtables.  */
    if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
--- 7102,7108 ----
  static tree
  dfs_fixup_binfo_vtbls (tree binfo, void* data)
  {
!   BINFO_MARKED (binfo) = 0;
  
    /* We don't care about bases that don't have vtables.  */
    if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
*************** build_ctor_vtbl_group (tree binfo, tree 
*** 7484,7497 ****
         vbase = TREE_CHAIN (vbase))
      {
        tree b;
-       tree orig_base;
  
        if (!TREE_VIA_VIRTUAL (vbase))
  	continue;
!       b = binfo_for_vbase (BINFO_TYPE (vbase), t);
!       orig_base = binfo_for_vbase (BINFO_TYPE (vbase), BINFO_TYPE (binfo));
        
!       accumulate_vtbl_inits (b, orig_base, binfo, t, list);
      }
    inits = TREE_VALUE (list);
  
--- 7153,7164 ----
         vbase = TREE_CHAIN (vbase))
      {
        tree b;
  
        if (!TREE_VIA_VIRTUAL (vbase))
  	continue;
!       b = copied_binfo (vbase, binfo);
        
!       accumulate_vtbl_inits (b, vbase, binfo, t, list);
      }
    inits = TREE_VALUE (list);
  
*************** dfs_accumulate_vtbl_inits (tree binfo,
*** 7621,7628 ****
  	 either case, we share our vtable with LAST, i.e. the
  	 derived-most base within B of which we are a primary.  */
        if (b == rtti_binfo
! 	  || (b && binfo_for_vbase (BINFO_TYPE (b),
! 				    BINFO_TYPE (rtti_binfo))))
  	/* Just set our BINFO_VTABLE to point to LAST, as we may not have
  	   set LAST's BINFO_VTABLE yet.  We'll extract the actual vptr in
  	   binfo_ctor_vtable after everything's been set up.  */
--- 7288,7295 ----
  	 either case, we share our vtable with LAST, i.e. the
  	 derived-most base within B of which we are a primary.  */
        if (b == rtti_binfo
! 	  || (b && purpose_member (BINFO_TYPE (b),
! 				   CLASSTYPE_VBASECLASSES (BINFO_TYPE (rtti_binfo)))))
  	/* Just set our BINFO_VTABLE to point to LAST, as we may not have
  	   set LAST's BINFO_VTABLE yet.  We'll extract the actual vptr in
  	   binfo_ctor_vtable after everything's been set up.  */
*************** dfs_accumulate_vtbl_inits (tree binfo,
*** 7630,7636 ****
  
        /* Otherwise, this is case 3 and we get our own.  */
      }
!   else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
      return inits;
  
    if (!vtbl)
--- 7297,7303 ----
  
        /* Otherwise, this is case 3 and we get our own.  */
      }
!   else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo))
      return inits;
  
    if (!vtbl)
*************** build_vtbl_initializer (tree binfo,
*** 7733,7739 ****
    for (vbase = CLASSTYPE_VBASECLASSES (t); 
         vbase; 
         vbase = TREE_CHAIN (vbase))
!     CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
  
    /* If the target requires padding between data entries, add that now.  */
    if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
--- 7400,7406 ----
    for (vbase = CLASSTYPE_VBASECLASSES (t); 
         vbase; 
         vbase = TREE_CHAIN (vbase))
!     BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase)) = 0;
  
    /* If the target requires padding between data entries, add that now.  */
    if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
*************** build_vbase_offset_vtbl_entries (tree bi
*** 7937,7949 ****
  
        /* Find the instance of this virtual base in the complete
  	 object.  */
!       b = binfo_for_vbase (BINFO_TYPE (vbase), t);
  
        /* If we've already got an offset for this virtual base, we
  	 don't need another one.  */
        if (BINFO_VTABLE_PATH_MARKED (b))
  	continue;
!       SET_BINFO_VTABLE_PATH_MARKED (b);
  
        /* Figure out where we can find this vbase offset.  */
        delta = size_binop (MULT_EXPR, 
--- 7604,7616 ----
  
        /* Find the instance of this virtual base in the complete
  	 object.  */
!       b = copied_binfo (vbase, binfo);
  
        /* If we've already got an offset for this virtual base, we
  	 don't need another one.  */
        if (BINFO_VTABLE_PATH_MARKED (b))
  	continue;
!       BINFO_VTABLE_PATH_MARKED (b) = 1;
  
        /* Figure out where we can find this vbase offset.  */
        delta = size_binop (MULT_EXPR, 
*************** build_vbase_offset_vtbl_entries (tree bi
*** 7955,7970 ****
  
        if (binfo != TYPE_BINFO (t))
  	{
- 	  tree orig_vbase;
- 
- 	  /* Find the instance of this virtual base in the type of BINFO.  */
- 	  orig_vbase = binfo_for_vbase (BINFO_TYPE (vbase),
- 					BINFO_TYPE (binfo));
- 
  	  /* The vbase offset had better be the same.  */
! 	  if (!tree_int_cst_equal (delta,
! 				   BINFO_VPTR_FIELD (orig_vbase)))
! 	    abort ();
  	}
  
        /* The next vbase will come at a more negative offset.  */
--- 7622,7631 ----
  
        if (binfo != TYPE_BINFO (t))
  	{
  	  /* The vbase offset had better be the same.  */
! 	  my_friendly_assert (tree_int_cst_equal (delta,
! 						  BINFO_VPTR_FIELD (vbase)),
! 			      20030202);
  	}
  
        /* The next vbase will come at a more negative offset.  */
*************** add_vcall_offset_vtbl_entries_1 (tree bi
*** 8118,8125 ****
        if (vid->ctor_vtbl_p)
  	/* For a ctor vtable we need the equivalent binfo within the hierarchy
  	   where rtti_binfo is the most derived type.  */
! 	non_primary_binfo = get_original_base
!           (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
        
        for (base_virtuals = BINFO_VIRTUALS (binfo),
  	     derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
--- 7779,7786 ----
        if (vid->ctor_vtbl_p)
  	/* For a ctor vtable we need the equivalent binfo within the hierarchy
  	   where rtti_binfo is the most derived type.  */
! 	non_primary_binfo
! 	  = original_binfo (non_primary_binfo, vid->rtti_binfo);
        
        for (base_virtuals = BINFO_VIRTUALS (binfo),
  	     derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.811
diff -c -3 -p -r1.811 cp-tree.h
*** cp/cp-tree.h	15 Feb 2003 18:03:21 -0000	1.811
--- cp/cp-tree.h	17 Feb 2003 19:44:01 -0000
*************** struct diagnostic_context;
*** 58,64 ****
        TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
        INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
        ICS_ELLIPSIS_FLAG (in _CONV)
!       BINFO_ACCESS (in BINFO)
        DECL_INITIALIZED_P (in VAR_DECL)
     2: IDENTIFIER_OPNAME_P.
        TYPE_POLYMORPHIC_P (in _TYPE)
--- 58,64 ----
        TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
        INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
        ICS_ELLIPSIS_FLAG (in _CONV)
!       BINFO_DEPENDENT_BASE_P (in BINFO)
        DECL_INITIALIZED_P (in VAR_DECL)
     2: IDENTIFIER_OPNAME_P.
        TYPE_POLYMORPHIC_P (in _TYPE)
*************** struct diagnostic_context;
*** 79,85 ****
        NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
        IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
     5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
!    6: BINFO_ACCESS (in BINFO)
  
     Usage of TYPE_LANG_FLAG_?:
     0: TYPE_DEPENDENT_P
--- 79,85 ----
        NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
        IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
     5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
!    6: For future expansion
  
     Usage of TYPE_LANG_FLAG_?:
     0: TYPE_DEPENDENT_P
*************** enum cp_tree_index
*** 595,609 ****
      CPTI_GLOBAL_DELETE_FNDECL,
      CPTI_AGGR_TAG,
  
-     CPTI_ACCESS_DEFAULT,
-     CPTI_ACCESS_PUBLIC,
-     CPTI_ACCESS_PROTECTED,
-     CPTI_ACCESS_PRIVATE,
-     CPTI_ACCESS_DEFAULT_VIRTUAL,
-     CPTI_ACCESS_PUBLIC_VIRTUAL,
-     CPTI_ACCESS_PROTECTED_VIRTUAL,
-     CPTI_ACCESS_PRIVATE_VIRTUAL,
- 
      CPTI_CTOR_IDENTIFIER,
      CPTI_COMPLETE_CTOR_IDENTIFIER,
      CPTI_BASE_CTOR_IDENTIFIER,
--- 595,600 ----
*************** extern GTY(()) tree cp_global_trees[CPTI
*** 685,703 ****
  #define global_delete_fndecl		cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
  #define current_aggr			cp_global_trees[CPTI_AGGR_TAG]
  
- /* Define the sets of attributes that member functions and baseclasses
-    can have.  These are sensible combinations of {public,private,protected}
-    cross {virtual,non-virtual}.  */
- 
- #define access_default_node             cp_global_trees[CPTI_ACCESS_DEFAULT]
- #define access_public_node              cp_global_trees[CPTI_ACCESS_PUBLIC]
- #define access_protected_node           cp_global_trees[CPTI_ACCESS_PROTECTED]
- #define access_private_node             cp_global_trees[CPTI_ACCESS_PRIVATE]
- #define access_default_virtual_node     cp_global_trees[CPTI_ACCESS_DEFAULT_VIRTUAL]
- #define access_public_virtual_node      cp_global_trees[CPTI_ACCESS_PUBLIC_VIRTUAL]
- #define access_protected_virtual_node   cp_global_trees[CPTI_ACCESS_PROTECTED_VIRTUAL]
- #define access_private_virtual_node     cp_global_trees[CPTI_ACCESS_PRIVATE_VIRTUAL]
- 
  /* We cache these tree nodes so as to call get_identifier less
     frequently.  */
  
--- 676,681 ----
*************** extern GTY(()) tree cp_global_trees[CPTI
*** 771,776 ****
--- 749,759 ----
  
  #define keyed_classes                   cp_global_trees[CPTI_KEYED_CLASSES]
  
+ /* Node to indicate default access. This must be distinct from the
+    access nodes in tree.h.  */
+ 
+ #define access_default_node		null_node
+ 
  /* Global state.  */
  
  struct saved_scope GTY(())
*************** struct lang_type GTY(())
*** 1417,1437 ****
  /* A chain of BINFOs for the direct and indirect virtual base classes
     that this type uses in a post-order depth-first left-to-right
     order.  (In other words, these bases appear in the order that they
!    should be initialized.)  If a virtual base is primary, then the
!    primary copy will appear on this list.  Thus, the BINFOs on this
!    list are all "real"; they are the same BINFOs that will be
!    encountered when using dfs_unmarked_real_bases_queue_p and related
!    functions.  */
  #define CLASSTYPE_VBASECLASSES(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vbases)
  
- /* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
-    binfo_for_vbase.  C is the most derived class for the hierarchy
-    containing BINFO.  */
- #define CANONICAL_BINFO(BINFO, C)		\
-   (TREE_VIA_VIRTUAL (BINFO)			\
-    ? binfo_for_vbase (BINFO_TYPE (BINFO), C)	\
-    : (BINFO))
- 
  /* Number of direct baseclasses of NODE.  */
  #define CLASSTYPE_N_BASECLASSES(NODE) \
    (BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
--- 1400,1408 ----
  /* A chain of BINFOs for the direct and indirect virtual base classes
     that this type uses in a post-order depth-first left-to-right
     order.  (In other words, these bases appear in the order that they
!    should be initialized.)  */
  #define CLASSTYPE_VBASECLASSES(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vbases)
  
  /* Number of direct baseclasses of NODE.  */
  #define CLASSTYPE_N_BASECLASSES(NODE) \
    (BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
*************** struct lang_type GTY(())
*** 1554,1616 ****
  /* Additional macros for inheritance information.  */
  
  /* The BINFO_INHERITANCE_CHAIN is used opposite to the description in
!    gcc/tree.h.  In particular if D is derived from B then the BINFO
!    for B (in D) will have a BINFO_INHERITANCE_CHAIN pointing to
!    D.  In tree.h, this pointer is described as pointing in other
!    direction.  There is a different BINFO for each path to a virtual
!    base; BINFOs for virtual bases are not shared.
! 
!    We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private
!    inheritance is indicated by the absence of the other two flags, not
!    by TREE_VIA_PRIVATE, which is unused.  */
! 
! /* Mark the binfo, whether shared or not. Each instance of a virtual
!    base can be separately marked.  */
! #define BINFO_UNSHARED_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
  
  /* Nonzero means marked by DFS or BFS search.  */
! #define BINFO_MARKED(NODE)			\
!   (TREE_VIA_VIRTUAL (NODE)			\
!    ? CLASSTYPE_MARKED (BINFO_TYPE (NODE))	\
!    : TREE_LANG_FLAG_0 (NODE))
! /* Macros needed because of C compilers that don't allow conditional
!    expressions to be lvalues.  Grr!  */
! #define SET_BINFO_MARKED(NODE)			\
!   (TREE_VIA_VIRTUAL(NODE)			\
!    ? SET_CLASSTYPE_MARKED (BINFO_TYPE (NODE))	\
!    : (void)(TREE_LANG_FLAG_0 (NODE) = 1))
! #define CLEAR_BINFO_MARKED(NODE)		\
!   (TREE_VIA_VIRTUAL (NODE)			\
!    ? CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (NODE))	\
!    : (void)(TREE_LANG_FLAG_0 (NODE) = 0))
  
  /* Nonzero means that this class is on a path leading to a new vtable.  */
! #define BINFO_VTABLE_PATH_MARKED(NODE)		\
!   (TREE_VIA_VIRTUAL (NODE)			\
!    ? CLASSTYPE_MARKED3 (BINFO_TYPE (NODE))	\
!    : TREE_LANG_FLAG_3 (NODE))
! #define SET_BINFO_VTABLE_PATH_MARKED(NODE)	\
!   (TREE_VIA_VIRTUAL(NODE)			\
!    ? SET_CLASSTYPE_MARKED3 (BINFO_TYPE (NODE))	\
!    : (TREE_LANG_FLAG_3 (NODE) = 1))
! #define CLEAR_BINFO_VTABLE_PATH_MARKED(NODE)	\
!   (TREE_VIA_VIRTUAL (NODE)			\
!    ? CLEAR_CLASSTYPE_MARKED3 (BINFO_TYPE (NODE))\
!    : (TREE_LANG_FLAG_3 (NODE) = 0))
! 
! /* Nonzero means B (a BINFO) has its own vtable.  Under the old ABI,
!    secondary vtables are sometimes shared.  Any copies will not have
!    this flag set.
! 
!    B is part of the hierarchy dominated by C.  */
! #define BINFO_NEW_VTABLE_MARKED(B, C) \
!   (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
  
  /* Any subobject that needs a new vtable must have a vptr and must not
     be a non-virtual primary base (since it would then use the vtable from a
     derived class and never become non-primary.)  */
! #define SET_BINFO_NEW_VTABLE_MARKED(B, C)				 \
!   (BINFO_NEW_VTABLE_MARKED (B, C) = 1,					 \
     my_friendly_assert (!BINFO_PRIMARY_P (B)				 \
  		       || TREE_VIA_VIRTUAL (B), 20000517),		 \
     my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE,  \
--- 1525,1552 ----
  /* Additional macros for inheritance information.  */
  
  /* The BINFO_INHERITANCE_CHAIN is used opposite to the description in
!    gcc/tree.h.  In particular if D is non-virtually derived from B
!    then the BINFO for B (in D) will have a BINFO_INHERITANCE_CHAIN
!    pointing to D.  If D is virtually derived, its
!    BINFO_INHERITANCE_CHAIN will point to the most derived binfo. In
!    tree.h, this pointer is described as pointing in other
!    direction.  The binfos of virtual bases are shared.  */
  
  /* Nonzero means marked by DFS or BFS search.  */
! #define BINFO_MARKED(NODE)   TREE_LANG_FLAG_0 (NODE)
  
  /* Nonzero means that this class is on a path leading to a new vtable.  */
! #define BINFO_VTABLE_PATH_MARKED(NODE) TREE_LANG_FLAG_3 (NODE)
! 
! /* Nonzero means B (a BINFO) has its own vtable.  Any copies will not
!    have this flag set. */
! #define BINFO_NEW_VTABLE_MARKED(B) (TREE_LANG_FLAG_4 (B))
  
  /* Any subobject that needs a new vtable must have a vptr and must not
     be a non-virtual primary base (since it would then use the vtable from a
     derived class and never become non-primary.)  */
! #define SET_BINFO_NEW_VTABLE_MARKED(B)					 \
!   (BINFO_NEW_VTABLE_MARKED (B) = 1,					 \
     my_friendly_assert (!BINFO_PRIMARY_P (B)				 \
  		       || TREE_VIA_VIRTUAL (B), 20000517),		 \
     my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE,  \
*************** struct lang_type GTY(())
*** 1618,1625 ****
  
  /* Nonzero means this class has done dfs_pushdecls.  */
  #define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE)
- #define SET_BINFO_PUSHDECLS_MARKED(NODE) SET_BINFO_VTABLE_PATH_MARKED (NODE)
- #define CLEAR_BINFO_PUSHDECLS_MARKED(NODE) CLEAR_BINFO_VTABLE_PATH_MARKED (NODE)
  
  /* Nonzero if this BINFO is a primary base class.  Note, this can be
     set for non-canononical virtual bases. For a virtual primary base
--- 1554,1559 ----
*************** struct lang_type GTY(())
*** 1646,1651 ****
--- 1580,1589 ----
  
  #define BINFO_LANG_ELTS (BINFO_ELTS + 3)
  
+ /* Nonzero if this binfo is for a dependent base - one that should not
+    be searched.  */
+ #define BINFO_DEPENDENT_BASE_P(NODE) TREE_LANG_FLAG_1(NODE)
+ 
  /* Nonzero if this binfo has lost its primary base binfo (because that
     is a nearly-empty virtual base that has been taken by some other
     base in the complete hierarchy.  */
*************** typedef enum tmpl_spec_kind {
*** 3080,3086 ****
  /* The various kinds of access.  BINFO_ACCESS depends on these being
     two bit quantities.  The numerical values are important; they are
     used to initialize RTTI data structures, so changing them changes
!    the ABI.  */
  typedef enum access_kind {
    ak_none = 0,             /* Inaccessible.  */
    ak_public = 1,           /* Accessible, as a `public' thing.  */
--- 3018,3024 ----
  /* The various kinds of access.  BINFO_ACCESS depends on these being
     two bit quantities.  The numerical values are important; they are
     used to initialize RTTI data structures, so changing them changes
!    the ABI.   */
  typedef enum access_kind {
    ak_none = 0,             /* Inaccessible.  */
    ak_public = 1,           /* Accessible, as a `public' thing.  */
*************** extern tree binfo_from_vbase			(tree);
*** 4146,4173 ****
  extern tree look_for_overrides_here		(tree, tree);
  extern int check_final_overrider		(tree, tree);
  extern tree dfs_walk                            (tree,
! 						       tree (*) (tree, void *),
! 						       tree (*) (tree, void *),
! 						       void *);
  extern tree dfs_walk_real                      (tree,
! 						       tree (*) (tree, void *),
! 						       tree (*) (tree, void *),
! 						       tree (*) (tree, void *),
! 						       void *);
  extern tree dfs_unmark                          (tree, void *);
! extern tree markedp                             (tree, void *);
! extern tree unmarkedp                           (tree, void *);
! extern tree dfs_unmarked_real_bases_queue_p     (tree, void *);
! extern tree dfs_marked_real_bases_queue_p       (tree, void *);
! extern tree dfs_skip_vbases                     (tree, void *);
! extern tree marked_vtable_pathp                 (tree, void *);
! extern tree unmarked_vtable_pathp               (tree, void *);
! extern tree find_vbase_instance                 (tree, tree);
! extern tree binfo_for_vbase                     (tree, tree);
  extern tree binfo_via_virtual                   (tree, tree);
  extern tree build_baselink                      (tree, tree, tree, tree);
  extern tree adjust_result_of_qualified_name_lookup
                                                  (tree, tree, tree);
  /* in semantics.c */
  extern void push_deferring_access_checks	(bool defer_p);
  extern void resume_deferring_access_checks	(void);
--- 4084,4107 ----
  extern tree look_for_overrides_here		(tree, tree);
  extern int check_final_overrider		(tree, tree);
  extern tree dfs_walk                            (tree,
! 						 tree (*) (tree, void *),
! 						 tree (*) (tree, int, void *),
! 						 void *);
  extern tree dfs_walk_real                      (tree,
! 						tree (*) (tree, void *),
! 						tree (*) (tree, void *),
! 						tree (*) (tree, int, void *),
! 						void *);
  extern tree dfs_unmark                          (tree, void *);
! extern tree markedp                             (tree, int, void *);
! extern tree unmarkedp                           (tree, int, void *);
  extern tree binfo_via_virtual                   (tree, tree);
  extern tree build_baselink                      (tree, tree, tree, tree);
  extern tree adjust_result_of_qualified_name_lookup
                                                  (tree, tree, tree);
+ extern tree copied_binfo			(tree, tree);
+ extern tree original_binfo			(tree, tree);
+ 
  /* in semantics.c */
  extern void push_deferring_access_checks	(bool defer_p);
  extern void resume_deferring_access_checks	(void);
*************** extern void finish_default_args         
*** 4249,4255 ****
  extern tree finish_member_class_template        (tree);
  extern void finish_template_decl                (tree);
  extern tree finish_template_type                (tree, tree, int);
! extern tree finish_base_specifier               (tree, tree);
  extern void finish_member_declaration           (tree);
  extern void check_multiple_declarators          (void);
  extern tree finish_typeof			(tree);
--- 4183,4189 ----
  extern tree finish_member_class_template        (tree);
  extern void finish_template_decl                (tree);
  extern tree finish_template_type                (tree, tree, int);
! extern tree finish_base_specifier               (tree, tree, bool);
  extern void finish_member_declaration           (tree);
  extern void check_multiple_declarators          (void);
  extern tree finish_typeof			(tree);
*************** extern void init_tree			        (void);
*** 4279,4285 ****
  extern int pod_type_p				(tree);
  extern int zero_init_p				(tree);
  extern tree canonical_type_variant              (tree);
! extern void unshare_base_binfos			(tree);
  extern int member_p				(tree);
  extern cp_lvalue_kind real_lvalue_p		(tree);
  extern int non_cast_lvalue_p			(tree);
--- 4213,4219 ----
  extern int pod_type_p				(tree);
  extern int zero_init_p				(tree);
  extern tree canonical_type_variant              (tree);
! extern tree copy_base_binfos			(tree, tree, tree);
  extern int member_p				(tree);
  extern cp_lvalue_kind real_lvalue_p		(tree);
  extern int non_cast_lvalue_p			(tree);
*************** extern tree hash_tree_cons			(tree, tree
*** 4297,4303 ****
  extern tree hash_tree_chain			(tree, tree);
  extern tree hash_chainon			(tree, tree);
  extern tree make_binfo				(tree, tree, tree, tree);
- extern tree reverse_path			(tree);
  extern int count_functions			(tree);
  extern int is_overloaded_fn			(tree);
  extern tree get_first_fn			(tree);
--- 4231,4236 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.998
diff -c -3 -p -r1.998 decl.c
*** cp/decl.c	15 Feb 2003 18:03:21 -0000	1.998
--- cp/decl.c	17 Feb 2003 19:44:58 -0000
*************** xref_tag_from_type (tree old, tree id, i
*** 12834,12850 ****
  }
  
  /* REF is a type (named NAME), for which we have just seen some
!    baseclasses.  BINFO is a list of those baseclasses; the
     TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
!    the base-class.  CODE_TYPE_NODE indicates whether REF is a class,
     struct, or union.  */
  
  void
! xref_basetypes (tree ref, tree binfo)
  {
    /* In the declaration `A : X, Y, ... Z' we mark all the types
       (A, X, Y, ..., Z) so we can check for duplicates.  */
-   tree binfos;
    tree *basep;
  
    int i;
--- 12834,12850 ----
  }
  
  /* REF is a type (named NAME), for which we have just seen some
!    baseclasses.  BASE_LIST is a list of those baseclasses; the
     TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
!    the base-class.  TREE_VIA_VIRTUAL indicates virtual
!    inheritance. CODE_TYPE_NODE indicates whether REF is a class,
     struct, or union.  */
  
  void
! xref_basetypes (tree ref, tree base_list)
  {
    /* In the declaration `A : X, Y, ... Z' we mark all the types
       (A, X, Y, ..., Z) so we can check for duplicates.  */
    tree *basep;
  
    int i;
*************** xref_basetypes (tree ref, tree binfo)
*** 12862,13006 ****
       instantiated.  This ensures that if we call ourselves recursively
       we do not get confused about which classes are marked and which
       are not.  */
!   basep = &binfo; 
    while (*basep) 
      {
        tree basetype = TREE_VALUE (*basep);
        if (!(processing_template_decl && uses_template_parms (basetype))
  	  && !complete_type_or_else (basetype, NULL))
! 	/* An incomplete type.  Remove it form the list.  */
  	*basep = TREE_CHAIN (*basep);
        else
  	basep = &TREE_CHAIN (*basep);
      }
  
    SET_CLASSTYPE_MARKED (ref);
!   BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos 
!     = make_tree_vec (list_length (binfo));
! 
!   for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
      {
!       /* The base of a derived struct is public by default.  */
!       int via_public
! 	= (TREE_PURPOSE (binfo) == access_public_node
! 	   || TREE_PURPOSE (binfo) == access_public_virtual_node
! 	   || (tag_code != class_type
! 	       && (TREE_PURPOSE (binfo) == access_default_node
! 		   || TREE_PURPOSE (binfo) == access_default_virtual_node)));
!       int via_protected
! 	= (TREE_PURPOSE (binfo) == access_protected_node
! 	   || TREE_PURPOSE (binfo) == access_protected_virtual_node);
!       int via_virtual
! 	= (TREE_PURPOSE (binfo) == access_private_virtual_node
! 	   || TREE_PURPOSE (binfo) == access_protected_virtual_node
! 	   || TREE_PURPOSE (binfo) == access_public_virtual_node
! 	   || TREE_PURPOSE (binfo) == access_default_virtual_node);
!       tree basetype = TREE_VALUE (binfo);
!       tree base_binfo;
! 
!       if (basetype && TREE_CODE (basetype) == TYPE_DECL)
! 	basetype = TREE_TYPE (basetype);
!       if (!basetype
! 	  || (TREE_CODE (basetype) != RECORD_TYPE
! 	      && TREE_CODE (basetype) != TYPENAME_TYPE
! 	      && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
! 	      && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
! 	{
! 	  error ("base type `%T' fails to be a struct or class type",
! 		    TREE_VALUE (binfo));
! 	  continue;
! 	}
! 
!       if (CLASSTYPE_MARKED (basetype))
  	{
! 	  if (basetype == ref)
! 	    error ("recursive type `%T' undefined", basetype);
  	  else
! 	    error ("duplicate base type `%T' invalid", basetype);
! 	  continue;
  	}
! 
!       if (TYPE_FOR_JAVA (basetype)
! 	  && (current_lang_depth () == 0))
! 	TYPE_FOR_JAVA (ref) = 1;
! 
!       /* Note that the BINFO records which describe individual
! 	 inheritances are *not* shared in the lattice!  They
! 	 cannot be shared because a given baseclass may be
! 	 inherited with different `accessibility' by different
! 	 derived classes.  (Each BINFO record describing an
! 	 individual inheritance contains flags which say what
! 	 the `accessibility' of that particular inheritance is.)  */
! 
!       base_binfo
! 	= make_binfo (size_zero_node, basetype,
! 		      CLASS_TYPE_P (basetype)
! 		      ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
! 		      CLASS_TYPE_P (basetype)
! 		      ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
! 
!       TREE_VEC_ELT (binfos, i) = base_binfo;
!       TREE_VIA_PUBLIC (base_binfo) = via_public;
!       TREE_VIA_PROTECTED (base_binfo) = via_protected;
!       TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
!       BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
! 
!       /* We need to unshare the binfos now so that lookups during class
! 	 definition work.  */
!       unshare_base_binfos (base_binfo);
! 
!       SET_CLASSTYPE_MARKED (basetype);
! 
!       /* We are free to modify these bits because they are meaningless
! 	 at top level, and BASETYPE is a top-level type.  */
!       if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
  	{
! 	  TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
! 	  /* Converting to a virtual base class requires looking
! 	     up the offset of the virtual base.  */
  	  TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
  	}
! 
        if (CLASS_TYPE_P (basetype))
  	{
! 	  TYPE_HAS_NEW_OPERATOR (ref)
! 	    |= TYPE_HAS_NEW_OPERATOR (basetype);
! 	  TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
! 	    |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
! 	  TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
! 	  /* If the base-class uses multiple inheritance, so do we.  */
! 	  TYPE_USES_MULTIPLE_INHERITANCE (ref)
! 	    |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
! 	  /* Likewise, if converting to a base of the base may require
! 	     code, then we may need to generate code to convert to a
! 	     base as well.  */
! 	  TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
! 	    |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
  	}
- 
-       i += 1;
      }
-   if (i)
-     TREE_VEC_LENGTH (binfos) = i;
-   else
-     BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
- 
-   if (i > 1)
-     {
-       TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
-       /* If there is more than one non-empty they cannot be at the same
- 	 address.  */
-       TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
-     }
- 
-   /* Unmark all the types.  */
-   while (--i >= 0)
-     CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
    CLEAR_CLASSTYPE_MARKED (ref);
- 
-   /* Now that we know all the base-classes, set up the list of virtual
-      bases.  */
-   get_vbase_types (ref);
  }
  
  
--- 12862,13008 ----
       instantiated.  This ensures that if we call ourselves recursively
       we do not get confused about which classes are marked and which
       are not.  */
!   basep = &base_list; 
    while (*basep) 
      {
        tree basetype = TREE_VALUE (*basep);
        if (!(processing_template_decl && uses_template_parms (basetype))
  	  && !complete_type_or_else (basetype, NULL))
! 	/* An incomplete type.  Remove it from the list.  */
  	*basep = TREE_CHAIN (*basep);
        else
  	basep = &TREE_CHAIN (*basep);
      }
  
    SET_CLASSTYPE_MARKED (ref);
!   i = list_length (base_list);
!   if (i)
      {
!       tree binfo = TYPE_BINFO (ref);
!       tree binfos = make_tree_vec (i);
!       tree accesses = make_tree_vec (i);
!       
!       BINFO_BASETYPES (binfo) = binfos;
!       BINFO_BASEACCESSES (binfo) = accesses;
!   
!       for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
  	{
! 	  tree access = TREE_PURPOSE (base_list);
! 	  int via_virtual = TREE_VIA_VIRTUAL (base_list);
! 	  tree basetype = TREE_VALUE (base_list);
! 	  tree base_binfo;
! 	  
! 	  if (access == access_default_node)
! 	    /* The base of a derived struct is public by default.  */
! 	    access = (tag_code == class_type
! 		      ? access_private_node : access_public_node);
! 	  
! 	  if (basetype && TREE_CODE (basetype) == TYPE_DECL)
! 	    basetype = TREE_TYPE (basetype);
! 	  if (!basetype
! 	      || (TREE_CODE (basetype) != RECORD_TYPE
! 		  && TREE_CODE (basetype) != TYPENAME_TYPE
! 		  && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
! 		  && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
! 	    {
! 	      error ("base type `%T' fails to be a struct or class type",
! 		     basetype);
! 	      continue;
! 	    }
! 	  
! 	  if (CLASSTYPE_MARKED (basetype))
! 	    {
! 	      if (basetype == ref)
! 		error ("recursive type `%T' undefined", basetype);
! 	      else
! 		error ("duplicate base type `%T' invalid", basetype);
! 	      continue;
! 	    }
! 	  
! 	  if (TYPE_FOR_JAVA (basetype)
! 	      && (current_lang_depth () == 0))
! 	    TYPE_FOR_JAVA (ref) = 1;
! 	  
! 	  if (CLASS_TYPE_P (basetype))
! 	    {
! 	      base_binfo = TYPE_BINFO (basetype);
! 	      /* This flag will be in the binfo of the base type, we must
! 	     	 clear it after copying the base binfos.  */
! 	      BINFO_DEPENDENT_BASE_P (base_binfo)
! 		= dependent_type_p (basetype);
! 	    }
  	  else
! 	    base_binfo = make_binfo (size_zero_node, basetype,
! 				     NULL_TREE, NULL_TREE);
! 	  
! 	  TREE_VEC_ELT (binfos, i) = base_binfo;
! 	  TREE_VEC_ELT (accesses, i) = access;
! 	  /* This flag will be in the binfo of the base type, we must
! 	     clear it after copying the base binfos.  */
! 	  TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
! 	  
! 	  SET_CLASSTYPE_MARKED (basetype);
! 	  
! 	  /* We are free to modify these bits because they are meaningless
! 	     at top level, and BASETYPE is a top-level type.  */
! 	  if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
! 	    {
! 	      TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
! 	      /* Converting to a virtual base class requires looking
! 	     	 up the offset of the virtual base.  */
! 	      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
! 	    }
! 	  
! 	  if (CLASS_TYPE_P (basetype))
! 	    {
! 	      TYPE_HAS_NEW_OPERATOR (ref)
! 		|= TYPE_HAS_NEW_OPERATOR (basetype);
! 	      TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
! 		|= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
! 	      TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
! 	      /* If the base-class uses multiple inheritance, so do we.  */
! 	      TYPE_USES_MULTIPLE_INHERITANCE (ref)
! 		|= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
! 	      /* Likewise, if converting to a base of the base may require
! 	     	 code, then we may need to generate code to convert to a
! 	     	 base as well.  */
! 	      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
! 		|= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
! 	    }
! 	  i++;
  	}
!       if (i)
! 	TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
!       else
! 	BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
!       
!       if (i > 1)
  	{
! 	  TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
! 	  /* If there is more than one non-empty they cannot be at the same
! 	     address.  */
  	  TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
  	}
!     }
!   
!   /* Copy the base binfos, collect the virtual bases and set the
!      inheritance order chain.  */
!   copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
!   CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
!   
!   /* Unmark all the types.  */
!   while (i--)
!     {
!       tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));
!       
!       CLEAR_CLASSTYPE_MARKED (basetype);
        if (CLASS_TYPE_P (basetype))
  	{
! 	  TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;
! 	  BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;
  	}
      }
    CLEAR_CLASSTYPE_MARKED (ref);
  }
  
  
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.309
diff -c -3 -p -r1.309 init.c
*** cp/init.c	15 Feb 2003 18:03:21 -0000	1.309
--- cp/init.c	17 Feb 2003 19:45:12 -0000
***************
*** 1,6 ****
  /* Handle initialization things in C++.
     Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann at cygnus dot com)
  
  This file is part of GCC.
--- 1,6 ----
  /* Handle initialization things in C++.
     Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann at cygnus dot com)
  
  This file is part of GCC.
*************** dfs_initialize_vtbl_ptrs (binfo, data)
*** 127,133 ****
        expand_virtual_init (binfo, base_ptr);
      }
  
!   SET_BINFO_MARKED (binfo);
  
    return NULL_TREE;
  }
--- 127,133 ----
        expand_virtual_init (binfo, base_ptr);
      }
  
!   BINFO_MARKED (binfo) = 1;
  
    return NULL_TREE;
  }
*************** initialize_vtbl_ptrs (addr)
*** 149,158 ****
       class.  We do these in pre-order because can't find the virtual
       bases for a class until we've initialized the vtbl for that
       class.  */
!   dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
! 		 NULL, dfs_unmarked_real_bases_queue_p, list);
!   dfs_walk (TYPE_BINFO (type), dfs_unmark,
! 	    dfs_marked_real_bases_queue_p, type);
  }
  
  /* Return an expression for the zero-initialization of an object with
--- 149,157 ----
       class.  We do these in pre-order because can't find the virtual
       bases for a class until we've initialized the vtbl for that
       class.  */
!   dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
! 		 NULL, unmarkedp, list);
!   dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, type);
  }
  
  /* Return an expression for the zero-initialization of an object with
*************** expand_member_init (tree name, tree init
*** 1001,1015 ****
  
        binfo = lookup_base (current_class_type, basetype, 
  			   ba_ignore, NULL);
!       if (binfo)
! 	{
! 	  if (TREE_VIA_VIRTUAL (binfo))
! 	    binfo = binfo_for_vbase (basetype, current_class_type);
! 	  else if (BINFO_INHERITANCE_CHAIN (binfo) 
! 		   != TYPE_BINFO (current_class_type))
! 	    binfo = NULL_TREE;
! 	}
!       if (!binfo)
  	{
  	  if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
  	    error ("type `%D' is not a direct or virtual base of `%T'",
--- 1000,1008 ----
  
        binfo = lookup_base (current_class_type, basetype, 
  			   ba_ignore, NULL);
!       if (!binfo || (!TREE_VIA_VIRTUAL (binfo)
! 		     && (BINFO_INHERITANCE_CHAIN (binfo)
! 			 != TYPE_BINFO (current_class_type))))
  	{
  	  if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
  	    error ("type `%D' is not a direct or virtual base of `%T'",
*************** expand_member_init (tree name, tree init
*** 1019,1027 ****
  		   name, current_class_type);
  	  return NULL_TREE;
  	}
! 
!       if (binfo)
! 	return build_tree_list (binfo, init);
      }
    else
      {
--- 1012,1018 ----
  		   name, current_class_type);
  	  return NULL_TREE;
  	}
!       return build_tree_list (binfo, init);
      }
    else
      {
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.42
diff -c -3 -p -r1.42 parser.c
*** cp/parser.c	30 Jan 2003 07:23:59 -0000	1.42
--- cp/parser.c	17 Feb 2003 19:46:03 -0000
*************** cp_parser_base_clause (cp_parser* parser
*** 12413,12434 ****
  static tree
  cp_parser_base_specifier (cp_parser* parser)
  {
-   static const tree *const access_nodes[][2] =
-   {
-     /* This ordering must match the access_kind enumeration.  */
-     {&access_default_node,   &access_default_virtual_node},
-     {&access_public_node,    &access_public_virtual_node},
-     {&access_protected_node, &access_protected_virtual_node},
-     {&access_private_node,   &access_private_virtual_node}
-   };
    cp_token *token;
    bool done = false;
    bool virtual_p = false;
    bool duplicate_virtual_error_issued_p = false;
    bool duplicate_access_error_issued_p = false;
    bool class_scope_p, template_p;
!   access_kind access = ak_none;
!   tree access_node;
    tree type;
  
    /* Process the optional `virtual' and `access-specifier'.  */
--- 12413,12425 ----
  static tree
  cp_parser_base_specifier (cp_parser* parser)
  {
    cp_token *token;
    bool done = false;
    bool virtual_p = false;
    bool duplicate_virtual_error_issued_p = false;
    bool duplicate_access_error_issued_p = false;
    bool class_scope_p, template_p;
!   tree access = access_default_node;
    tree type;
  
    /* Process the optional `virtual' and `access-specifier'.  */
*************** cp_parser_base_specifier (cp_parser* par
*** 12460,12475 ****
  	case RID_PRIVATE:
  	  /* If more than one access specifier appears, issue an
  	     error.  */
! 	  if (access != ak_none && !duplicate_access_error_issued_p)
  	    {
  	      cp_parser_error (parser,
  			       "more than one access specifier in base-specified");
  	      duplicate_access_error_issued_p = true;
  	    }
  
! 	  access = ((access_kind) 
! 		    tree_low_cst (ridpointers[(int) token->keyword],
! 				  /*pos=*/1));
  
  	  /* Consume the access-specifier.  */
  	  cp_lexer_consume_token (parser->lexer);
--- 12451,12465 ----
  	case RID_PRIVATE:
  	  /* If more than one access specifier appears, issue an
  	     error.  */
! 	  if (access != access_default_node
! 	      && !duplicate_access_error_issued_p)
  	    {
  	      cp_parser_error (parser,
  			       "more than one access specifier in base-specified");
  	      duplicate_access_error_issued_p = true;
  	    }
  
! 	  access = ridpointers[(int) token->keyword];
  
  	  /* Consume the access-specifier.  */
  	  cp_lexer_consume_token (parser->lexer);
*************** cp_parser_base_specifier (cp_parser* par
*** 12482,12490 ****
  	}
      }
  
-   /* Map `virtual_p' and `access' onto one of the access tree-nodes.  */
-   access_node = *access_nodes[access][virtual_p];
-   
    /* Look for the optional `::' operator.  */
    cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
    /* Look for the nested-name-specifier.  The simplest way to
--- 12472,12477 ----
*************** cp_parser_base_specifier (cp_parser* par
*** 12520,12526 ****
    if (type == error_mark_node)
      return error_mark_node;
  
!   return finish_base_specifier (access_node, TREE_TYPE (type));
  }
  
  /* Exception handling [gram.exception] */
--- 12507,12513 ----
    if (type == error_mark_node)
      return error_mark_node;
  
!   return finish_base_specifier (TREE_TYPE (type), access, virtual_p);
  }
  
  /* Exception handling [gram.exception] */
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.660
diff -c -3 -p -r1.660 pt.c
*** cp/pt.c	15 Feb 2003 18:03:22 -0000	1.660
--- cp/pt.c	17 Feb 2003 19:46:33 -0000
*************** instantiate_class_template (type)
*** 5146,5152 ****
  {
    tree template, args, pattern, t, member;
    tree typedecl;
! 
    if (type == error_mark_node)
      return error_mark_node;
  
--- 5146,5153 ----
  {
    tree template, args, pattern, t, member;
    tree typedecl;
!   tree pbinfo;
!   
    if (type == error_mark_node)
      return error_mark_node;
  
*************** instantiate_class_template (type)
*** 5277,5286 ****
    if (ANON_AGGR_TYPE_P (pattern))
      SET_ANON_AGGR_TYPE_P (type);
  
!   if (TYPE_BINFO_BASETYPES (pattern))
      {
        tree base_list = NULL_TREE;
!       tree pbases = TYPE_BINFO_BASETYPES (pattern);
        int i;
  
        /* Substitute into each of the bases to determine the actual
--- 5278,5290 ----
    if (ANON_AGGR_TYPE_P (pattern))
      SET_ANON_AGGR_TYPE_P (type);
  
!   pbinfo = TYPE_BINFO (pattern);
!   
!   if (BINFO_BASETYPES (pbinfo))
      {
        tree base_list = NULL_TREE;
!       tree pbases = BINFO_BASETYPES (pbinfo);
!       tree paccesses = BINFO_BASEACCESSES (pbinfo);
        int i;
  
        /* Substitute into each of the bases to determine the actual
*************** instantiate_class_template (type)
*** 5292,5324 ****
  	  tree pbase;
  
  	  pbase = TREE_VEC_ELT (pbases, i);
  
  	  /* Substitute to figure out the base class.  */
  	  base = tsubst (BINFO_TYPE (pbase), args, tf_error, NULL_TREE);
  	  if (base == error_mark_node)
  	    continue;
! 
! 	  /* Calculate the correct access node.  */
! 	  if (TREE_VIA_VIRTUAL (pbase)) 
! 	    {
! 	      if (TREE_VIA_PUBLIC (pbase))
! 		access = access_public_virtual_node;
! 	      else if (TREE_VIA_PROTECTED (pbase))
! 		access = access_protected_virtual_node;
! 	      else 
! 		access = access_private_virtual_node;
! 	    }
! 	  else
! 	    {
! 	      if (TREE_VIA_PUBLIC (pbase))
! 		access = access_public_node;
! 	      else if (TREE_VIA_PROTECTED (pbase))
! 		access = access_protected_node;
! 	      else 
! 		access = access_private_node;
! 	    }
! 
  	  base_list = tree_cons (access, base, base_list);
  	}
  
        /* The list is now in reverse order; correct that.  */
--- 5296,5310 ----
  	  tree pbase;
  
  	  pbase = TREE_VEC_ELT (pbases, i);
+ 	  access = TREE_VEC_ELT (paccesses, i);
  
  	  /* Substitute to figure out the base class.  */
  	  base = tsubst (BINFO_TYPE (pbase), args, tf_error, NULL_TREE);
  	  if (base == error_mark_node)
  	    continue;
! 	  
  	  base_list = tree_cons (access, base, base_list);
+ 	  TREE_VIA_VIRTUAL (base_list) = TREE_VIA_VIRTUAL (pbase);
  	}
  
        /* The list is now in reverse order; correct that.  */
*************** get_template_base_recursive (tparms, tar
*** 9162,9168 ****
        /* When searching for a non-virtual, we cannot mark virtually
  	 found binfos.  */
        if (! this_virtual)
! 	SET_BINFO_MARKED (base_binfo);
        
        rval = get_template_base_recursive (tparms, targs,
  					  parm,
--- 9148,9154 ----
        /* When searching for a non-virtual, we cannot mark virtually
  	 found binfos.  */
        if (! this_virtual)
! 	BINFO_MARKED (base_binfo) = 1;
        
        rval = get_template_base_recursive (tparms, targs,
  					  parm,
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.154
diff -c -3 -p -r1.154 rtti.c
*** cp/rtti.c	17 Jan 2003 20:14:44 -0000	1.154
--- cp/rtti.c	17 Feb 2003 19:46:36 -0000
*************** get_pseudo_ti_init (tree type, tree var_
*** 1039,1044 ****
--- 1039,1045 ----
  	  tree binfo = TYPE_BINFO (type);
            int nbases = BINFO_N_BASETYPES (binfo);
            tree base_binfos = BINFO_BASETYPES (binfo);
+ 	  tree base_accesses = BINFO_BASEACCESSES (binfo);
            tree base_inits = NULL_TREE;
            int ix;
            
*************** get_pseudo_ti_init (tree type, tree var_
*** 1051,1065 ****
                tree tinfo;
                tree offset;
                
!               if (TREE_PUBLIC (base_binfo))
                  flags |= 2;
                tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
  	      if (TREE_VIA_VIRTUAL (base_binfo))
  		{
  		   /* We store the vtable offset at which the virtual
         		      base offset can be found.  */
! 		  offset = BINFO_VPTR_FIELD
! 		    (binfo_for_vbase (BINFO_TYPE (base_binfo), type));
  		  offset = convert (sizetype, offset);
  		  flags |= 1;
  		}
--- 1052,1065 ----
                tree tinfo;
                tree offset;
                
!               if (TREE_VEC_ELT (base_accesses, ix) == access_public_node)
                  flags |= 2;
                tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
  	      if (TREE_VIA_VIRTUAL (base_binfo))
  		{
  		   /* We store the vtable offset at which the virtual
         		      base offset can be found.  */
! 		  offset = BINFO_VPTR_FIELD (base_binfo);
  		  offset = convert (sizetype, offset);
  		  flags |= 1;
  		}
*************** get_pseudo_ti_desc (tree type)
*** 1187,1198 ****
  	return class_desc_type_node;
        else
  	{
! 	  tree base_binfo =
! 	    TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), 0);
! 	  int num_bases = BINFO_N_BASETYPES (TYPE_BINFO (type));
  	  
  	  if (num_bases == 1
! 	      && TREE_PUBLIC (base_binfo)
  	      && !TREE_VIA_VIRTUAL (base_binfo)
  	      && integer_zerop (BINFO_OFFSET (base_binfo)))
  	    /* single non-virtual public.  */
--- 1187,1200 ----
  	return class_desc_type_node;
        else
  	{
! 	  tree binfo = TYPE_BINFO (type);
! 	  tree base_binfos = BINFO_BASETYPES (binfo);
! 	  tree base_accesses = BINFO_BASEACCESSES (binfo);
! 	  tree base_binfo = TREE_VEC_ELT (base_binfos, 0);
! 	  int num_bases = TREE_VEC_LENGTH (base_binfos);
  	  
  	  if (num_bases == 1
! 	      && TREE_VEC_ELT (base_accesses, 0) == access_public_node
  	      && !TREE_VIA_VIRTUAL (base_binfo)
  	      && integer_zerop (BINFO_OFFSET (base_binfo)))
  	    /* single non-virtual public.  */
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.297
diff -c -3 -p -r1.297 semantics.c
*** cp/semantics.c	30 Jan 2003 07:23:59 -0000	1.297
--- cp/semantics.c	17 Feb 2003 19:46:51 -0000
***************
*** 3,9 ****
     building RTL.  These routines are used both during actual parsing
     and during the instantiation of template functions. 
  
!    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
     Written by Mark Mitchell (mmitchell at usa dot net) based on code found
     formerly in parse.y and pt.c.  
  
--- 3,10 ----
     building RTL.  These routines are used both during actual parsing
     and during the instantiation of template functions. 
  
!    Copyright (C) 1998, 1999, 2000, 2001, 2002,
!    2003 Free Software Foundation, Inc.
     Written by Mark Mitchell (mmitchell at usa dot net) based on code found
     formerly in parse.y and pt.c.  
  
*************** finish_template_type (name, args, enteri
*** 2038,2064 ****
     access_{default,public,protected_private}[_virtual]_node.*/
  
  tree 
! finish_base_specifier (access_specifier, base_class)
!      tree access_specifier;
!      tree base_class;
  {
    tree result;
  
!   if (base_class == error_mark_node)
      {
        error ("invalid base-class specification");
        result = NULL_TREE;
      }
!   else if (! is_aggr_type (base_class, 1))
      result = NULL_TREE;
    else
      {
!       if (cp_type_quals (base_class) != 0)
          {
!           error ("base class `%T' has cv qualifiers", base_class);
!           base_class = TYPE_MAIN_VARIANT (base_class);
          }
!       result = build_tree_list (access_specifier, base_class);
      }
  
    return result;
--- 2039,2064 ----
     access_{default,public,protected_private}[_virtual]_node.*/
  
  tree 
! finish_base_specifier (tree base, tree access, bool virtual_p)
  {
    tree result;
  
!   if (base == error_mark_node)
      {
        error ("invalid base-class specification");
        result = NULL_TREE;
      }
!   else if (! is_aggr_type (base, 1))
      result = NULL_TREE;
    else
      {
!       if (cp_type_quals (base) != 0)
          {
!           error ("base class `%T' has cv qualifiers", base);
!           base = TYPE_MAIN_VARIANT (base);
          }
!       result = build_tree_list (access, base);
!       TREE_VIA_VIRTUAL (result) = virtual_p;
      }
  
    return result;
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.317
diff -c -3 -p -r1.317 tree.c
*** cp/tree.c	31 Jan 2003 14:46:53 -0000	1.317
--- cp/tree.c	17 Feb 2003 19:46:58 -0000
***************
*** 1,6 ****
  /* Language-dependent node constructors for parse phase of GNU compiler.
     Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann at cygnus dot com)
  
  This file is part of GCC.
--- 1,6 ----
  /* Language-dependent node constructors for parse phase of GNU compiler.
     Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann at cygnus dot com)
  
  This file is part of GCC.
*************** canonical_type_variant (t)
*** 714,750 ****
    return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
  }
  
! /* Makes new binfos for the indirect bases under BINFO, and updates
!    BINFO_OFFSET for them and their bases.  */
  
! void
! unshare_base_binfos (binfo)
!      tree binfo;
  {
    tree binfos = BINFO_BASETYPES (binfo);
!   tree new_binfo;
!   int j;
  
    if (binfos == NULL_TREE)
!     return;
  
!   /* Now unshare the structure beneath BINFO.  */
!   for (j = TREE_VEC_LENGTH (binfos)-1;
!        j >= 0; j--)
!     {
!       tree base_binfo = TREE_VEC_ELT (binfos, j);
!       new_binfo = TREE_VEC_ELT (binfos, j)
! 	= make_binfo (BINFO_OFFSET (base_binfo),
! 		      base_binfo,
! 		      BINFO_VTABLE (base_binfo),
! 		      BINFO_VIRTUALS (base_binfo));
!       TREE_VIA_PUBLIC (new_binfo) = TREE_VIA_PUBLIC (base_binfo);
!       TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
!       TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
!       BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
!       BINFO_PRIMARY_BASE_OF (new_binfo) = NULL_TREE;
!       unshare_base_binfos (new_binfo);
      }
  }
  
  
--- 714,794 ----
    return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
  }
  
! /* Makes new binfos for the indirect bases under BINFO. T is the most
!    derived TYPE. PREV is the previous binfo, whose TREE_CHAIN we make
!    point to this binfo. We return the last BINFO created.
  
!    The CLASSTYPE_VBASECLASSES list of T is constructed in reverse
!    order (pre-order, depth-first, right-to-left). You must nreverse it.
! 
!    The BINFO_INHERITANCE of a virtual base class points to the binfo
!    og the most derived type.
! 
!    The binfo's TREE_CHAIN is set to inheritance graph order, but bases
!    for non-class types are not included (i.e. those which are
!    dependent bases in non-instantiated templates).  */
! 
! tree
! copy_base_binfos (binfo, t, prev)
!      tree binfo, t, prev;
  {
    tree binfos = BINFO_BASETYPES (binfo);
!   int n, ix;
  
+   if (prev)
+     TREE_CHAIN (prev) = binfo;
+   prev = binfo;
+   
    if (binfos == NULL_TREE)
!     return prev;
! 
!   n = TREE_VEC_LENGTH (binfos);
!   
!   /* Now copy the structure beneath BINFO.  */
!   for (ix = 0; ix != n; ix++)
!     {
!       tree base_binfo = TREE_VEC_ELT (binfos, ix);
!       tree new_binfo = NULL_TREE;
  
!       if (!CLASS_TYPE_P (BINFO_TYPE (base_binfo)))
! 	{
! 	  my_friendly_assert (binfo == TYPE_BINFO (t), 20030204);
! 	  
! 	  new_binfo = base_binfo;
! 	  TREE_CHAIN (prev) = new_binfo;
! 	  prev = new_binfo;
! 	  BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
! 	  BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
! 	}
!       else if (TREE_VIA_VIRTUAL (base_binfo))
! 	{
! 	  new_binfo = purpose_member (BINFO_TYPE (base_binfo),
! 				      CLASSTYPE_VBASECLASSES (t));
! 	  if (new_binfo)
! 	    new_binfo = TREE_VALUE (new_binfo);
! 	}
!       
!       if (!new_binfo)
! 	{
! 	  new_binfo = make_binfo (BINFO_OFFSET (base_binfo),
! 				  base_binfo, NULL_TREE,
! 				  BINFO_VIRTUALS (base_binfo));
! 	  prev = copy_base_binfos (new_binfo, t, prev);
! 	  if (TREE_VIA_VIRTUAL (base_binfo))
! 	    {
! 	      CLASSTYPE_VBASECLASSES (t)
! 		= tree_cons (BINFO_TYPE (new_binfo), new_binfo,
! 			     CLASSTYPE_VBASECLASSES (t));
! 	      TREE_VIA_VIRTUAL (new_binfo) = 1;
! 	      BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
! 	    }
! 	  else
! 	    BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
! 	}
!       TREE_VEC_ELT (binfos, ix) = new_binfo;
      }
+ 
+   return prev;
  }
  
  
*************** make_binfo (offset, binfo, vtable, virtu
*** 897,907 ****
    tree type;
  
    if (TREE_CODE (binfo) == TREE_VEC)
!     type = BINFO_TYPE (binfo);
    else
      {
        type = binfo;
!       binfo = CLASS_TYPE_P (type) ? TYPE_BINFO (binfo) : NULL_TREE;
      }
  
    TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
--- 941,955 ----
    tree type;
  
    if (TREE_CODE (binfo) == TREE_VEC)
!     {
!       type = BINFO_TYPE (binfo);
!       BINFO_DEPENDENT_BASE_P (new_binfo) = BINFO_DEPENDENT_BASE_P (binfo);
!     }
    else
      {
        type = binfo;
!       binfo = NULL_TREE;
!       BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
      }
  
    TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
*************** make_binfo (offset, binfo, vtable, virtu
*** 909,939 ****
    BINFO_VTABLE (new_binfo) = vtable;
    BINFO_VIRTUALS (new_binfo) = virtuals;
  
!   if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
!     BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));      
!   return new_binfo;
! }
! 
! /* Return a TREE_LIST whose TREE_VALUE nodes along the
!    BINFO_INHERITANCE_CHAIN for BINFO, but in the opposite order.  In
!    other words, while the BINFO_INHERITANCE_CHAIN goes from base
!    classes to derived classes, the reversed path goes from derived
!    classes to base classes.  */
! 
! tree
! reverse_path (binfo)
!      tree binfo;
! {
!   tree reversed_path;
! 
!   reversed_path = NULL_TREE;
!   while (binfo) 
      {
!       reversed_path = tree_cons (NULL_TREE, binfo, reversed_path);
!       binfo = BINFO_INHERITANCE_CHAIN (binfo);
      }
! 
!   return reversed_path;
  }
  
  void
--- 957,970 ----
    BINFO_VTABLE (new_binfo) = vtable;
    BINFO_VIRTUALS (new_binfo) = virtuals;
  
!   if (binfo && !BINFO_DEPENDENT_BASE_P (binfo)
!       && BINFO_BASETYPES (binfo) != NULL_TREE)
      {
!       BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));
!       /* We do not need to copy the accesses, as they are read only.  */
!       BINFO_BASEACCESSES (new_binfo) = BINFO_BASEACCESSES (binfo);
      }
!   return new_binfo;
  }
  
  void
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.449
diff -c -3 -p -r1.449 typeck.c
*** cp/typeck.c	15 Feb 2003 18:03:22 -0000	1.449
--- cp/typeck.c	17 Feb 2003 19:47:22 -0000
*************** get_delta_difference (from, to, force)
*** 5720,5728 ****
        if (virt_binfo)
          {
            /* This is a reinterpret cast, we choose to do nothing.  */
!           warning ("pointer to member cast via virtual base `%T' of `%T'",
! 	              BINFO_TYPE (virt_binfo),
! 	              BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
            return delta;
          }
        delta = BINFO_OFFSET (binfo);
--- 5720,5727 ----
        if (virt_binfo)
          {
            /* This is a reinterpret cast, we choose to do nothing.  */
!           warning ("pointer to member cast via virtual base `%T'",
! 		   BINFO_TYPE (virt_binfo));
            return delta;
          }
        delta = BINFO_OFFSET (binfo);
*************** get_delta_difference (from, to, force)
*** 5739,5751 ****
      {
        /* This is a reinterpret cast, we choose to do nothing.  */
        if (force)
!         warning ("pointer to member cast via virtual base `%T' of `%T'",
!                     BINFO_TYPE (virt_binfo),
!                     BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
        else
! 	error ("pointer to member conversion via virtual base `%T' of `%T'",
! 		  BINFO_TYPE (virt_binfo),
!                   BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
        return delta;
      }
    delta = BINFO_OFFSET (binfo);
--- 5738,5748 ----
      {
        /* This is a reinterpret cast, we choose to do nothing.  */
        if (force)
!         warning ("pointer to member cast via virtual base `%T'",
! 		 BINFO_TYPE (virt_binfo));
        else
! 	error ("pointer to member conversion via virtual base `%T'",
! 	       BINFO_TYPE (virt_binfo));
        return delta;
      }
    delta = BINFO_OFFSET (binfo);
Index: java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.152
diff -c -3 -p -r1.152 class.c
*** java/class.c	31 Jan 2003 14:46:54 -0000	1.152
--- java/class.c	17 Feb 2003 19:47:31 -0000
*************** set_super_info (int access_flags, tree t
*** 363,369 ****
        tree super_binfo = make_tree_vec (BINFO_ELTS);
        BINFO_TYPE (super_binfo) = super_class;
        BINFO_OFFSET (super_binfo) = integer_zero_node;
-       TREE_VIA_PUBLIC (super_binfo) = 1;
        TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (this_class)), 0)
  	= super_binfo;
        CLASS_HAS_SUPER (this_class) = 1;
--- 363,368 ----
*************** add_interface_do (tree basetype_vec, tre
*** 497,503 ****
    BINFO_OFFSET (interface_binfo) = integer_zero_node;
    BINFO_VPTR_FIELD (interface_binfo) = integer_zero_node;
    TREE_VIA_VIRTUAL (interface_binfo) = 1;
-   TREE_VIA_PUBLIC (interface_binfo) = 1;
    TREE_VEC_ELT (basetype_vec, i) = interface_binfo;
  }
  
--- 496,501 ----
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.252
diff -c -3 -p -r1.252 search.c
*** cp/search.c	15 Feb 2003 18:03:22 -0000	1.252
--- cp/search.c	18 Feb 2003 19:08:23 -0000
*************** struct vbase_info 
*** 82,99 ****
  };
  
  static tree lookup_field_1 (tree, tree);
- static int is_subobject_of_p (tree, tree, tree);
- static int is_subobject_of_p_1 (tree, tree, tree);
  static tree dfs_check_overlap (tree, void *);
! static tree dfs_no_overlap_yet (tree, void *);
! static base_kind lookup_base_r (tree, tree, base_access,
! 				bool, bool, bool, tree *);
  static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
! static tree marked_pushdecls_p (tree, void *);
! static tree unmarked_pushdecls_p (tree, void *);
! static tree dfs_debug_unmarkedp (tree, void *);
  static tree dfs_debug_mark (tree, void *);
- static tree dfs_get_vbase_types (tree, void *);
  static tree dfs_push_type_decls (tree, void *);
  static tree dfs_push_decls (tree, void *);
  static tree dfs_unuse_fields (tree, void *);
--- 82,96 ----
  };
  
  static tree lookup_field_1 (tree, tree);
  static tree dfs_check_overlap (tree, void *);
! static tree dfs_no_overlap_yet (tree, int, void *);
! static base_kind lookup_base_r
! 	(tree, tree, base_access, int, int, int, tree *);
  static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
! static tree marked_pushdecls_p (tree, int, void *);
! static tree unmarked_pushdecls_p (tree, int, void *);
! static tree dfs_debug_unmarkedp (tree, int, void *);
  static tree dfs_debug_mark (tree, void *);
  static tree dfs_push_type_decls (tree, void *);
  static tree dfs_push_decls (tree, void *);
  static tree dfs_unuse_fields (tree, void *);
*************** static int look_for_overrides_r (tree, t
*** 102,130 ****
  static struct search_level *push_search_level (struct stack_level *,
  					       struct obstack *);
  static struct search_level *pop_search_level (struct stack_level *);
! static tree bfs_walk (tree, tree (*) (tree, void *),
! 		      tree (*) (tree, void *), void *);
! static tree lookup_field_queue_p (tree, void *);
  static int shared_member_p (tree);
  static tree lookup_field_r (tree, void *);
! static tree canonical_binfo (tree);
! static tree shared_marked_p (tree, void *);
! static tree shared_unmarked_p (tree, void *);
! static int  dependent_base_p (tree);
! static tree dfs_accessible_queue_p (tree, void *);
  static tree dfs_accessible_p (tree, void *);
  static tree dfs_access_in_type (tree, void *);
  static access_kind access_in_type (tree, tree);
- static tree dfs_canonical_queue (tree, void *);
- static tree dfs_assert_unmarked_p (tree, void *);
- static void assert_canonical_unmarked (tree);
  static int protected_accessible_p (tree, tree, tree);
  static int friend_accessible_p (tree, tree, tree);
  static void setup_class_bindings (tree, int);
  static int template_self_reference_p (tree, tree);
- static tree dfs_find_vbase_instance (tree, void *);
  static tree dfs_get_pure_virtuals (tree, void *);
- static tree dfs_build_inheritance_graph_order (tree, void *);
  
  /* Allocate a level of searching.  */
  
--- 99,120 ----
  static struct search_level *push_search_level (struct stack_level *,
  					       struct obstack *);
  static struct search_level *pop_search_level (struct stack_level *);
! static tree bfs_walk (tree,
! 		      tree (*) (tree, void *),
! 		      tree (*) (tree, int, void *),
! 		      void *);
! static tree lookup_field_queue_p (tree, int, void *);
  static int shared_member_p (tree);
  static tree lookup_field_r (tree, void *);
! static tree dfs_accessible_queue_p (tree, int, void *);
  static tree dfs_accessible_p (tree, void *);
  static tree dfs_access_in_type (tree, void *);
  static access_kind access_in_type (tree, tree);
  static int protected_accessible_p (tree, tree, tree);
  static int friend_accessible_p (tree, tree, tree);
  static void setup_class_bindings (tree, int);
  static int template_self_reference_p (tree, tree);
  static tree dfs_get_pure_virtuals (tree, void *);
  
  /* Allocate a level of searching.  */
  
*************** lookup_base_r (tree binfo, tree base, ba
*** 182,188 ****
  	       tree *binfo_ptr)
  {
    int i;
!   tree bases;
    base_kind found = bk_not_base;
    
    if (access == ba_check
--- 172,178 ----
  	       tree *binfo_ptr)
  {
    int i;
!   tree bases, accesses;
    base_kind found = bk_not_base;
    
    if (access == ba_check
*************** lookup_base_r (tree binfo, tree base, ba
*** 206,213 ****
        
        if (!*binfo_ptr)
  	*binfo_ptr = binfo;
!       else if (!is_virtual || !tree_int_cst_equal (BINFO_OFFSET (binfo),
! 						   BINFO_OFFSET (*binfo_ptr)))
  	{
  	  if (access != ba_any)
  	    *binfo_ptr = NULL;
--- 196,202 ----
        
        if (!*binfo_ptr)
  	*binfo_ptr = binfo;
!       else if (binfo != *binfo_ptr)
  	{
  	  if (access != ba_any)
  	    *binfo_ptr = NULL;
*************** lookup_base_r (tree binfo, tree base, ba
*** 221,243 ****
      }
    
    bases = BINFO_BASETYPES (binfo);
    if (!bases)
      return bk_not_base;
    
    for (i = TREE_VEC_LENGTH (bases); i--;)
      {
        tree base_binfo = TREE_VEC_ELT (bases, i);
        int this_non_public = is_non_public;
        int this_virtual = is_virtual;
        base_kind bk;
  
        if (access <= ba_ignore)
  	; /* no change */
!       else if (TREE_VIA_PUBLIC (base_binfo))
  	; /* no change */
        else if (access == ba_not_special)
  	this_non_public = 1;
!       else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope)
  	; /* no change */
        else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
  	; /* no change */
--- 210,235 ----
      }
    
    bases = BINFO_BASETYPES (binfo);
+   accesses = BINFO_BASEACCESSES (binfo);
    if (!bases)
      return bk_not_base;
    
    for (i = TREE_VEC_LENGTH (bases); i--;)
      {
        tree base_binfo = TREE_VEC_ELT (bases, i);
+       tree base_access = TREE_VEC_ELT (accesses, i);
+       
        int this_non_public = is_non_public;
        int this_virtual = is_virtual;
        base_kind bk;
  
        if (access <= ba_ignore)
  	; /* no change */
!       else if (base_access == access_public_node)
  	; /* no change */
        else if (access == ba_not_special)
  	this_non_public = 1;
!       else if (base_access == access_protected_node && within_current_scope)
  	; /* no change */
        else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
  	; /* no change */
*************** lookup_base_r (tree binfo, tree base, ba
*** 289,297 ****
  }
  
  /* Lookup BASE in the hierarchy dominated by T.  Do access checking as
!    ACCESS specifies.  Return the binfo we discover (which might not be
!    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
--- 281,289 ----
  }
  
  /* Lookup BASE in the hierarchy dominated by T.  Do access checking as
!    ACCESS specifies.  Return the binfo we discover.  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
*************** static int
*** 364,370 ****
  dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
  			   tree *offset_ptr)
  {
!   tree binfos;
    int i, n_baselinks;
    int worst = -2;
    
--- 357,363 ----
  dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
  			   tree *offset_ptr)
  {
!   tree binfos, accesses;
    int i, n_baselinks;
    int worst = -2;
    
*************** dynamic_cast_base_recurse (tree subtype,
*** 380,392 ****
      }
    
    binfos = BINFO_BASETYPES (binfo);
    n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
    for (i = 0; i < n_baselinks; i++)
      {
        tree base_binfo = TREE_VEC_ELT (binfos, i);
        int rval;
        
!       if (!TREE_VIA_PUBLIC (base_binfo))
          continue;
        rval = dynamic_cast_base_recurse
               (subtype, base_binfo,
--- 373,387 ----
      }
    
    binfos = BINFO_BASETYPES (binfo);
+   accesses = BINFO_BASEACCESSES (binfo);
    n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
    for (i = 0; i < n_baselinks; i++)
      {
        tree base_binfo = TREE_VEC_ELT (binfos, i);
+       tree base_access = TREE_VEC_ELT (accesses, i);
        int rval;
        
!       if (base_access != access_public_node)
          continue;
        rval = dynamic_cast_base_recurse
               (subtype, base_binfo,
*************** context_for_name_lookup (tree decl)
*** 602,675 ****
    return context;
  }
  
- /* Return a canonical BINFO if BINFO is a virtual base, or just BINFO
-    otherwise.  */
- 
- static tree
- canonical_binfo (tree binfo)
- {
-   return (TREE_VIA_VIRTUAL (binfo)
- 	  ? TYPE_BINFO (BINFO_TYPE (binfo)) : binfo);
- }
- 
- /* A queue function that simply ensures that we walk into the
-    canonical versions of virtual bases.  */
- 
- static tree
- dfs_canonical_queue (tree binfo, void *data ATTRIBUTE_UNUSED)
- {
-   return canonical_binfo (binfo);
- }
- 
- /* Called via dfs_walk from assert_canonical_unmarked.  */
- 
- static tree
- dfs_assert_unmarked_p (tree binfo, void *data ATTRIBUTE_UNUSED)
- {
-   my_friendly_assert (!BINFO_MARKED (binfo), 0);
-   return NULL_TREE;
- }
- 
- /* Asserts that all the nodes below BINFO (using the canonical
-    versions of virtual bases) are unmarked.  */
- 
- static void
- assert_canonical_unmarked (tree binfo)
- {
-   dfs_walk (binfo, dfs_assert_unmarked_p, dfs_canonical_queue, 0);
- }
- 
- /* If BINFO is marked, return a canonical version of BINFO.
-    Otherwise, return NULL_TREE.  */
- 
- static tree
- shared_marked_p (tree binfo, void *data)
- {
-   binfo = canonical_binfo (binfo);
-   return markedp (binfo, data);
- }
- 
- /* If BINFO is not marked, return a canonical version of BINFO.
-    Otherwise, return NULL_TREE.  */
- 
- static tree
- shared_unmarked_p (tree binfo, void *data)
- {
-   binfo = canonical_binfo (binfo);
-   return unmarkedp (binfo, data);
- }
- 
  /* The accessibility routines use BINFO_ACCESS for scratch space
     during the computation of the accssibility of some declaration.  */
  
  #define BINFO_ACCESS(NODE) \
!   ((access_kind) ((TREE_LANG_FLAG_1 (NODE) << 1) | TREE_LANG_FLAG_6 (NODE)))
  
  /* Set the access associated with NODE to ACCESS.  */
  
  #define SET_BINFO_ACCESS(NODE, ACCESS)			\
!   ((TREE_LANG_FLAG_1 (NODE) = ((ACCESS) & 2) != 0),	\
!    (TREE_LANG_FLAG_6 (NODE) = ((ACCESS) & 1) != 0))
  
  /* Called from access_in_type via dfs_walk.  Calculate the access to
     DATA (which is really a DECL) in BINFO.  */
--- 597,613 ----
    return context;
  }
  
  /* The accessibility routines use BINFO_ACCESS for scratch space
     during the computation of the accssibility of some declaration.  */
  
  #define BINFO_ACCESS(NODE) \
!   ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
  
  /* Set the access associated with NODE to ACCESS.  */
  
  #define SET_BINFO_ACCESS(NODE, ACCESS)			\
!   ((TREE_PUBLIC (NODE) = ((ACCESS) & 2) != 0),	\
!    (TREE_PRIVATE (NODE) = ((ACCESS) & 1) != 0))
  
  /* Called from access_in_type via dfs_walk.  Calculate the access to
     DATA (which is really a DECL) in BINFO.  */
*************** dfs_access_in_type (tree binfo, void *da
*** 701,751 ****
        if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
  	{
  	  tree decl_access = purpose_member (type, DECL_ACCESS (decl));
  	  if (decl_access)
! 	    access = ((access_kind) 
! 		      TREE_INT_CST_LOW (TREE_VALUE (decl_access)));
  	}
  
        if (!access)
  	{
  	  int i;
  	  int n_baselinks;
! 	  tree binfos;
  	  
  	  /* Otherwise, scan our baseclasses, and pick the most favorable
  	     access.  */
  	  binfos = BINFO_BASETYPES (binfo);
  	  n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
  	  for (i = 0; i < n_baselinks; ++i)
  	    {
  	      tree base_binfo = TREE_VEC_ELT (binfos, i);
! 	      access_kind base_access 
! 		= BINFO_ACCESS (canonical_binfo (base_binfo));
  
! 	      if (base_access == ak_none || base_access == ak_private)
  		/* If it was not accessible in the base, or only
  		   accessible as a private member, we can't access it
  		   all.  */
! 		base_access = ak_none;
! 	      else if (TREE_VIA_PROTECTED (base_binfo))
! 		/* Public and protected members in the base are
  		   protected here.  */
! 		base_access = ak_protected;
! 	      else if (!TREE_VIA_PUBLIC (base_binfo))
! 		/* Public and protected members in the base are
  		   private here.  */
! 		base_access = ak_private;
  
  	      /* See if the new access, via this base, gives more
  		 access than our previous best access.  */
! 	      if (base_access != ak_none
! 		  && (base_access == ak_public
! 		      || (base_access == ak_protected
! 			  && access != ak_public)
! 		      || (base_access == ak_private 
! 			  && access == ak_none)))
  		{
! 		  access = base_access;
  
  		  /* If the new access is public, we can't do better.  */
  		  if (access == ak_public)
--- 639,697 ----
        if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
  	{
  	  tree decl_access = purpose_member (type, DECL_ACCESS (decl));
+ 	  
  	  if (decl_access)
! 	    {
! 	      decl_access = TREE_VALUE (decl_access);
! 	      
! 	      if (decl_access == access_public_node)
! 		access = ak_public;
! 	      else if (decl_access == access_protected_node)
! 		access = ak_protected;
! 	      else if (decl_access == access_private_node)
! 		access = ak_private;
! 	      else
! 		my_friendly_assert (false, 20030217);
! 	    }
  	}
  
        if (!access)
  	{
  	  int i;
  	  int n_baselinks;
! 	  tree binfos, accesses;
  	  
  	  /* Otherwise, scan our baseclasses, and pick the most favorable
  	     access.  */
  	  binfos = BINFO_BASETYPES (binfo);
+ 	  accesses = BINFO_BASEACCESSES (binfo);
  	  n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
  	  for (i = 0; i < n_baselinks; ++i)
  	    {
  	      tree base_binfo = TREE_VEC_ELT (binfos, i);
! 	      tree base_access = TREE_VEC_ELT (accesses, i);
! 	      access_kind base_access_now = BINFO_ACCESS (base_binfo);
  
! 	      if (base_access_now == ak_none || base_access_now == ak_private)
  		/* If it was not accessible in the base, or only
  		   accessible as a private member, we can't access it
  		   all.  */
! 		base_access_now = ak_none;
! 	      else if (base_access == access_protected_node)
! 		/* Public and protected members in the base become
  		   protected here.  */
! 		base_access_now = ak_protected;
! 	      else if (base_access == access_private_node)
! 		/* Public and protected members in the base become
  		   private here.  */
! 		base_access_now = ak_private;
  
  	      /* See if the new access, via this base, gives more
  		 access than our previous best access.  */
! 	      if (base_access_now != ak_none
! 		  && (access == ak_none || base_access_now < access))
  		{
! 		  access = base_access_now;
  
  		  /* If the new access is public, we can't do better.  */
  		  if (access == ak_public)
*************** dfs_access_in_type (tree binfo, void *da
*** 760,766 ****
  
    /* Mark TYPE as visited so that if we reach it again we do not
       duplicate our efforts here.  */
!   SET_BINFO_MARKED (binfo);
  
    return NULL_TREE;
  }
--- 706,712 ----
  
    /* Mark TYPE as visited so that if we reach it again we do not
       duplicate our efforts here.  */
!   BINFO_MARKED (binfo) = 1;
  
    return NULL_TREE;
  }
*************** access_in_type (tree type, tree decl)
*** 783,791 ****
      The algorithm we use is to make a post-order depth-first traversal
      of the base-class hierarchy.  As we come up the tree, we annotate
      each node with the most lenient access.  */
!   dfs_walk_real (binfo, 0, dfs_access_in_type, shared_unmarked_p, decl);
!   dfs_walk (binfo, dfs_unmark, shared_marked_p,  0);
!   assert_canonical_unmarked (binfo);
  
    return BINFO_ACCESS (binfo);
  }
--- 729,736 ----
      The algorithm we use is to make a post-order depth-first traversal
      of the base-class hierarchy.  As we come up the tree, we annotate
      each node with the most lenient access.  */
!   dfs_walk_real (binfo, 0, dfs_access_in_type, unmarkedp, decl);
!   dfs_walk (binfo, dfs_unmark, markedp,  0);
  
    return BINFO_ACCESS (binfo);
  }
*************** access_in_type (tree type, tree decl)
*** 793,811 ****
  /* Called from dfs_accessible_p via dfs_walk.  */
  
  static tree
! dfs_accessible_queue_p (tree binfo, void *data ATTRIBUTE_UNUSED)
  {
    if (BINFO_MARKED (binfo))
      return NULL_TREE;
  
    /* If this class is inherited via private or protected inheritance,
!      then we can't see it, unless we are a friend of the subclass.  */
!   if (!TREE_VIA_PUBLIC (binfo)
!       && !is_friend (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
! 		     current_scope ()))
      return NULL_TREE;
  
!   return canonical_binfo (binfo);
  }
  
  /* Called from dfs_accessible_p via dfs_walk.  */
--- 738,757 ----
  /* Called from dfs_accessible_p via dfs_walk.  */
  
  static tree
! dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
  {
+   tree binfo = BINFO_BASETYPE (derived, ix);
+   
    if (BINFO_MARKED (binfo))
      return NULL_TREE;
  
    /* If this class is inherited via private or protected inheritance,
!      then we can't see it, unless we are a friend of the derived class.  */
!   if (BINFO_BASEACCESS (derived, ix) != access_public_node
!       && !is_friend (BINFO_TYPE (derived), current_scope ()))
      return NULL_TREE;
  
!   return binfo;
  }
  
  /* Called from dfs_accessible_p via dfs_walk.  */
*************** dfs_accessible_p (tree binfo, void *data
*** 816,822 ****
    int protected_ok = data != 0;
    access_kind access;
  
!   SET_BINFO_MARKED (binfo);
    access = BINFO_ACCESS (binfo);
    if (access == ak_public || (access == ak_protected && protected_ok))
      return binfo;
--- 762,768 ----
    int protected_ok = data != 0;
    access_kind access;
  
!   BINFO_MARKED (binfo) = 1;
    access = BINFO_ACCESS (binfo);
    if (access == ak_public || (access == ak_protected && protected_ok))
      return binfo;
*************** accessible_p (tree type, tree decl)
*** 1014,1088 ****
    /* Clear any mark bits.  Note that we have to walk the whole tree
       here, since we have aborted the previous walk from some point
       deep in the tree.  */
!   dfs_walk (binfo, dfs_unmark, dfs_canonical_queue,  0);
!   assert_canonical_unmarked (binfo);
  
    return t != NULL_TREE;
  }
  
- /* Recursive helper funciton for is_subobject_of_p; see that routine
-    for documentation of the parameters.  */
- 
- static int
- is_subobject_of_p_1 (tree parent, tree binfo, tree most_derived)
- {
-   tree binfos;
-   int i, n_baselinks;
- 
-   if (parent == binfo)
-     return 1;
- 
-   binfos = BINFO_BASETYPES (binfo);
-   n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- 
-   /* Iterate through the base types.  */
-   for (i = 0; i < n_baselinks; i++)
-     {
-       tree base_binfo = TREE_VEC_ELT (binfos, i);
-       tree base_type;
- 
-       base_type = TREE_TYPE (base_binfo);
-       if (!CLASS_TYPE_P (base_type))
- 	/* If we see a TEMPLATE_TYPE_PARM, or some such, as a base
- 	   class there's no way to descend into it.  */
- 	continue;
- 
-       /* Avoid walking into the same virtual base more than once.  */
-       if (TREE_VIA_VIRTUAL (base_binfo))
- 	{
- 	  if (CLASSTYPE_MARKED4 (base_type))
- 	    continue;
- 	  SET_CLASSTYPE_MARKED4 (base_type);
- 	  base_binfo = binfo_for_vbase (base_type, most_derived);
- 	}
- 
-       if (is_subobject_of_p_1 (parent, base_binfo, most_derived))
- 	return 1;
-     }
-   return 0;
- }
- 
- /* Routine to see if the sub-object denoted by the binfo PARENT can be
-    found as a base class and sub-object of the object denoted by
-    BINFO.  MOST_DERIVED is the most derived type of the hierarchy being
-    searched.  */
- 
- static int
- is_subobject_of_p (tree parent, tree binfo, tree most_derived)
- {
-   int result;
-   tree vbase;
- 
-   result = is_subobject_of_p_1 (parent, binfo, most_derived);
-   /* Clear the mark bits on virtual bases.  */
-   for (vbase = CLASSTYPE_VBASECLASSES (most_derived);
-        vbase;
-        vbase = TREE_CHAIN (vbase))
-     CLEAR_CLASSTYPE_MARKED4 (TREE_TYPE (TREE_VALUE (vbase)));
- 
-   return result;
- }
- 
  struct lookup_field_info {
    /* The type in which we're looking.  */
    tree type;
--- 960,970 ----
    /* Clear any mark bits.  Note that we have to walk the whole tree
       here, since we have aborted the previous walk from some point
       deep in the tree.  */
!   dfs_walk (binfo, dfs_unmark, 0,  0);
  
    return t != NULL_TREE;
  }
  
  struct lookup_field_info {
    /* The type in which we're looking.  */
    tree type;
*************** struct lookup_field_info {
*** 1097,1104 ****
    tree ambiguous;
    /* If nonzero, we are looking for types, not data members.  */
    int want_type;
-   /* If nonzero, RVAL was found by looking through a dependent base.  */
-   int from_dep_base_p;
    /* If something went wrong, a message indicating what.  */
    const char *errstr;
  };
--- 979,984 ----
*************** struct lookup_field_info {
*** 1109,1116 ****
     lookup_field via breadth_first_search.  */
  
  static tree
! lookup_field_queue_p (tree binfo, void *data)
  {
    struct lookup_field_info *lfi = (struct lookup_field_info *) data;
  
    /* Don't look for constructors or destructors in base classes.  */
--- 989,997 ----
     lookup_field via breadth_first_search.  */
  
  static tree
! lookup_field_queue_p (tree derived, int ix, void *data)
  {
+   tree binfo = BINFO_BASETYPE (derived, ix);
    struct lookup_field_info *lfi = (struct lookup_field_info *) data;
  
    /* Don't look for constructors or destructors in base classes.  */
*************** lookup_field_queue_p (tree binfo, void *
*** 1119,1129 ****
  
    /* If this base class is hidden by the best-known value so far, we
       don't need to look.  */
!   binfo = CANONICAL_BINFO (binfo, lfi->type);
!   if (!lfi->from_dep_base_p && lfi->rval_binfo
!       && is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
      return NULL_TREE;
  
    return binfo;
  }
  
--- 1000,1012 ----
  
    /* If this base class is hidden by the best-known value so far, we
       don't need to look.  */
!   if (lfi->rval_binfo && original_binfo (binfo, lfi->rval_binfo))
      return NULL_TREE;
  
+   /* If this is a dependent base, don't look in it.  */
+   if (BINFO_DEPENDENT_BASE_P (binfo))
+     return NULL_TREE;
+   
    return binfo;
  }
  
*************** lookup_field_r (tree binfo, void *data)
*** 1186,1192 ****
    struct lookup_field_info *lfi = (struct lookup_field_info *) data;
    tree type = BINFO_TYPE (binfo);
    tree nval = NULL_TREE;
-   int from_dep_base_p;
  
    /* First, look for a function.  There can't be a function and a data
       member with the same name, and if there's a function and a type
--- 1069,1074 ----
*************** lookup_field_r (tree binfo, void *data)
*** 1240,1279 ****
        && template_self_reference_p (type, nval))
      return NULL_TREE;
  
-   from_dep_base_p = dependent_base_p (binfo);
-   if (lfi->from_dep_base_p && !from_dep_base_p)
-     {
-       /* If the new declaration is not found via a dependent base, and
- 	 the old one was, then we must prefer the new one.  We weren't
- 	 really supposed to be able to find the old one, so we don't
- 	 want to be affected by a specialization.  Consider:
- 
- 	   struct B { typedef int I; };
- 	   template <typename T> struct D1 : virtual public B {}; 
- 	   template <typename T> struct D :
- 	   public D1, virtual pubic B { I i; };
- 
- 	 The `I' in `D<T>' is unambigousuly `B::I', regardless of how
- 	 D1 is specialized.  */
-       lfi->from_dep_base_p = 0;
-       lfi->rval = NULL_TREE;
-       lfi->rval_binfo = NULL_TREE;
-       lfi->ambiguous = NULL_TREE;
-       lfi->errstr = 0;
-     }
-   else if (lfi->rval_binfo && !lfi->from_dep_base_p && from_dep_base_p)
-     /* Similarly, if the old declaration was not found via a dependent
-        base, and the new one is, ignore the new one.  */
-     return NULL_TREE;
- 
    /* If the lookup already found a match, and the new value doesn't
       hide the old one, we might have an ambiguity.  */
!   if (lfi->rval_binfo && !is_subobject_of_p (lfi->rval_binfo, binfo, lfi->type))
      {
        if (nval == lfi->rval && shared_member_p (nval))
  	/* The two things are really the same.  */
  	;
!       else if (is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
  	/* The previous value hides the new one.  */
  	;
        else
--- 1122,1135 ----
        && template_self_reference_p (type, nval))
      return NULL_TREE;
  
    /* If the lookup already found a match, and the new value doesn't
       hide the old one, we might have an ambiguity.  */
!   if (lfi->rval_binfo && !original_binfo (lfi->rval_binfo, binfo))
      {
        if (nval == lfi->rval && shared_member_p (nval))
  	/* The two things are really the same.  */
  	;
!       else if (original_binfo (binfo, lfi->rval_binfo))
  	/* The previous value hides the new one.  */
  	;
        else
*************** lookup_field_r (tree binfo, void *data)
*** 1297,1314 ****
      }
    else
      {
-       if (from_dep_base_p && TREE_CODE (nval) == TYPE_DECL
- 	  /* We need to return a member template class so we can
- 	     define partial specializations.  Is there a better
- 	     way?  */
- 	  && !DECL_CLASS_TEMPLATE_P (nval))
- 	/* The thing we're looking for isn't a type, so the implicit
- 	   typename extension doesn't apply, so we just pretend we
- 	   didn't find anything.  */
- 	return NULL_TREE;
- 
        lfi->rval = nval;
-       lfi->from_dep_base_p = from_dep_base_p;
        lfi->rval_binfo = binfo;
      }
  
--- 1153,1159 ----
*************** lookup_member (tree xbasetype, tree name
*** 1442,1452 ****
        rval = error_mark_node;
      }
  
-   /* If the thing we found was found via the implicit typename
-      extension, build the typename type.  */
-   if (rval && lfi.from_dep_base_p && !DECL_CLASS_TEMPLATE_P (rval))
-     abort ();
- 
    if (rval && is_overloaded_fn (rval)) 
      rval = build_baselink (rval_binfo, basetype_path, rval,
  			   (IDENTIFIER_TYPENAME_P (name)
--- 1287,1292 ----
*************** adjust_result_of_qualified_name_lookup (
*** 1632,1639 ****
     called.  */
  
  static tree
! bfs_walk (tree binfo, tree (*fn) (tree, void *),
! 	  tree (*qfn) (tree, void *), void *data)
  {
    size_t head;
    size_t tail;
--- 1472,1481 ----
     called.  */
  
  static tree
! bfs_walk (tree binfo,
! 	  tree (*fn) (tree, void *),
! 	  tree (*qfn) (tree, int, void *),
! 	  void *data)
  {
    size_t head;
    size_t tail;
*************** bfs_walk (tree binfo, tree (*fn) (tree, 
*** 1652,1661 ****
  
    for (head = 0; head < tail; ++head)
      {
-       int i;
-       int n_baselinks;
-       tree binfos;
- 
        /* Pull the next type out of the queue.  */
        binfo = VARRAY_TREE (bfs_bases, head);
  
--- 1494,1499 ----
*************** bfs_walk (tree binfo, tree (*fn) (tree, 
*** 1665,1685 ****
  	break;
  
        /* Queue up the base types.  */
!       binfos = BINFO_BASETYPES (binfo);
!       n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
!       for (i = 0; i < n_baselinks; i++)
  	{
! 	  tree base_binfo = TREE_VEC_ELT (binfos, i);
! 
! 	  if (qfn)
! 	    base_binfo = (*qfn) (base_binfo, data);
! 
! 	  if (base_binfo)
  	    {
! 	      if (tail == VARRAY_SIZE (bfs_bases))
! 		VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
! 	      VARRAY_TREE (bfs_bases, tail) = base_binfo;
! 	      ++tail;
  	    }
  	}
      }
--- 1503,1528 ----
  	break;
  
        /* Queue up the base types.  */
!       if (BINFO_BASETYPES (binfo))
  	{
! 	  int i, n = TREE_VEC_LENGTH (BINFO_BASETYPES (binfo));
! 	  
! 	  for (i = 0; i != n; i++)
  	    {
! 	      tree base_binfo;
! 	      
! 	      if (qfn)
! 		base_binfo = (*qfn) (binfo, i, data);
! 	      else
! 		base_binfo = BINFO_BASETYPE (binfo, i);
! 
! 	      if (base_binfo)
! 		{
! 		  if (tail == VARRAY_SIZE (bfs_bases))
! 		    VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
! 		  VARRAY_TREE (bfs_bases, tail) = base_binfo;
! 		  ++tail;
! 		}
  	    }
  	}
      }
*************** bfs_walk (tree binfo, tree (*fn) (tree, 
*** 1692,1704 ****
     in postorder.  */
  
  tree
! dfs_walk_real (tree binfo, 
! 	       tree (*prefn) (tree, void *), tree (*postfn) (tree, void *),
! 	       tree (*qfn) (tree, void *), void *data)
  {
-   int i;
-   int n_baselinks;
-   tree binfos;
    tree rval = NULL_TREE;
  
    /* Call the pre-order walking function.  */
--- 1535,1546 ----
     in postorder.  */
  
  tree
! dfs_walk_real (tree binfo,
! 	       tree (*prefn) (tree, void *),
! 	       tree (*postfn) (tree, void *),
! 	       tree (*qfn) (tree, int, void *),
! 	       void *data)
  {
    tree rval = NULL_TREE;
  
    /* Call the pre-order walking function.  */
*************** dfs_walk_real (tree binfo, 
*** 1710,1729 ****
      }
  
    /* Process the basetypes.  */
!   binfos = BINFO_BASETYPES (binfo);
!   n_baselinks = BINFO_N_BASETYPES (binfo);
!   for (i = 0; i < n_baselinks; i++)
      {
!       tree base_binfo = TREE_VEC_ELT (binfos, i);
!       
!       if (qfn)
! 	base_binfo = (*qfn) (base_binfo, data);
! 
!       if (base_binfo)
  	{
! 	  rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
! 	  if (rval)
! 	    return rval;
  	}
      }
  
--- 1552,1575 ----
      }
  
    /* Process the basetypes.  */
!   if (BINFO_BASETYPES (binfo))
      {
!       int i, n = TREE_VEC_LENGTH (BINFO_BASETYPES (binfo));
!       for (i = 0; i != n; i++)
  	{
! 	  tree base_binfo;
!       
! 	  if (qfn)
! 	    base_binfo = (*qfn) (binfo, i, data);
! 	  else
! 	    base_binfo = BINFO_BASETYPE (binfo, i);
! 	  
! 	  if (base_binfo)
! 	    {
! 	      rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
! 	      if (rval)
! 		return rval;
! 	    }
  	}
      }
  
*************** dfs_walk_real (tree binfo, 
*** 1738,1745 ****
     performed.  */
  
  tree
! dfs_walk (tree binfo, tree (*fn) (tree, void *),
! 	  tree (*qfn) (tree, void *), void *data)
  {
    return dfs_walk_real (binfo, 0, fn, qfn, data);
  }
--- 1584,1593 ----
     performed.  */
  
  tree
! dfs_walk (tree binfo,
! 	  tree (*fn) (tree, void *),
! 	  tree (*qfn) (tree, int, void *),
! 	  void *data)
  {
    return dfs_walk_real (binfo, 0, fn, qfn, data);
  }
*************** look_for_overrides_r (tree type, tree fn
*** 1941,1999 ****
    return look_for_overrides (type, fndecl);
  }
  
- /* A queue function to use with dfs_walk that only walks into
-    canonical bases.  DATA should be the type of the complete object,
-    or a TREE_LIST whose TREE_PURPOSE is the type of the complete
-    object.  By using this function as a queue function, you will walk
-    over exactly those BINFOs that actually exist in the complete
-    object, including those for virtual base classes.  If you
-    SET_BINFO_MARKED for each binfo you process, you are further
-    guaranteed that you will walk into each virtual base class exactly
-    once.  */
- 
- tree
- dfs_unmarked_real_bases_queue_p (tree binfo, void *data)
- {
-   if (TREE_VIA_VIRTUAL (binfo))
-     {
-       tree type = (tree) data;
- 
-       if (TREE_CODE (type) == TREE_LIST)
- 	type = TREE_PURPOSE (type);
-       binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
-     }
-   return unmarkedp (binfo, NULL);
- }
- 
- /* Like dfs_unmarked_real_bases_queue_p but walks only into things
-    that are marked, rather than unmarked.  */
- 
- tree
- dfs_marked_real_bases_queue_p (tree binfo, void *data)
- {
-   if (TREE_VIA_VIRTUAL (binfo))
-     {
-       tree type = (tree) data;
- 
-       if (TREE_CODE (type) == TREE_LIST)
- 	type = TREE_PURPOSE (type);
-       binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
-     }
-   return markedp (binfo, NULL);
- }
- 
- /* A queue function that skips all virtual bases (and their 
-    bases).  */
- 
- tree
- dfs_skip_vbases (tree binfo, void *data ATTRIBUTE_UNUSED)
- {
-   if (TREE_VIA_VIRTUAL (binfo))
-     return NULL_TREE;
- 
-   return binfo;
- }
- 
  /* Called via dfs_walk from dfs_get_pure_virtuals.  */
  
  static tree
--- 1789,1794 ----
*************** dfs_get_pure_virtuals (tree binfo, void 
*** 2017,2023 ****
  			 CLASSTYPE_PURE_VIRTUALS (type));
      }
    
!   SET_BINFO_MARKED (binfo);
  
    return NULL_TREE;
  }
--- 1812,1818 ----
  			 CLASSTYPE_PURE_VIRTUALS (type));
      }
    
!   BINFO_MARKED (binfo) = 1;
  
    return NULL_TREE;
  }
*************** get_pure_virtuals (tree type)
*** 2038,2047 ****
       (A primary base is not interesting because the derived class of
       which it is a primary base will contain vtable entries for the
       pure virtuals in the base class.  */
!   dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, 
! 	    dfs_unmarked_real_bases_queue_p, type);
!   dfs_walk (TYPE_BINFO (type), dfs_unmark, 
! 	    dfs_marked_real_bases_queue_p, type);
  
    /* Put the pure virtuals in dfs order.  */
    CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
--- 1833,1840 ----
       (A primary base is not interesting because the derived class of
       which it is a primary base will contain vtable entries for the
       pure virtuals in the base class.  */
!   dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, unmarkedp, type);
!   dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, type);
  
    /* Put the pure virtuals in dfs order.  */
    CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
*************** get_pure_virtuals (tree type)
*** 2066,2107 ****
  /* DEPTH-FIRST SEARCH ROUTINES.  */
  
  tree 
! markedp (tree binfo, void *data ATTRIBUTE_UNUSED)
  {
    return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
  }
  
  tree
! unmarkedp (tree binfo, void *data ATTRIBUTE_UNUSED)
  {
!   return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
! }
! 
! tree
! marked_vtable_pathp (tree binfo, void *data ATTRIBUTE_UNUSED)
! { 
!   return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE; 
! }
! 
! tree
! unmarked_vtable_pathp (tree binfo, void *data ATTRIBUTE_UNUSED)
! { 
!   return !BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE; 
  }
  
  static tree
! marked_pushdecls_p (tree binfo, void *data ATTRIBUTE_UNUSED)
  {
!   return (CLASS_TYPE_P (BINFO_TYPE (binfo))
! 	  && !dependent_base_p (binfo)
  	  && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE; 
  }
  
  static tree
! unmarked_pushdecls_p (tree binfo, void *data ATTRIBUTE_UNUSED)
  { 
!   return (CLASS_TYPE_P (BINFO_TYPE (binfo))
! 	  && !dependent_base_p (binfo)
  	  && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
  }
  
--- 1859,1894 ----
  /* DEPTH-FIRST SEARCH ROUTINES.  */
  
  tree 
! markedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED) 
  {
+   tree binfo = BINFO_BASETYPE (derived, ix);
+   
    return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
  }
  
  tree
! unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED) 
  {
!   tree binfo = BINFO_BASETYPE (derived, ix);
!   
!   return !BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
  }
  
  static tree
! marked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
  {
!   tree binfo = BINFO_BASETYPE (derived, ix);
!   
!   return (!BINFO_DEPENDENT_BASE_P (binfo)
  	  && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE; 
  }
  
  static tree
! unmarked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
  { 
!   tree binfo = BINFO_BASETYPE (derived, ix);
!   
!   return (!BINFO_DEPENDENT_BASE_P (binfo)
  	  && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
  }
  
*************** unmarked_pushdecls_p (tree binfo, void *
*** 2111,2209 ****
  
  tree
  dfs_unmark (tree binfo, void *data ATTRIBUTE_UNUSED)
- { 
-   CLEAR_BINFO_MARKED (binfo); 
-   return NULL_TREE;
- }
- 
- /* get virtual base class types.
-    This adds type to the vbase_types list in reverse dfs order.
-    Ordering is very important, so don't change it.  */
- 
- static tree
- dfs_get_vbase_types (tree binfo, void *data)
- {
-   tree type = (tree) data;
- 
-   if (TREE_VIA_VIRTUAL (binfo))
-     CLASSTYPE_VBASECLASSES (type)
-       = tree_cons (BINFO_TYPE (binfo), 
- 		   binfo, 
- 		   CLASSTYPE_VBASECLASSES (type));
-   SET_BINFO_MARKED (binfo);
-   return NULL_TREE;
- }
- 
- /* Called via dfs_walk from mark_primary_bases.  Builds the
-    inheritance graph order list of BINFOs.  */
- 
- static tree
- dfs_build_inheritance_graph_order (tree binfo, void *data)
  {
!   tree *last_binfo = (tree *) data;
! 
!   if (*last_binfo)
!     TREE_CHAIN (*last_binfo) = binfo;
!   *last_binfo = binfo;
!   SET_BINFO_MARKED (binfo);
    return NULL_TREE;
  }
  
- /* Set CLASSTYPE_VBASECLASSES for TYPE.  */
- 
- void
- get_vbase_types (tree type)
- {
-   tree last_binfo;
- 
-   CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
-   dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
-   /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
-      reverse it so that we get normal dfs ordering.  */
-   CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
-   dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
-   /* Thread the BINFOs in inheritance-graph order.  */
-   last_binfo = NULL;
-   dfs_walk_real (TYPE_BINFO (type),
- 		 dfs_build_inheritance_graph_order,
- 		 NULL,
- 		 unmarkedp,
- 		 &last_binfo);
-   dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
- }
- 
- /* Called from find_vbase_instance via dfs_walk.  */
- 
- static tree
- dfs_find_vbase_instance (tree binfo, void *data)
- {
-   tree base = TREE_VALUE ((tree) data);
- 
-   if (BINFO_PRIMARY_P (binfo)
-       && same_type_p (BINFO_TYPE (binfo), base))
-     return binfo;
- 
-   return NULL_TREE;
- }
- 
- /* Find the real occurrence of the virtual BASE (a class type) in the
-    hierarchy dominated by TYPE.  */
- 
- tree
- find_vbase_instance (tree base, tree type)
- {
-   tree instance;
- 
-   instance = binfo_for_vbase (base, type);
-   if (!BINFO_PRIMARY_P (instance))
-     return instance;
- 
-   return dfs_walk (TYPE_BINFO (type), 
- 		   dfs_find_vbase_instance, 
- 		   NULL,
- 		   build_tree_list (type, base));
- }
- 
  
  /* Debug info for C++ classes can get very large; try to avoid
     emitting it everywhere.
--- 1898,1908 ----
  
  tree
  dfs_unmark (tree binfo, void *data ATTRIBUTE_UNUSED)
  {
!   BINFO_MARKED (binfo) = 0;
    return NULL_TREE;
  }
  
  
  /* Debug info for C++ classes can get very large; try to avoid
     emitting it everywhere.
*************** dfs_debug_mark (tree binfo, void *data A
*** 2268,2275 ****
     info for this base class.  */
  
  static tree 
! dfs_debug_unmarkedp (tree binfo, void *data ATTRIBUTE_UNUSED)
! { 
    return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) 
  	  ? binfo : NULL_TREE);
  }
--- 1967,1976 ----
     info for this base class.  */
  
  static tree 
! dfs_debug_unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
! {
!   tree binfo = BINFO_BASETYPE (derived, ix);
!   
    return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) 
  	  ? binfo : NULL_TREE);
  }
*************** note_debug_info_needed (tree type)
*** 2295,2316 ****
  
  /* Subroutines of push_class_decls ().  */
  
- /* Returns 1 iff BINFO is a base we shouldn't really be able to see into,
-    because it (or one of the intermediate bases) depends on template parms.  */
- 
- static int
- dependent_base_p (tree binfo)
- {
-   for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
-     {
-       if (currently_open_class (TREE_TYPE (binfo)))
- 	break;
-       if (dependent_type_p (TREE_TYPE (binfo)))
- 	return 1;
-     }
-   return 0;
- }
- 
  static void
  setup_class_bindings (tree name, int type_binding_p)
  {
--- 1996,2001 ----
*************** dfs_push_type_decls (tree binfo, void *d
*** 2383,2389 ****
  
    /* We can't just use BINFO_MARKED because envelope_add_decl uses
       DERIVED_FROM_P, which calls get_base_distance.  */
!   SET_BINFO_PUSHDECLS_MARKED (binfo);
  
    return NULL_TREE;
  }
--- 2070,2076 ----
  
    /* We can't just use BINFO_MARKED because envelope_add_decl uses
       DERIVED_FROM_P, which calls get_base_distance.  */
!   BINFO_PUSHDECLS_MARKED (binfo) = 1;
  
    return NULL_TREE;
  }
*************** dfs_push_type_decls (tree binfo, void *d
*** 2394,2439 ****
  static tree
  dfs_push_decls (tree binfo, void *data)
  {
!   tree type;
    tree method_vec;
!   int dep_base_p;
! 
!   type = BINFO_TYPE (binfo);
!   dep_base_p = (processing_template_decl && type != current_class_type
! 		&& dependent_base_p (binfo));
!   if (!dep_base_p)
!     {
!       tree fields;
!       for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
! 	if (DECL_NAME (fields) 
! 	    && TREE_CODE (fields) != TYPE_DECL
! 	    && TREE_CODE (fields) != USING_DECL
! 	    && !DECL_ARTIFICIAL (fields))
! 	  setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
! 	else if (TREE_CODE (fields) == FIELD_DECL
! 		 && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
! 	  dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
! 	  
!       method_vec = (CLASS_TYPE_P (type) 
! 		    ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
! 
!       if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
! 	{
! 	  tree *methods;
! 	  tree *end;
! 
! 	  /* Farm out constructors and destructors.  */
! 	  end = TREE_VEC_END (method_vec);
! 
! 	  for (methods = &TREE_VEC_ELT (method_vec, 2);
! 	       methods < end && *methods;
! 	       methods++)
! 	    setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)), 
! 				  /*type_binding_p=*/0);
! 	}
      }
  
!   CLEAR_BINFO_PUSHDECLS_MARKED (binfo);
  
    return NULL_TREE;
  }
--- 2081,2119 ----
  static tree
  dfs_push_decls (tree binfo, void *data)
  {
!   tree type = BINFO_TYPE (binfo);
    tree method_vec;
!   tree fields;
!   
!   for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
!     if (DECL_NAME (fields) 
! 	&& TREE_CODE (fields) != TYPE_DECL
! 	&& TREE_CODE (fields) != USING_DECL
! 	&& !DECL_ARTIFICIAL (fields))
!       setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
!     else if (TREE_CODE (fields) == FIELD_DECL
! 	     && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
!       dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
!   
!   method_vec = (CLASS_TYPE_P (type) 
! 		? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
!   
!   if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
!     {
!       tree *methods;
!       tree *end;
!       
!       /* Farm out constructors and destructors.  */
!       end = TREE_VEC_END (method_vec);
!       
!       for (methods = &TREE_VEC_ELT (method_vec, 2);
! 	   methods < end && *methods;
! 	   methods++)
! 	setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)), 
! 			      /*type_binding_p=*/0);
      }
  
!   BINFO_PUSHDECLS_MARKED (binfo) = 0;
  
    return NULL_TREE;
  }
*************** dfs_check_overlap (tree empty_binfo, voi
*** 2612,2620 ****
  /* Trivial function to stop base traversal when we find something.  */
  
  static tree
! dfs_no_overlap_yet (tree binfo, void *data)
  {
    struct overlap_info *oi = (struct overlap_info *) data;
    return !oi->found_overlap ? binfo : NULL_TREE;
  }
  
--- 2292,2302 ----
  /* Trivial function to stop base traversal when we find something.  */
  
  static tree
! dfs_no_overlap_yet (tree derived, int ix, void *data)
  {
+   tree binfo = BINFO_BASETYPE (derived, ix);
    struct overlap_info *oi = (struct overlap_info *) data;
+   
    return !oi->found_overlap ? binfo : NULL_TREE;
  }
  
*************** binfo_via_virtual (tree binfo, tree limi
*** 2693,2706 ****
    return NULL_TREE;
  }
  
! /* Returns the BINFO (if any) for the virtual baseclass T of the class
!    C from the CLASSTYPE_VBASECLASSES list.  */
  
  tree
! binfo_for_vbase (tree basetype, tree classtype)
  {
!   tree binfo;
  
!   binfo = purpose_member (basetype, CLASSTYPE_VBASECLASSES (classtype));
!   return binfo ? TREE_VALUE (binfo) : NULL_TREE;
  }
--- 2375,2473 ----
    return NULL_TREE;
  }
  
! /* BINFO is a base binfo in the complete type BINFO_TYPE (HERE).
!    Find the equivalent binfo within whatever graph HERE is located.
!    This is the inverse of original_binfo. */
  
  tree
! copied_binfo (tree binfo, tree here)
  {
!   tree result = NULL_TREE;
!   
!   if (TREE_VIA_VIRTUAL (binfo))
!     {
!       tree t;
  
!       for (t = here; BINFO_INHERITANCE_CHAIN (t);
! 	   t = BINFO_INHERITANCE_CHAIN (t))
! 	continue;
!       
!       result = purpose_member (BINFO_TYPE (binfo),
! 			       CLASSTYPE_VBASECLASSES (BINFO_TYPE (t)));
!       result = TREE_VALUE (result);
!     }
!   else if (BINFO_INHERITANCE_CHAIN (binfo))
!     {
!       tree base_binfos;
!       int ix, n;
!       
!       base_binfos = copied_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
!       base_binfos = BINFO_BASETYPES (base_binfos);
!       n = TREE_VEC_LENGTH (base_binfos);
!       for (ix = 0; ix != n; ix++)
! 	{
! 	  tree base = TREE_VEC_ELT (base_binfos, ix);
! 	  
! 	  if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
! 	    {
! 	      result = base;
! 	      break;
! 	    }
! 	}
!     }
!   else
!     {
!       my_friendly_assert (BINFO_TYPE (here) == BINFO_TYPE (binfo), 20030202);
!       result = here;
!     }
! 
!   my_friendly_assert (result, 20030202);
!   return result;
  }
+ 
+ /* BINFO is some base binfo of HERE, within some other
+    hierachy. Return the equivalent binfo, but in the hierarchy
+    dominated by HERE.  This is the inverse of copied_binfo.  If BINFO
+    is not a base binfo of HERE, returns NULL_TREE. */
+ 
+ tree
+ original_binfo (tree binfo, tree here)
+ {
+   tree result = NULL;
+   
+   if (BINFO_TYPE (binfo) == BINFO_TYPE (here))
+     result = here;
+   else if (TREE_VIA_VIRTUAL (binfo))
+     {
+       result = purpose_member (BINFO_TYPE (binfo),
+ 			       CLASSTYPE_VBASECLASSES (BINFO_TYPE (here)));
+       if (result)
+ 	result = TREE_VALUE (result);
+     }
+   else if (BINFO_INHERITANCE_CHAIN (binfo))
+     {
+       tree base_binfos;
+       
+       base_binfos = original_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
+       if (base_binfos)
+ 	{
+ 	  int ix, n;
+ 	  
+ 	  base_binfos = BINFO_BASETYPES (base_binfos);
+ 	  n = TREE_VEC_LENGTH (base_binfos);
+ 	  for (ix = 0; ix != n; ix++)
+ 	    {
+ 	      tree base = TREE_VEC_ELT (base_binfos, ix);
+ 	      
+ 	      if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
+ 		{
+ 		  result = base;
+ 		  break;
+ 		}
+ 	    }
+ 	}
+     }
+   
+   return result;
+ }
+ 

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