diff options
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/class.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/vthunk1.C | 45 |
4 files changed, 59 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b1f52f3..ed40395 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2001-07-31 Nathan Sidwell <nathan@codesourcery.com> + PR c++/3631 + * class.c (update_vtable_entry_for_fn): The fixed adjustment + of a virtual thunk should be from declaring base. + +2001-07-31 Nathan Sidwell <nathan@codesourcery.com> + * class.c (dfs_ctor_vtable_bases_queue_p): Always walk into the shared virtual base, so preserving inheritance graph order. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f4aae8e..42c03713 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2563,10 +2563,10 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) (or one of its primary bases, which are at the same offset). */ if (virtual_base) - /* The `this' pointer needs to be adjusted to the nearest virtual - base. */ + /* The `this' pointer needs to be adjusted from the declaration to + the nearest virtual base. */ delta = size_diffop (BINFO_OFFSET (virtual_base), - BINFO_OFFSET (binfo)); + BINFO_OFFSET (first_defn)); else { /* The `this' pointer needs to be adjusted from pointing to @@ -2580,7 +2580,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) /* We'll need a thunk. But if we have a (perhaps formerly) primary virtual base, we have a vcall slot for this function, so we can use it rather than create a non-virtual thunk. */ - + b = get_primary_binfo (first_defn); for (; b; b = get_primary_binfo (b)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c8670e..67650f0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2001-07-31 Nathan Sidwell <nathan@codesourcery.com> + * g++.dg/abi/vthunk1.C: New test. + +2001-07-31 Nathan Sidwell <nathan@codesourcery.com> + * g++.dg/abi/vbase8-22.C: New test. 2001-07-31 Neil Booth <neil@cat.daikokuya.demon.co.uk> diff --git a/gcc/testsuite/g++.dg/abi/vthunk1.C b/gcc/testsuite/g++.dg/abi/vthunk1.C new file mode 100644 index 0000000..73a0b13 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/vthunk1.C @@ -0,0 +1,45 @@ +// { dg-do link } + +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 29 Jul 2001 <nathan@codesourcery.com> + +// Origin snyder@fnal.gov +// Bug 3631. We mis-calculated the non-virtual part of a virtual +// thunk. Leading to a link failure, in this case. + +struct A { virtual ~A () {} }; + +struct B : virtual public A +{ + virtual void destroy() {} +}; + +class C : virtual public B {}; +class D : virtual public C {}; +class E : public virtual A {}; + +struct F : virtual public B, virtual public E +{ + virtual void destroy() = 0; +}; + +struct G : public virtual F +{ + virtual void destroy() {} +}; + +class H : virtual public C, virtual public F {}; +class I : virtual public D, virtual public H {}; +class J : public virtual G, public virtual H {}; + +class K : public virtual I, public virtual J +{ + public: + virtual ~K(); +}; +K::~K() {} + +int main () +{ + return 0; +} |