summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2001-04-12 07:44:48 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2001-04-12 07:44:48 +0000
commita201f10a506699835bda97b35aa0adb7b94880f8 (patch)
tree66c0685dcdf9b9573500425894dace9e9db6f15d /gcc
parentf74d2b776f9017c404f76c854a06661bc7183608 (diff)
downloadgcc-a201f10a506699835bda97b35aa0adb7b94880f8.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41295 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/class.c55
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/crash1.C21
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/primary3.C14
5 files changed, 86 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1066de11c43..634c8cf0675 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
2001-04-12 Nathan Sidwell <nathan@codesourcery.com>
+ * 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 <nathan@codesourcery.com>
+
* method.c (make_thunk): Clear DECL_CLONED_FUNCTION.
2001-04-11 Mark Mitchell <mark@codesourcery.com>
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,4 +1,9 @@
2001-04-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ * 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 <nathan@codesourcery.com>
* 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 <nathan@codesourcery.com>
+
+// 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 <void *> (apc) != static_cast <void *> (b1pc))
return 1;
- if (static_cast <void *> (apd) != static_cast <void *> (b1pd))
+ if (static_cast <void *> (&c) != static_cast <void *> (b2pc))
return 2;
- if (static_cast <void *> (apd) != static_cast <void *> (&d))
+ if (static_cast <void *> (b1pc) == static_cast <void *> (b2pc))
return 3;
+
+ if (static_cast <void *> (apd) != static_cast <void *> (b1pd))
+ return 11;
+ if (static_cast <void *> (b2pd) != static_cast <void *> (&d))
+ return 12;
+ if (static_cast <void *> (b2pd) != static_cast <void *> (cpd))
+ return 13;
+ if (static_cast <void *> (b1pd) == static_cast <void *> (b2pd))
+ return 14;
#endif
return 0;
}