From 7cafdb8bfe700513a2916358303f4f8c28eff4d9 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 5 Jun 2000 20:01:47 +0000 Subject: [PATCH] class.c (indirect_primary_base_p): New function. * class.c (indirect_primary_base_p): New function. (determine_primary_base): Use it. From-SVN: r34412 --- gcc/cp/ChangeLog | 5 +++ gcc/cp/class.c | 85 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ae8756bc363..f0f7e367a05 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2000-06-05 Mark Mitchell + + * class.c (indirect_primary_base_p): New function. + (determine_primary_base): Use it. + 2000-06-05 Nathan Sidwell Update new-abi dynamic cast algorithm. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 8d74b4426d5..77a5b7e6499 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -188,6 +188,7 @@ static void build_vtt PARAMS ((tree)); static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *)); static tree dfs_build_vtt_inits PARAMS ((tree, void *)); static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *)); +static int indirect_primary_base_p PARAMS ((tree, tree)); /* Variables shared between class.c and call.c. */ @@ -1807,6 +1808,35 @@ set_primary_base (t, i, vfuns_p) *vfuns_p = CLASSTYPE_VSIZE (basetype); } +/* Returns true iff BINFO (a direct virtual base of T) is an indirect + primary base. */ + +static int +indirect_primary_base_p (t, binfo) + tree t; + tree binfo; +{ + int i; + + for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i) + { + tree type; + tree b; + + /* Figure out to which type the Ith base corresponds. */ + type = TYPE_BINFO_BASETYPE (t, i); + /* See if any of the primary bases have the same type as BINFO. */ + for (b = TYPE_BINFO (type); b; b = TREE_CHAIN (b)) + /* If this base is primary, and has the same type as BINFO, + then BINFO is an indirect primary base. */ + if (BINFO_PRIMARY_MARKED_P (b) + && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo))) + return 1; + } + + return 0; +} + /* Determine the primary class for T. */ static void @@ -1874,19 +1904,50 @@ determine_primary_base (t, vfuns_p) class as the primary base class if no non-virtual polymorphic base can be found. */ if (flag_new_abi && !CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - for (i = 0; i < n_baseclasses; ++i) - { - tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i); - tree basetype = BINFO_TYPE (base_binfo); + { + /* If not -1, this is the index in TYPE_BINFO_BASETYPEs of the + best primary base candidate we have found so far. */ + int candidate = -1; - if (TREE_VIA_VIRTUAL (base_binfo) - && CLASSTYPE_NEARLY_EMPTY_P (basetype)) - { - set_primary_base (t, i, vfuns_p); - CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype)); - break; - } - } + /* Loop over the baseclasses. */ + for (i = 0; i < n_baseclasses; ++i) + { + tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i); + tree basetype = BINFO_TYPE (base_binfo); + + if (TREE_VIA_VIRTUAL (base_binfo) + && CLASSTYPE_NEARLY_EMPTY_P (basetype)) + { + int indirect_primary_p; + + /* Figure out whether or not this base is an indirect + primary base. */ + indirect_primary_p = indirect_primary_base_p (t, base_binfo); + + /* If this is not an indirect primary base, then it's + definitely our primary base. */ + if (!indirect_primary_p) + { + candidate = i; + break; + } + /* If this was an indirect primary base, it's still our + primary base -- unless there's another nearly-empty + virtual base that isn't an indirect primary base. */ + else if (candidate == -1) + candidate = i; + } + } + + /* If we've got a primary base, use it. */ + if (candidate != -1) + { + set_primary_base (t, candidate, vfuns_p); + CLASSTYPE_VFIELDS (t) + = copy_list (CLASSTYPE_VFIELDS (TYPE_BINFO_BASETYPE (t, + candidate))); + } + } /* Mark the primary base classes at this point. */ mark_primary_bases (t);