From 0fb3018cd802d7aae15888ba68f51ad9a83cb71d Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 12 Apr 2001 07:44:48 +0000 Subject: [PATCH] class.c (dfs_unshared_virtual_bases): New function. cp: * class.c (dfs_unshared_virtual_bases): New function. (mark_primary_bases): Call it. (check_bases): Ignore virtual bases when determining nearly-emptiness. testsuite: * g++.old-deja/g++.abi/primary3.C (main): Correct expected layout. * g++.old-deja/g++.abi/crash1.C: New test. From-SVN: r41295 --- gcc/cp/ChangeLog | 7 +++ gcc/cp/class.c | 55 ++++++++++++++----- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.old-deja/g++.abi/crash1.C | 21 +++++++ gcc/testsuite/g++.old-deja/g++.abi/primary3.C | 14 ++++- 5 files changed, 86 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/crash1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1066de11c43..634c8cf0675 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2001-04-12 Nathan Sidwell + + * class.c (dfs_unshared_virtual_bases): New function. + (mark_primary_bases): Call it. + (check_bases): Ignore virtual bases when determining + nearly-emptiness. + 2001-04-12 Nathan Sidwell * method.c (make_thunk): Clear DECL_CLONED_FUNCTION. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 406843e0c9b..290dc214da4 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -190,6 +190,7 @@ static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, vtbl_init_data *)); static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree)); static void force_canonical_binfo PARAMS ((tree, tree, tree, tree)); +static tree dfs_unshared_virtual_bases PARAMS ((tree, void *)); static void mark_primary_bases PARAMS ((tree)); static tree mark_primary_virtual_base PARAMS ((tree, tree, tree)); static void clone_constructors_and_destructors PARAMS ((tree)); @@ -1596,12 +1597,12 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p, { int n_baseclasses; int i; - int seen_nearly_empty_base_p; + int seen_non_virtual_nearly_empty_base_p; tree binfos; binfos = TYPE_BINFO_BASETYPES (t); n_baseclasses = CLASSTYPE_N_BASECLASSES (t); - seen_nearly_empty_base_p = 0; + seen_non_virtual_nearly_empty_base_p = 0; /* An aggregate cannot have baseclasses. */ CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0); @@ -1662,19 +1663,23 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p, basetype); } - /* If the base class is not empty or nearly empty, then this - class cannot be nearly empty. */ - if (!CLASSTYPE_NEARLY_EMPTY_P (basetype) && !is_empty_class (basetype)) - CLASSTYPE_NEARLY_EMPTY_P (t) = 0; - /* And if there is more than one nearly empty base, then the - derived class is not nearly empty either. */ - else if (CLASSTYPE_NEARLY_EMPTY_P (basetype) - && seen_nearly_empty_base_p) - CLASSTYPE_NEARLY_EMPTY_P (t) = 0; - /* If this is the first nearly empty base class, then remember - that we saw it. */ + if (TREE_VIA_VIRTUAL (base_binfo)) + /* A virtual base does not effect nearly emptiness. */ + ; else if (CLASSTYPE_NEARLY_EMPTY_P (basetype)) - seen_nearly_empty_base_p = 1; + { + if (seen_non_virtual_nearly_empty_base_p) + /* And if there is more than one nearly empty base, then the + derived class is not nearly empty either. */ + CLASSTYPE_NEARLY_EMPTY_P (t) = 0; + else + /* Remember we've seen one. */ + seen_non_virtual_nearly_empty_base_p = 1; + } + else if (!is_empty_class (basetype)) + /* If the base class is not empty or nearly empty, then this + class cannot be nearly empty. */ + CLASSTYPE_NEARLY_EMPTY_P (t) = 0; /* A lot of properties from the bases also apply to the derived class. */ @@ -1814,6 +1819,23 @@ mark_primary_virtual_base (binfo, base_binfo, type) return base_binfo; } +/* If BINFO is an unmarked virtual binfo for a class with a primary + base, then BINFO has no primary base in this graph. Called from + mark_primary_bases. */ + +static tree dfs_unshared_virtual_bases (binfo, data) + tree binfo; + void *data; +{ + if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo) + && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))) + BINFO_LOST_PRIMARY_P (binfo) = 1; + + CLEAR_BINFO_MARKED (binfo); + + return NULL; +} + /* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy dominated by TYPE that are primary bases. */ @@ -1839,7 +1861,12 @@ mark_primary_bases (type) if (base_binfo) BINFO_PRIMARY_BASE_OF (base_binfo) = binfo; + SET_BINFO_MARKED (binfo); } + /* There could remain unshared virtual bases which were not visited + in the inheritance graph walk. These bases will have lost their + primary base (should they have one). We must now find them. */ + dfs_walk (TYPE_BINFO (type), dfs_unshared_virtual_bases, NULL, NULL); } /* Make the BINFO the primary base of T. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 36c2e53cbf8..ea72f127ae1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2001-04-12 Nathan Sidwell + + * g++.old-deja/g++.abi/primary3.C (main): Correct expected layout. + * g++.old-deja/g++.abi/crash1.C: New test. + 2001-04-12 Nathan Sidwell * g++.old-deja/g++.other/crash40.C: New test. diff --git a/gcc/testsuite/g++.old-deja/g++.abi/crash1.C b/gcc/testsuite/g++.old-deja/g++.abi/crash1.C new file mode 100644 index 00000000000..8526818c713 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/crash1.C @@ -0,0 +1,21 @@ +// Build don't link: +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 11 Apr 2001 + +// Bug 1944. We failed to calculate nearly emptiness properly, and +// lost primary too. + +struct A1 {}; +struct A2 {}; + +struct B1 : virtual A1 {}; +struct B2 : virtual A2 {}; + +struct C1 : virtual B2 {}; +struct C2 : virtual B2 {}; + +struct D1 : virtual C1, virtual C2 {}; +struct D2 : virtual C2, virtual B1 {}; + +struct E : virtual D1, virtual D2 {}; diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary3.C b/gcc/testsuite/g++.old-deja/g++.abi/primary3.C index ef245ef789e..fbeb2b70b30 100644 --- a/gcc/testsuite/g++.old-deja/g++.abi/primary3.C +++ b/gcc/testsuite/g++.old-deja/g++.abi/primary3.C @@ -21,14 +21,24 @@ int main () A *apd = &d; B1 *b1pd = &d; B2 *b2pd = &d; + C *cpd = &d; #if __GXX_ABI_VERSION >= 100 if (static_cast (apc) != static_cast (b1pc)) return 1; - if (static_cast (apd) != static_cast (b1pd)) + if (static_cast (&c) != static_cast (b2pc)) return 2; - if (static_cast (apd) != static_cast (&d)) + if (static_cast (b1pc) == static_cast (b2pc)) return 3; + + if (static_cast (apd) != static_cast (b1pd)) + return 11; + if (static_cast (b2pd) != static_cast (&d)) + return 12; + if (static_cast (b2pd) != static_cast (cpd)) + return 13; + if (static_cast (b1pd) == static_cast (b2pd)) + return 14; #endif return 0; } -- 2.30.2