C++ PATCH to remimplement get_pure_virtuals

Mark Mitchell mark@codesourcery.com
Sat Jan 1 20:35:00 GMT 2000


This patch reimplements get_pure_virtuals in a more general way: one
that will handle virtual base classes as primary bases.  Many of the
routines that walk over the base class hierarchy to create vtables,
etc., will be reworked in a similar fashion in the near future.

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

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

	* cp-tree.h (CLASSTYPE_N_BASECLASSES): Use BINFO_N_BASETYPES.
	(BINFO_PRIMARY_MARKED_P): New macro.
	(SET_BINFO_PRIMARY_MARKED_P): Likewise.
	(CLEAR_BINFO_PRIMARY_MARKED_P): Likewise.
	(mark_primary_bases): New function.
	(unmark_primary_bases): Likewise.
	* search.c (get_abstract_virtuals_1): Remove.
	(dfs_mark_primary_bases): New function.
	(mark_primary_bases): Likewise.
	(dfs_unmark_primary_bases): Likewise.
	(unmark_primary_bases): Likewise.
	(dfs_get_pure_virtuals): Likewise.

Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.374
diff -c -p -r1.374 cp-tree.h
*** cp-tree.h	2000/01/02 04:04:05	1.374
--- cp-tree.h	2000/01/02 04:30:46
*************** struct lang_type
*** 1420,1427 ****
  
  /* Number of direct baseclasses of NODE.  */
  #define CLASSTYPE_N_BASECLASSES(NODE) \
!   (TYPE_BINFO_BASETYPES (NODE) ? \
!    TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES(NODE)) : 0)
  
  /* Used for keeping search-specific information.  Any search routine
     which uses this must define what exactly this slot is used for.  */
--- 1420,1426 ----
  
  /* Number of direct baseclasses of NODE.  */
  #define CLASSTYPE_N_BASECLASSES(NODE) \
!   (BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
  
  /* Used for keeping search-specific information.  Any search routine
     which uses this must define what exactly this slot is used for.  */
*************** struct lang_type
*** 1563,1568 ****
--- 1562,1577 ----
  #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 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)
  
*************** extern int flag_new_for_scope;
*** 2533,2539 ****
     to `struct S {}; typedef struct S S;' in C.  This macro will hold
     for the typedef indicated in this example.  Note that in C++, there
     is a second implicit typedef for each class, in the scope of `S'
!    itself, so that you can `S::S'.  This macro does *not* hold for
     those typedefs.  */
  #define DECL_IMPLICIT_TYPEDEF_P(NODE) \
    (TREE_CODE ((NODE)) == TYPE_DECL && DECL_LANG_FLAG_2 ((NODE)))
--- 2542,2548 ----
     to `struct S {}; typedef struct S S;' in C.  This macro will hold
     for the typedef indicated in this example.  Note that in C++, there
     is a second implicit typedef for each class, in the scope of `S'
!    itself, so that you can say `S::S'.  This macro does *not* hold for
     those typedefs.  */
  #define DECL_IMPLICIT_TYPEDEF_P(NODE) \
    (TREE_CODE ((NODE)) == TYPE_DECL && DECL_LANG_FLAG_2 ((NODE)))
*************** extern tree dfs_walk                    
*** 3900,3905 ****
--- 3909,3916 ----
  						       void *));
  extern tree dfs_unmark                          PROTO((tree, void *));
  extern tree markedp                             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));
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.137
diff -c -p -r1.137 search.c
*** search.c	2000/01/02 04:04:05	1.137
--- search.c	2000/01/02 04:30:52
*************** pop_stack_level (stack)
*** 75,81 ****
  #define search_level stack_level
  static struct search_level *search_stack;
  
- static tree get_abstract_virtuals_1 PROTO((tree, int, tree));
  static tree next_baselink PROTO((tree));
  static tree get_vbase_1 PROTO((tree, tree, unsigned int *));
  static tree convert_pointer_to_vbase PROTO((tree, tree));
--- 75,80 ----
*************** static int friend_accessible_p PROTO ((t
*** 152,157 ****
--- 151,158 ----
  static void setup_class_bindings PROTO ((tree, int));
  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.  */
  
*************** get_matching_virtual (binfo, fndecl, dto
*** 2103,2148 ****
      }
  }
  
! /* Return the list of virtual functions which are abstract in type
!    TYPE that come from non virtual base classes.  See
!    expand_direct_vtbls_init for the style of search we do.  */
  
  static tree
! get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
       tree binfo;
!      int do_self;
!      tree abstract_virtuals;
  {
!   tree binfos = BINFO_BASETYPES (binfo);
!   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
! 
!   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))
! 	abstract_virtuals
! 	  = get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
! 				     abstract_virtuals);
      }
!   /* Should we use something besides CLASSTYPE_VFIELDS? */
!   if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
      {
        tree virtuals;
  
!       virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL);
  
!       while (virtuals)
! 	{
! 	  tree base_fndecl = TREE_VALUE (virtuals);
! 	  if (DECL_PURE_VIRTUAL_P (base_fndecl))
! 	    abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, 
! 					   abstract_virtuals);
! 	  virtuals = TREE_CHAIN (virtuals);
! 	}
!     }
!   return abstract_virtuals;
  }
  
  /* Set CLASSTYPE_PURE_VIRTUALS for TYPE.  */
--- 2104,2203 ----
      }
  }
  
! /* Called via dfs_walk from mark_nonprimary_bases.  */
  
  static tree
! dfs_mark_primary_bases (binfo, data)
       tree binfo;
!      void *data ATTRIBUTE_UNUSED;
  {
!   if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
      {
!       int i;
! 
!       i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
!       SET_BINFO_PRIMARY_MARKED_P (BINFO_BASETYPE (binfo, i));
      }
! 
!   SET_BINFO_MARKED (binfo);
! 
!   return NULL_TREE;
! }
! 
! /* 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,
! 	    unmarkedp,
! 	    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.  */
! 
! static tree
! dfs_get_pure_virtuals (binfo, data)
!      tree binfo;
!      void *data;
! {
!   /* We're not interested in primary base classes; the derived class
!      of which they are a primary base will contain the information we
!      need.  */
!   if (!BINFO_PRIMARY_MARKED_P (binfo))
      {
+       tree type = (tree) data;
+       tree shared_binfo;
        tree virtuals;
+       
+       /* If this is a virtual base class, then use the shared binfo
+ 	 since that is the only place where BINFO_VIRTUALS is valid;
+ 	 the various copies in the main hierarchy are not updated when
+ 	 vtables are created.  */
+       shared_binfo = (TREE_VIA_VIRTUAL (binfo) 
+ 		      ? BINFO_FOR_VBASE (BINFO_TYPE (binfo), type)
+ 		      : binfo);
+ 
+       for (virtuals = skip_rtti_stuff (shared_binfo, 
+ 				       BINFO_TYPE (shared_binfo), 
+ 				       NULL);
+ 	   virtuals;
+ 	   virtuals = TREE_CHAIN (virtuals))
+ 	if (DECL_PURE_VIRTUAL_P (TREE_VALUE (virtuals)))
+ 	  CLASSTYPE_PURE_VIRTUALS (type) 
+ 	    = tree_cons (NULL_TREE, TREE_VALUE (virtuals),
+ 			 CLASSTYPE_PURE_VIRTUALS (type));
+     }
  
!   CLEAR_BINFO_MARKED (binfo);
  
!   return NULL_TREE;
  }
  
  /* Set CLASSTYPE_PURE_VIRTUALS for TYPE.  */
*************** get_pure_virtuals (type)
*** 2152,2182 ****
       tree type;
  {
    tree vbases;
!   tree abstract_virtuals = NULL;
  
-   /* First get all from non-virtual bases.  */
-   abstract_virtuals
-     = get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
- 					       
    for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
      {
!       tree virtuals;
! 
!       virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
  
        while (virtuals)
  	{
  	  tree base_fndecl = TREE_VALUE (virtuals);
  	  if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
  	    cp_error ("`%#D' needs a final overrider", base_fndecl);
- 	  else if (DECL_PURE_VIRTUAL_P (base_fndecl))
- 	    abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, 
- 					   abstract_virtuals);
  	  virtuals = TREE_CHAIN (virtuals);
  	}
      }
- 
-   CLASSTYPE_PURE_VIRTUALS (type) = nreverse (abstract_virtuals);
  }
  
  static tree
--- 2207,2242 ----
       tree type;
  {
    tree vbases;
! 
!   /* 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));
  
    for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
      {
!       tree virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
  
        while (virtuals)
  	{
  	  tree base_fndecl = TREE_VALUE (virtuals);
  	  if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
  	    cp_error ("`%#D' needs a final overrider", base_fndecl);
  	  virtuals = TREE_CHAIN (virtuals);
  	}
      }
  }
  
  static tree


More information about the Gcc-patches mailing list