From: Nathan Sidwell Date: Tue, 12 Jun 2001 08:47:48 +0000 (+0000) Subject: re PR c++/3089 (ICE in dfs_accumulate_vtbl_inits) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7bdcf888aaa78808dc2dd4e16e70458244a607be;p=platform%2Fupstream%2Fgcc.git re PR c++/3089 (ICE in dfs_accumulate_vtbl_inits) cp: PR c++/3089 * class.c (dfs_accumulate_vtbl_inits): Always walk down the hierarchy looking for primary bases for a ctor vtable. Recursively call oneself, if we meet our primary via this route and haven't met it yet via inheritance graph order. testsuite: * g++.old-deja/g++.abi/vbase4.C: New test. From-SVN: r43248 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8d84da6..577038e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2001-06-12 Nathan Sidwell + + PR c++/3089 + * class.c (dfs_accumulate_vtbl_inits): Always walk down the + hierarchy looking for primary bases for a ctor + vtable. Recursively call oneself, if we meet our primary via + this route and haven't met it yet via inheritance graph order. + 2001-06-11 Mark Mitchell * lang-options.h: Emit documentation for -fno-honor-std, not diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 499053c..a0cd2ce 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -7409,7 +7409,7 @@ build_ctor_vtbl_group (binfo, t) tree id; tree vbase; - /* See if we've already create this construction vtable group. */ + /* See if we've already created this construction vtable group. */ id = mangle_ctor_vtbl_for_type (t, binfo); if (IDENTIFIER_GLOBAL_VALUE (id)) return; @@ -7525,91 +7525,118 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l) tree vtbl = NULL_TREE; int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); - if (ctor_vtbl_p - && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo)) + if (ctor_vtbl_p) { - /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary - virtual base. If it is not the same primary in the hierarchy of T, - we'll need to generate a ctor vtable for it, to place at its - location in T. If it is the same primary, we still need a VTT - entry for the vtable, but it should point to the ctor vtable for the - base it is a primary for within the sub-hierarchy of RTTI_BINFO. - - There are three possible cases: - - 1) We are in the same place. - 2) We are a primary base within a lost primary virtual base of - RTTI_BINFO. - 3) We are not primary to anything else in RTTI_BINFO. */ - - tree primary = NULL_TREE; - if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo), - size_diffop (BINFO_OFFSET (binfo), - BINFO_OFFSET (rtti_binfo)))) + tree primary = binfo; + tree orig_primary = orig_binfo; + + if (TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo)) { - /* Case 1: We're in the same place relative to RTTI_BINFO as we - were in the complete type, so we are primary either to - RTTI_BINFO or one of its secondary bases. */ - - tree b = BINFO_PRIMARY_BASE_OF (binfo); - - /* Walk down our until we either find the last primary base or - rtti_binfo. */ - for (; b; b = BINFO_PRIMARY_BASE_OF (b)) + /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a + primary virtual base. If it is not the same primary in + the hierarchy of T, we'll need to generate a ctor vtable + for it, to place at its location in T. If it is the same + primary, we still need a VTT entry for the vtable, but it + should point to the ctor vtable for the base it is a + primary for within the sub-hierarchy of RTTI_BINFO. + + There are three possible cases: + + 1) We are in the same place. + 2) We are a primary base within a lost primary virtual base of + RTTI_BINFO. + 3) We are not primary to anything else in RTTI_BINFO. */ + + if (tree_int_cst_equal (BINFO_OFFSET (orig_binfo), + size_diffop (BINFO_OFFSET (binfo), + BINFO_OFFSET (rtti_binfo)))) { - primary = b; - if (b == rtti_binfo) - break; - } - } - else - { - /* Case 2 or 3: We're not in the same place. We might still be - primary to something within a lost primary virtual base of - RTTI_BINFO. */ - - tree b = BINFO_PRIMARY_BASE_OF (binfo); - tree last; + /* Case 1: We're in the same place relative to + RTTI_BINFO as we were in the complete type, so we are + primary either to RTTI_BINFO or one of its secondary + bases. */ + + /* Walk down our until we either find the last + primary base or rtti_binfo. */ + tree b = BINFO_PRIMARY_BASE_OF (binfo); - /* First, look through the bases we are primary to for a virtual - base. */ - for (; b; b = BINFO_PRIMARY_BASE_OF (b)) + for (; b; b = BINFO_PRIMARY_BASE_OF (b)) + { + primary = b; + orig_primary = BINFO_PRIMARY_BASE_OF (orig_primary); + if (b == rtti_binfo) + break; + } + } + else { - last = b; - if (TREE_VIA_VIRTUAL (b)) - break; + /* Case 2 or 3: We're not in the same place. We might + still be primary to something within a lost primary + virtual base of RTTI_BINFO. */ + tree b; + tree last, orig_last; + + /* First, look through the bases we are primary to for a + virtual base. */ + for (b = BINFO_PRIMARY_BASE_OF (binfo), orig_last = orig_binfo; + b; + b = BINFO_PRIMARY_BASE_OF (b)) + { + last = b; + if (orig_last) + orig_last = BINFO_PRIMARY_BASE_OF (orig_last); + if (TREE_VIA_VIRTUAL (b)) + break; + } + /* If we run out of primary links, keep looking down our + inheritance chain; we might be an indirect primary of + a virtual base. */ + if (b == NULL_TREE) + for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b)) + if (TREE_VIA_VIRTUAL (b)) + break; + + /* If we found a virtual base B and it is a base of + RTTI_BINFO, we share our vtable with LAST, i.e. the + derived-most base within B of which we are a primary. + Otherwise, we get our own. */ + if (b && binfo_for_vbase (BINFO_TYPE (b), + BINFO_TYPE (rtti_binfo))) + { + my_friendly_assert (orig_last, 20010611); + primary = last; + orig_primary = orig_last; + } } - /* If we run out of primary links, keep looking down our - inheritance chain; we might be an indirect primary of a - virtual base. */ - if (b == NULL_TREE) - for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b)) - if (TREE_VIA_VIRTUAL (b)) - break; - - /* If we found a virtual base B and it is a base of RTTI_BINFO, we - share our vtable with LAST, i.e. the derived-most base within - B of which we are a primary. Otherwise, we get our own. */ - if (b && binfo_for_vbase (BINFO_TYPE (b), - BINFO_TYPE (rtti_binfo))) - primary = last; } - - if (primary) + + vtbl = BINFO_VTABLE (primary); + if (vtbl && TREE_CODE (vtbl) == TREE_LIST + && TREE_PURPOSE (vtbl) == rtti_binfo) { - vtbl = BINFO_VTABLE (primary); - /* If we haven't already been here for our primary derivation, - all bets are off. Especially for case 2 above, we need - the derived vtable to have been generated. */ - my_friendly_assert (TREE_CODE (vtbl) == TREE_LIST - && TREE_PURPOSE (vtbl) == rtti_binfo, - 20010126); vtbl = TREE_VALUE (vtbl); + if (primary == binfo) + /* We created this vtable because we met its primary base + earlier in the inheritance graph walk of + RTTI_BINFO. */ + return inits; } + else if (primary != binfo) + { + /* We're the primary of some binfo that we've not yet + met in the inheritance graph walk of RTTI_BINFO. We + must create that vtable now. */ + inits = dfs_accumulate_vtbl_inits (primary, orig_primary, + rtti_binfo, t, l); + vtbl = BINFO_VTABLE (primary); + vtbl = TREE_VALUE (vtbl); + } + else + vtbl = NULL; } else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo))) return inits; - + if (!vtbl) { tree index; @@ -7635,19 +7662,16 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l) TREE_CONSTANT (vtbl) = 1; } - if (!ctor_vtbl_p) - { - /* For an ordinary vtable, set BINFO_VTABLE. */ - if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo)) - inits = NULL_TREE; - else - BINFO_VTABLE (binfo) = vtbl; - } - else + if (ctor_vtbl_p) /* For a construction vtable, we can't overwrite BINFO_VTABLE. So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will straighten this out. */ BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo)); + else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo)) + inits = NULL_TREE; + else + /* For an ordinary vtable, set BINFO_VTABLE. */ + BINFO_VTABLE (binfo) = vtbl; return inits; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index be457a8..a4dfba0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-06-12 Nathan Sidwell + + * g++.old-deja/g++.abi/vbase4.C: New test. + 2001-06-11 Stephane Carrez * gcc.c-torture/execute/920501-8.x: New file, sprintf() does not diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C b/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C new file mode 100644 index 0000000..116d79b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vbase4.C @@ -0,0 +1,165 @@ +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 9 Jun 2001 + +// Bug 3089. We ICE'd in construction vtables. + +int failed; + +void fail (int val) +{ + if (!failed) + failed = val; +} + +struct A +{ + virtual ~A(); + A (); + virtual void check (void *whole, void *base); +}; + +A::A () +{ + check (this, this); +} +A::~A () +{ + check (this, this); +} + +void A::check (void *whole, void *base) +{ + if (dynamic_cast (this) != whole) + fail (1); + else if (this != base) + fail (2); +} + +struct B +{ + virtual ~B (); + B (); + virtual void check (void *whole, void *base); +}; + +B::B () +{ + check (this, this); +} +B::~B () +{ + check (this, this); +} +void B::check (void *whole, void *base) +{ + if (dynamic_cast (this) != whole) + fail (3); + else if (this != base) + fail (4); +} + +struct C : virtual public B, virtual public A +{ + virtual ~C (); + C (); + virtual void check (void *whole, void *base); +}; +C::C () +{ + check (this, this); +} +C::~C () +{ + check (this, this); +} +void C::check (void *whole, void *base) +{ + if (dynamic_cast (this) != whole) + fail (5); + else if (this != base) + fail (6); + A::check (whole, static_cast (this)); + B::check (whole, static_cast (this)); +} + +struct D : virtual public A +{ + virtual ~D (); + D (); + virtual void check (void *whole, void *base); +}; +D::D () +{ + check (this, this); +} +D::~D () +{ + check (this, this); +} +void D::check (void *whole, void *base) +{ + if (dynamic_cast (this) != whole) + fail (5); + else if (this != base) + fail (6); + A::check (whole, static_cast (this)); +} + +struct E : virtual public C, virtual public D +{ + virtual ~E (); + E (); + virtual void check (void *whole, void *base); +}; +E::E () +{ + check (this, this); +} +E::~E () +{ + check (this, this); +} +void E::check (void *whole, void *base) +{ + if (dynamic_cast (this) != whole) + fail (5); + else if (this != base) + fail (6); + C::check (whole, static_cast (this)); + D::check (whole, static_cast (this)); +} + +struct F : virtual public E +{ + virtual ~F (); + F (); + virtual void check (void *whole, void *base); +}; +F::F () +{ + check (this, this); +} +F::~F () +{ + check (this, this); +} +void F::check (void *whole, void *base) +{ + if (dynamic_cast (this) != whole) + fail (5); + else if (this != base) + fail (6); + E::check (whole, static_cast (this)); +} + +int main () +{ + A a; + B b; + C c; + D d; + E e; + F f; + + return failed; +}