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