C++ PATCH: More support for virtual primary bases

Mark Mitchell mark@codesourcery.com
Sun Jan 2 22:59:00 GMT 2000


This patch continues adding support for primary virtual base classes.
Among the other cleanups, the notable change is to modify_all_vtables;
using the dfs_walk routines to iterate over the hierarchy makes for
much simpler expression of the algorithms involved, and automatically
generalizes them to deal with the different ABIs.

I suspect that (if we were to care to do so) adding support for other
vendor ABIs (such as the Sun C++ ABI on SPARC Solaris) would be not
too difficult, given the generalized code.  (Of course, there are
patent issues with some of the vendor ABIs.)

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

2000-01-02  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (CLASSTYPE_VFIELDS): Move definition.
	(BINFO_PRIMARY_MARKED_P): Use flag 5.
	(SET_BINFO_PRIMARY_MARKED_P): Likewise.
	(CLEAR_BINFO_PRIMARY_MARKED_P): Likewise.
	(unmark_primary_bases): Remove declaration.
	(unmarkedp): Declare.
	(dfs_vbase_unmark): Likewise.
	* class.c (determine_primary_base): Return immediately if there
	are no base classes.  Call mark_primary_bases here.
	(modify_all_direct_vtables): Remove.
	(modify_all_indirect_vtables): Remove.
	(dfs_modify_vtables_queue_p): New function.	
	(dfs_modify_vtables): New function.
	(modify_all_vtables): Use them.
	(build_base_fields): Build FIELD_DECLs for primary virtual base
	classes.
	(create_vtable_ptr): Don't call determine_primary_base here.
	(dfs_mark_primary_bases_and_set_vbase_offsets): Rename to ...
	(dfs_set_offset_for_vbases): ... this.
	(layout_virtual_bases): Use it.
	(layout_class_type): Call determine_primary_base here.
	* search.c (unmarkedp): Make it global.
	(shared_marked_p): Simplify.
	(shared_unmarked_p): Likewise.
	(dfs_primary_bases_queue_p): Remove.
	(dfs_unmark_primary_bases): Likewise.
	(unmark_primary_bases): Likewise.
	(mark_primary_bases): Simplify.
	(get_pure_virtuals): Don't call mark_primary_bases here.
	(dfs_vbase_unmark): New function.
	(get_vbase_types): Simplify.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.220
diff -c -p -r1.220 class.c
*** class.c	2000/01/03 04:05:43	1.220
--- class.c	2000/01/03 06:55:06
*************** static void check_for_override PROTO((tr
*** 102,110 ****
  static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
  static tree get_class_offset PROTO((tree, tree, tree, tree));
  static void modify_one_vtable PROTO((tree, tree, tree));
  static void modify_all_vtables PROTO((tree, tree));
- static void modify_all_direct_vtables PROTO((tree, int, tree, tree));
- static void modify_all_indirect_vtables PROTO((tree, int, int, tree, tree));
  static void determine_primary_base PROTO((tree, int *));
  static void finish_struct_methods PROTO((tree));
  static void maybe_warn_about_overly_private_class PROTO ((tree));
--- 102,110 ----
  static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
  static tree get_class_offset PROTO((tree, tree, tree, tree));
  static void modify_one_vtable PROTO((tree, tree, tree));
+ static tree dfs_modify_vtables_queue_p PROTO((tree, void *));
+ static tree dfs_modify_vtables PROTO((tree, void *));
  static void modify_all_vtables PROTO((tree, tree));
  static void determine_primary_base PROTO((tree, int *));
  static void finish_struct_methods PROTO((tree));
  static void maybe_warn_about_overly_private_class PROTO ((tree));
*************** static void fixup_inline_methods PROTO((
*** 138,144 ****
  static void set_primary_base PROTO((tree, int, int *));
  static void propagate_binfo_offsets PROTO((tree, tree));
  static void layout_basetypes PROTO((tree));
! static tree dfs_mark_primary_bases_and_set_vbase_offsets PROTO((tree, void *));
  static void layout_virtual_bases PROTO((tree));
  static void remove_base_fields PROTO((tree));
  
--- 138,144 ----
  static void set_primary_base PROTO((tree, int, int *));
  static void propagate_binfo_offsets PROTO((tree, tree));
  static void layout_basetypes PROTO((tree));
! static tree dfs_set_offset_for_vbases PROTO((tree, void *));
  static void layout_virtual_bases PROTO((tree));
  static void remove_base_fields PROTO((tree));
  
*************** determine_primary_base (t, has_virtual_p
*** 1651,1656 ****
--- 1651,1660 ----
  {
    int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
  
+   /* If there are no baseclasses, there is certainly no primary base.  */
+   if (n_baseclasses == 0)
+     return;
+ 
    *has_virtual_p = 0;
  
    for (i = 0; i < n_baseclasses; i++)
*************** determine_primary_base (t, has_virtual_p
*** 1666,1672 ****
  	  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
  	    CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
  
! 	  /* A virtual baseclass can't be the primary base.  */
  	  if (TREE_VIA_VIRTUAL (base_binfo))
  	    continue;
  
--- 1670,1678 ----
  	  if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
  	    CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
  
! 	  /* A virtual baseclass can't be the primary base under the
! 	     old ABI.  And under the new ABI we still prefer a
! 	     non-virtual base.  */
  	  if (TREE_VIA_VIRTUAL (base_binfo))
  	    continue;
  
*************** determine_primary_base (t, has_virtual_p
*** 1698,1703 ****
--- 1704,1714 ----
  
    if (!TYPE_VFIELD (t))
      CLASSTYPE_VFIELD_PARENT (t) = -1;
+ 
+   /* Now that we know what the primary base class is, we can run
+      through the entire hierarchy marking the primary bases for future
+      reference.  */
+   mark_primary_bases (t);
  }
  
  /* Set memoizing fields and bits of T (and its variants) for later
*************** modify_one_vtable (binfo, t, fndecl)
*** 2479,2509 ****
      }
  }
  
! /* These are the ones that are not through virtual base classes.  */
  
! static void
! modify_all_direct_vtables (binfo, do_self, t, fndecl)
       tree binfo;
!      int do_self;
!      tree t, fndecl;
  {
!   tree binfos = BINFO_BASETYPES (binfo);
!   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
  
!   /* Should we use something besides CLASSTYPE_VFIELDS? */
!   if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     modify_one_vtable (binfo, t, fndecl);
  
!   for (i = 0; i < n_baselinks; i++)
!     {
!       tree base_binfo = TREE_VEC_ELT (binfos, i);
!       int is_not_base_vtable
! 	= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
!       if (! TREE_VIA_VIRTUAL (base_binfo))
! 	modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl);
      }
  }
  
  /* Fixup all the delta entries in this one vtable that need updating.  */
  
  static void
--- 2490,2554 ----
      }
  }
  
! /* Called from modify_all_vtables via dfs_walk.  */
  
! static tree
! dfs_modify_vtables_queue_p (binfo, data)
       tree binfo;
!      void *data;
  {
!   tree list = (tree) data;
  
!   if (TREE_VIA_VIRTUAL (binfo))
!     binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
  
!   return (TREE_ADDRESSABLE (list) 
! 	  ? markedp (binfo, NULL) 
! 	  : unmarkedp (binfo, NULL));
! }
! 
! /* Called from modify_all_vtables via dfs_walk.  */
! 
! static tree
! dfs_modify_vtables (binfo, data)
!      tree binfo;
!      void *data;
! {
!   if (/* There's no need to modify the vtable for a primary base;
! 	 we're not going to use that vtable anyhow.  */
!       !BINFO_PRIMARY_MARKED_P (binfo)
!       /* Similarly, a base without a vtable needs no modification.  */
!       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     {
!       tree list = (tree) data;
! 
!       if (TREE_VIA_VIRTUAL (binfo))
! 	binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
!       modify_one_vtable (binfo, TREE_PURPOSE (list), TREE_VALUE (list)); 
      }
+ 
+   SET_BINFO_MARKED (binfo);
+ 
+   return NULL_TREE;
  }
  
+ static void
+ modify_all_vtables (t, fndecl)
+      tree t;
+      tree fndecl;
+ {
+   tree list;
+ 
+   list = build_tree_list (t, fndecl);
+   dfs_walk (TYPE_BINFO (t), dfs_modify_vtables, dfs_modify_vtables_queue_p,
+ 	    list);
+   /* Let dfs_modify_vtables_queue_p know to check that the mark is
+      present before queueing a base, rather than checking to see that
+      it is *not* present.  */
+   TREE_ADDRESSABLE (list) = 1;
+   dfs_walk (TYPE_BINFO (t), dfs_unmark, dfs_modify_vtables_queue_p, list);
+ }
+ 
  /* Fixup all the delta entries in this one vtable that need updating.  */
  
  static void
*************** fixup_vtable_deltas (binfo, init_self, t
*** 2595,2641 ****
      fixup_vtable_deltas1 (binfo, t);
  }
  
- /* These are the ones that are through virtual base classes.  */
- 
- static void
- modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl)
-      tree binfo;
-      int do_self, via_virtual;
-      tree t, fndecl;
- {
-   tree binfos = BINFO_BASETYPES (binfo);
-   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- 
-   /* Should we use something besides CLASSTYPE_VFIELDS? */
-   if (do_self && via_virtual && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
-     modify_one_vtable (binfo, t, fndecl);
- 
-   for (i = 0; i < n_baselinks; i++)
-     {
-       tree base_binfo = TREE_VEC_ELT (binfos, i);
-       int is_not_base_vtable
- 	= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
-       if (TREE_VIA_VIRTUAL (base_binfo))
- 	{
- 	  via_virtual = 1;
- 	  base_binfo = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), t);
- 	}
-       modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl);
-     }
- }
- 
- static void
- modify_all_vtables (t, fndecl)
-      tree t;
-      tree fndecl;
- {
-   /* Do these first, so that we will make use of any non-virtual class's
-      vtable, over a virtual classes vtable.  */
-   modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl);
-   if (TYPE_USES_VIRTUAL_BASECLASSES (t))
-     modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl);
- }
- 
  /* Here, we already know that they match in every respect.
     All we have to check is where they had their declarations.  */
  
--- 2640,2645 ----
*************** build_base_fields (rec, empty_p)
*** 3765,3771 ****
  	   location information.  */
  	continue;
  
!       if (TREE_VIA_VIRTUAL (base_binfo))
  	continue;
  
        decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
--- 3769,3779 ----
  	   location information.  */
  	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_basetypes.  */
!       if (TREE_VIA_VIRTUAL (base_binfo) 
! 	  && i != CLASSTYPE_VFIELD_PARENT (rec))
  	continue;
  
        decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
*************** create_vtable_ptr (t, empty_p, has_virtu
*** 3998,4009 ****
  {
    tree fn;
  
-   /* If possible, we reuse the virtual function table pointer from one
-      of our base classes.  */
-   if (CLASSTYPE_N_BASECLASSES (t))
-     /* Remember where we got our vfield from.  */
-     determine_primary_base (t, has_virtual_p);
- 
    /* Loop over the virtual functions, adding them to our various
       vtables.  */
    for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
--- 4006,4011 ----
*************** remove_base_fields (t)
*** 4270,4300 ****
  /* Called via dfs_walk from layout_virtual_bases.  */
  
  static tree
! dfs_mark_primary_bases_and_set_vbase_offsets (binfo, data)
       tree binfo;
       void *data;
  {
!   if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
!     {
!       int i;
!       tree base_binfo;
! 
!       i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
!       base_binfo = BINFO_BASETYPE (binfo, i);
!       
!       /* If this is a virtual base class, and we've just now
! 	 discovered it to be a primary base, then reuse this copy as
! 	 the virtual base class for the complete object. */
!       if (TREE_VIA_VIRTUAL (base_binfo)
! 	  && !BINFO_PRIMARY_MARKED_P (base_binfo))
! 	{
! 	  tree vbase;
! 
! 	  vbase = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
! 	  BINFO_OFFSET (vbase) = BINFO_OFFSET (base_binfo);
! 	}
! 
!       SET_BINFO_PRIMARY_MARKED_P (BINFO_BASETYPE (binfo, i));
      }
  
    SET_BINFO_MARKED (binfo);
--- 4272,4292 ----
  /* Called via dfs_walk from layout_virtual_bases.  */
  
  static tree
! dfs_set_offset_for_vbases (binfo, data)
       tree binfo;
       void *data;
  {
!   /* If this is a primary virtual base that we have not encountered
!      before, give it an offset.  */
!   if (TREE_VIA_VIRTUAL (binfo) 
!       && BINFO_PRIMARY_MARKED_P (binfo)
!       && !BINFO_MARKED (binfo))
!     {
!       tree vbase;
! 
!       vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), (tree) data);
!       BINFO_OFFSET (vbase) = BINFO_OFFSET (binfo);
!       SET_BINFO_VBASE_MARKED (binfo);
      }
  
    SET_BINFO_MARKED (binfo);
*************** layout_virtual_bases (t)
*** 4312,4326 ****
    tree vbase;
    int dsize;
  
-   /* Mark the primary base classes.  Only virtual bases that are not
-      also primary base classes need to be laid out (since otherwise we
-      can just reuse one of the places in the hierarchy where the
-      virtual base already occurs.)  */
-   dfs_walk (TYPE_BINFO (t), 
- 	    dfs_mark_primary_bases_and_set_vbase_offsets,
- 	    dfs_mark_primary_bases_queue_p, 
- 	    t);
- 
    /* DSIZE is the size of the class without the virtual bases.  */
    dsize = TREE_INT_CST_LOW (TYPE_SIZE (t));
    /* Make every class have alignment of at least one.  */
--- 4304,4309 ----
*************** layout_virtual_bases (t)
*** 4349,4375 ****
  	   take it's address and get something different for each base.  */
  	dsize += MAX (BITS_PER_UNIT,
  		      TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype)));
- 
- 	/* Now that we've laid out this virtual base class, some of
- 	   the remaining virtual bases might have been implicitly laid
- 	   out as well -- they could be primary base classes of
- 	   classes in BASETYPE.  */
- 	dfs_walk (vbase,
- 		  dfs_mark_primary_bases_and_set_vbase_offsets,
- 		  dfs_mark_primary_bases_queue_p, 
- 		  t);
        }
  
-   /* We're done with the various marks, now, so clear them.  */
-   unmark_primary_bases (t);
-   dfs_walk (TYPE_BINFO (t), dfs_unmark, markedp, 0);
- 
    /* Now, make sure that the total size of the type is a multiple of
       its alignment.  */
    dsize = CEIL (dsize, TYPE_ALIGN (t)) * TYPE_ALIGN (t);
    TYPE_SIZE (t) = size_int (dsize);
    TYPE_SIZE_UNIT (t) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (t),
  				   size_int (BITS_PER_UNIT));
  }
  
  /* Finish the work of layout_record, now taking virtual bases into account.
--- 4332,4350 ----
  	   take it's address and get something different for each base.  */
  	dsize += MAX (BITS_PER_UNIT,
  		      TREE_INT_CST_LOW (CLASSTYPE_SIZE (basetype)));
        }
  
    /* Now, make sure that the total size of the type is a multiple of
       its alignment.  */
    dsize = CEIL (dsize, TYPE_ALIGN (t)) * TYPE_ALIGN (t);
    TYPE_SIZE (t) = size_int (dsize);
    TYPE_SIZE_UNIT (t) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (t),
  				   size_int (BITS_PER_UNIT));
+ 
+   /* Run through the hierarchy now, setting up all the BINFO_OFFSETs
+      for those virtual base classes that we did not allocate above.  */
+   dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_vbases, unmarkedp, t);
+   dfs_walk (TYPE_BINFO (t), dfs_vbase_unmark, markedp, NULL);
  }
  
  /* Finish the work of layout_record, now taking virtual bases into account.
*************** layout_class_type (t, empty_p, has_virtu
*** 4431,4436 ****
--- 4406,4415 ----
       tree *pending_virtuals_p;
       tree *pending_hard_virtuals_p;
  {
+   /* If possible, we reuse the virtual function table pointer from one
+      of our base classes.  */
+   determine_primary_base (t, has_virtual_p);
+ 
    /* Add pointers to all of our virtual base-classes.  */
    TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, empty_p),
  			     TYPE_FIELDS (t));
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.376
diff -c -p -r1.376 cp-tree.h
*** cp-tree.h	2000/01/02 19:41:09	1.376
--- cp-tree.h	2000/01/03 06:55:09
***************
*** 1,5 ****
  /* Definitions for C++ parsing and type checking.
!    Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Definitions for C++ parsing and type checking.
!    Copyright (C) 1987, 92-97, 1998, 1999, 2000 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
*************** struct lang_type
*** 1415,1423 ****
  #define BINFO_FOR_VBASE(T, C) \
    (binfo_member (T, CLASSTYPE_VBASECLASSES (C)))
  
- /* The virtual function pointer fields that this type contains.  */
- #define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields)
- 
  /* Number of direct baseclasses of NODE.  */
  #define CLASSTYPE_N_BASECLASSES(NODE) \
    (BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
--- 1415,1420 ----
*************** struct lang_type
*** 1563,1582 ****
  #define CLEAR_BINFO_PUSHDECLS_MARKED(NODE) CLEAR_BINFO_VTABLE_PATH_MARKED (NODE)
  
  /* Nonzero if this BINFO has been marked as a primary base class.  */
! #define BINFO_PRIMARY_MARKED_P(NODE) BINFO_VTABLE_PATH_MARKED (NODE)
  
  /* Mark NODE as a primary base class.  */
! #define SET_BINFO_PRIMARY_MARKED_P(NODE) SET_BINFO_VTABLE_PATH_MARKED (NODE)
  
  /* Clear the primary base class mark.  */
! #define CLEAR_BINFO_PRIMARY_MARKED_P(NODE) \
!   CLEAR_BINFO_VTABLE_PATH_MARKED (NODE)
  
  /* Used by various search routines.  */
  #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
  
  /* Accessor macros for the vfield slots in structures.  */
  
  /* Get the assoc info that caused this vfield to exist.  */
  #define VF_BINFO_VALUE(NODE) TREE_PURPOSE (NODE)
  
--- 1560,1594 ----
  #define CLEAR_BINFO_PUSHDECLS_MARKED(NODE) CLEAR_BINFO_VTABLE_PATH_MARKED (NODE)
  
  /* Nonzero if this BINFO has been marked as a primary base class.  */
! #define BINFO_PRIMARY_MARKED_P(NODE)		\
!   (TREE_VIA_VIRTUAL (NODE) 			\
!    ? CLASSTYPE_MARKED5 (BINFO_TYPE (NODE))	\
!    : TREE_LANG_FLAG_5 (NODE))
  
  /* Mark NODE as a primary base class.  */
! #define SET_BINFO_PRIMARY_MARKED_P(NODE)	\
!   (TREE_VIA_VIRTUAL (NODE)			\
!    ? SET_CLASSTYPE_MARKED5 (BINFO_TYPE (NODE))	\
!    : (TREE_LANG_FLAG_5 (NODE) = 1))
  
  /* Clear the primary base class mark.  */
! #define CLEAR_BINFO_PRIMARY_MARKED_P(NODE) 		\
!   (TREE_VIA_VIRTUAL (NODE)				\
!    ? CLEAR_CLASSTYPE_MARKED5 (BINFO_TYPE (NODE))	\
!    : (TREE_LANG_FLAG_5 (NODE) = 0))
  
  /* Used by various search routines.  */
  #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
  
  /* Accessor macros for the vfield slots in structures.  */
  
+ /* The virtual function pointer fields that this type contains.  For a
+    vfield defined just for this class, or from a primary base, the
+    TREE_PURPOSE is NULL.  Otherwise, the TREE_PURPOSE is the BINFO for
+    the class containing the vfield.  The TREE_VALUE is the class where
+    the vfield was first defined.  */
+ #define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields)
+ 
  /* Get the assoc info that caused this vfield to exist.  */
  #define VF_BINFO_VALUE(NODE) TREE_PURPOSE (NODE)
  
*************** extern tree dfs_walk                    
*** 3908,3917 ****
  						       tree (*) (tree, void *),
  						       void *));
  extern tree dfs_unmark                          PROTO((tree, void *));
  extern tree markedp                             PROTO((tree, void *));
  extern tree dfs_mark_primary_bases_queue_p      PROTO((tree, void *));
  extern void mark_primary_bases                  PROTO((tree));
- extern void unmark_primary_bases                PROTO((tree));
  
  /* in semantics.c */
  extern void finish_expr_stmt                    PROTO((tree));
--- 3920,3930 ----
  						       tree (*) (tree, void *),
  						       void *));
  extern tree dfs_unmark                          PROTO((tree, void *));
+ extern tree dfs_vbase_unmark                    PROTO((tree, void *));
  extern tree markedp                             PROTO((tree, void *));
+ extern tree unmarkedp                           PROTO((tree, void *));
  extern tree dfs_mark_primary_bases_queue_p      PROTO((tree, void *));
  extern void mark_primary_bases                  PROTO((tree));
  
  /* in semantics.c */
  extern void finish_expr_stmt                    PROTO((tree));
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.139
diff -c -p -r1.139 search.c
*** search.c	2000/01/02 19:41:09	1.139
--- search.c	2000/01/03 06:55:14
***************
*** 1,6 ****
  /* Breadth-first and depth-first routines for
     searching multiple-inheritance lattice for GNU C++.
!    Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
--- 1,6 ----
  /* Breadth-first and depth-first routines for
     searching multiple-inheritance lattice for GNU C++.
!    Copyright (C) 1987, 89, 92-97, 1998, 1999, 2000 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
*************** static void expand_upcast_fixups 
*** 95,101 ****
  static void fixup_virtual_upcast_offsets
  	PROTO((tree, tree, int, int, tree, tree, tree, tree,
  	       tree *));
- static tree unmarkedp PROTO((tree, void *));
  static tree marked_vtable_pathp PROTO((tree, void *));
  static tree unmarked_vtable_pathp PROTO((tree, void *));
  static tree marked_new_vtablep PROTO((tree, void *));
--- 95,100 ----
*************** static void setup_class_bindings PROTO (
*** 152,158 ****
  static int template_self_reference_p PROTO ((tree, tree));
  static void fixup_all_virtual_upcast_offsets PROTO ((tree, tree));
  static tree dfs_mark_primary_bases PROTO((tree, void *));
- static tree dfs_unmark_primary_bases PROTO((tree, void *));
  
  /* Allocate a level of searching.  */
  
--- 151,156 ----
*************** shared_marked_p (binfo, data)
*** 777,783 ****
       void *data;
  {
    binfo = canonical_binfo (binfo);
!   return markedp (binfo, data) ? binfo : NULL_TREE;
  }
  
  /* If BINFO is not marked, return a canonical version of BINFO.
--- 775,781 ----
       void *data;
  {
    binfo = canonical_binfo (binfo);
!   return markedp (binfo, data);
  }
  
  /* If BINFO is not marked, return a canonical version of BINFO.
*************** shared_unmarked_p (binfo, data)
*** 789,795 ****
       void *data;
  {
    binfo = canonical_binfo (binfo);
!   return unmarkedp (binfo, data) ? binfo : NULL_TREE;
  }
  
  /* Called from access_in_type via dfs_walk.  Calculate the access to
--- 787,793 ----
       void *data;
  {
    binfo = canonical_binfo (binfo);
!   return unmarkedp (binfo, data);
  }
  
  /* Called from access_in_type via dfs_walk.  Calculate the access to
*************** dfs_mark_primary_bases (binfo, data)
*** 2124,2188 ****
    return NULL_TREE;
  }
  
- /* Called via dfs_walk from mark_primary_bases.  */
- 
- tree
- dfs_mark_primary_bases_queue_p (binfo, data)
-      tree binfo;
-      void *data ATTRIBUTE_UNUSED;
- {
-   /* Don't walk into virtual baseclasses that are not primary 
-      bases.  */
-   if (TREE_VIA_VIRTUAL (binfo))
-     {
-       tree derived_class;
-       tree primary_base;
-       
-       derived_class = BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo));
-       primary_base = CLASSTYPE_PRIMARY_BINFO (derived_class);
-       if (!primary_base || !same_type_p (BINFO_TYPE (primary_base),
- 					 BINFO_TYPE (binfo)))
- 	return NULL_TREE;
-     }
- 
-   /* But do walk into everything else.  */
-   return binfo;
- }
- 
  /* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
!    dominated by TYPE that are primary bases.  (In addition,
!    BINFO_MARKED is set for all classes in the hierarchy; callers
!    should clear BINFO_MARKED.)  */
  
  void
  mark_primary_bases (type)
       tree type;
- {
-   dfs_walk (TYPE_BINFO (type), 
- 	    dfs_mark_primary_bases,
- 	    dfs_mark_primary_bases_queue_p,
- 	    NULL);
- }
- 
- /* Called from unmark_primary_bases via dfs_walk.  */
- 
- static tree
- dfs_unmark_primary_bases (binfo, data)
-      tree binfo;
-      void *data ATTRIBUTE_UNUSED;
- {
-   CLEAR_BINFO_PRIMARY_MARKED_P (binfo);
-   return NULL_TREE;
- }
- 
- /* Clear BINFO_PRIMARY_MARKED_P for all binfo in the hierarchy
-    dominated by TYPE.  */
- 
- void
- unmark_primary_bases (type)
-      tree type;
  {
!   dfs_walk (TYPE_BINFO (type), dfs_unmark_primary_bases, NULL, NULL);
  }
  
  /* Called via dfs_walk from dfs_get_pure_virtuals.  */
--- 2122,2136 ----
    return NULL_TREE;
  }
  
  /* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
!    dominated by BINFO that are primary bases.  */
  
  void
  mark_primary_bases (type)
       tree type;
  {
!   dfs_walk (TYPE_BINFO (type), dfs_mark_primary_bases, unmarkedp, NULL);
!   dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
  }
  
  /* Called via dfs_walk from dfs_get_pure_virtuals.  */
*************** dfs_get_pure_virtuals (binfo, data)
*** 2219,2226 ****
  	    = tree_cons (NULL_TREE, TREE_VALUE (virtuals),
  			 CLASSTYPE_PURE_VIRTUALS (type));
      }
! 
!   CLEAR_BINFO_MARKED (binfo);
  
    return NULL_TREE;
  }
--- 2167,2174 ----
  	    = tree_cons (NULL_TREE, TREE_VALUE (virtuals),
  			 CLASSTYPE_PURE_VIRTUALS (type));
      }
!   
!   SET_BINFO_MARKED (binfo);
  
    return NULL_TREE;
  }
*************** get_pure_virtuals (type)
*** 2236,2252 ****
    /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
       is going to be overridden.  */
    CLASSTYPE_PURE_VIRTUALS (type) = NULL_TREE;
-   /* Find all the primary bases.  */
-   mark_primary_bases (type);
    /* Now, run through all the bases which are not primary bases, and
       collect the pure virtual functions.  We look at the vtable in
       each class to determine what pure virtual functions are present.
       (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, markedp, type);
!   /* Now, clear the BINFO_PRIMARY_MARKED_P bit.  */
!   unmark_primary_bases (type);
    /* Put the pure virtuals in dfs order.  */
    CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
  
--- 2184,2198 ----
    /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
       is going to be overridden.  */
    CLASSTYPE_PURE_VIRTUALS (type) = NULL_TREE;
    /* Now, run through all the bases which are not primary bases, and
       collect the pure virtual functions.  We look at the vtable in
       each class to determine what pure virtual functions are present.
       (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, 0);
! 
    /* Put the pure virtuals in dfs order.  */
    CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
  
*************** convert_pointer_to_single_level (to_type
*** 2317,2330 ****
    return NULL_TREE;
  }
  
! tree markedp (binfo, data) 
       tree binfo;
       void *data ATTRIBUTE_UNUSED;
  { 
    return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
  }
  
! static tree
  unmarkedp (binfo, data) 
       tree binfo;
       void *data ATTRIBUTE_UNUSED;
--- 2263,2277 ----
    return NULL_TREE;
  }
  
! tree 
! markedp (binfo, data) 
       tree binfo;
       void *data ATTRIBUTE_UNUSED;
  { 
    return BINFO_MARKED (binfo) ? binfo : NULL_TREE; 
  }
  
! tree
  unmarkedp (binfo, data) 
       tree binfo;
       void *data ATTRIBUTE_UNUSED;
*************** dfs_unmark (binfo, data) 
*** 2415,2420 ****
--- 2362,2378 ----
    return NULL_TREE;
  }
  
+ /* Clear both BINFO_MARKED and BINFO_VBASE_MARKED.  */
+ 
+ tree
+ dfs_vbase_unmark (binfo, data)
+      tree binfo;
+      void *data ATTRIBUTE_UNUSED;
+ {
+   CLEAR_BINFO_VBASE_MARKED (binfo);
+   return dfs_unmark (binfo, data);
+ }
+ 
  #if 0
  static void
  dfs_mark_vtable_path (binfo) tree binfo;
*************** void
*** 2973,2995 ****
  get_vbase_types (type)
       tree type;
  {
!   tree vbase_types;
!   tree vbases;
!   tree binfo;
! 
!   binfo = TYPE_BINFO (type);
!   vbase_types = NULL_TREE;
!   dfs_walk (binfo, dfs_get_vbase_types, unmarkedp, &vbase_types);
!   dfs_walk (binfo, dfs_unmark, markedp, 0);
    /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
       reverse it so that we get normal dfs ordering.  */
!   vbase_types = nreverse (vbase_types);
! 
!   /* unmark marked vbases */
!   for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
!     CLEAR_BINFO_VBASE_MARKED (vbases);
! 
!   CLASSTYPE_VBASECLASSES (type) = vbase_types;
  }
  
  /* Debug info for C++ classes can get very large; try to avoid
--- 2931,2943 ----
  get_vbase_types (type)
       tree type;
  {
!   CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
!   dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp,
! 	    &CLASSTYPE_VBASECLASSES (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_vbase_unmark, markedp, 0);
  }
  
  /* Debug info for C++ classes can get very large; try to avoid



More information about the Gcc-patches mailing list