/* Number of direct baseclasses of NODE. */
#define CLASSTYPE_N_BASECLASSES(NODE) \
- (TYPE_BINFO_BASETYPES (NODE) ? \
- TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES(NODE)) : 0)
+ (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. */
#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)
\f
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
+ 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)))
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));
#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));
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. */
}
}
-/* 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. */
+/* Called via dfs_walk from mark_nonprimary_bases. */
static tree
-get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
+dfs_mark_primary_bases (binfo, data)
tree binfo;
- int do_self;
- tree abstract_virtuals;
+ void *data ATTRIBUTE_UNUSED;
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
+ if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
{
- 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);
+ int i;
+
+ i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ SET_BINFO_PRIMARY_MARKED_P (BINFO_BASETYPE (binfo, i));
}
- /* Should we use something besides CLASSTYPE_VFIELDS? */
- if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+
+ 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);
- 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;
+ return NULL_TREE;
}
/* Set CLASSTYPE_PURE_VIRTUALS for TYPE. */
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);
-
+ /* 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;
-
- virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
+ 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);
- 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