From 994792bfe4019ebcbd878a02e8cbb890f2eebded Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 9 May 2005 11:48:11 +0000 Subject: [PATCH] re PR c++/21427 ([3.4/4.0 only] Failure in make_thunk, cp/method.c:145 when compiling with multiply-inherited members) cp: PR c++/21427 Backport 2005-03-01 Nathan Sidwell * class.c (update_vtable_entry_for_fn): Don't crash on invalid covariancy. * cp-tree.h (THUNK_TARGET): Expand comment. * method.c (use_thunk): Make sure we also use the target, if that is a thunk. Backport 2005-02-11 Nathan Sidwell * class.c (update_vtable_entry_for_fn): Walk the covariant's binfo chain rather than using lookup_base. testsuite: PR c++/21427 * g++.dg/inherit/covariant13.C: New. Backport 2005-03-01 Nathan Sidwell * g++.dg/inherit/covariant12.C: New. From-SVN: r99430 --- gcc/cp/ChangeLog | 15 ++++++ gcc/cp/class.c | 62 +++++++++++++++------- gcc/cp/cp-tree.h | 3 +- gcc/cp/method.c | 4 ++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/g++.dg/inherit/covariant13.C | 25 +++++++++ 6 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.dg/inherit/covariant13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bd59b7acfe17..9f5dbf286bbf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2005-05-08 Nathan Sidwell + + PR c++/21427 + Backport 2005-03-01 Nathan Sidwell + * class.c (update_vtable_entry_for_fn): Don't crash on invalid + covariancy. + + * cp-tree.h (THUNK_TARGET): Expand comment. + * method.c (use_thunk): Make sure we also use the target, if that + is a thunk. + + Backport 2005-02-11 Nathan Sidwell + * class.c (update_vtable_entry_for_fn): Walk the covariant's binfo + chain rather than using lookup_base. + 2005-05-04 Mark Mitchell Backport: diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a7093b174c3e..09daf118a80f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2116,6 +2116,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, also be converting to the return type of FN, we have to combine the two conversions here. */ tree fixed_offset, virtual_offset; + + over_return = TREE_TYPE (over_return); + base_return = TREE_TYPE (base_return); if (DECL_THUNK_P (fn)) { @@ -2133,32 +2136,51 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, virtual_offset = TREE_VALUE (purpose_member (BINFO_TYPE (virtual_offset), - CLASSTYPE_VBASECLASSES (TREE_TYPE (over_return)))); - else if (!same_type_p (TREE_TYPE (over_return), - TREE_TYPE (base_return))) + CLASSTYPE_VBASECLASSES (over_return))); + else if (!same_type_ignoring_top_level_qualifiers_p + (over_return, base_return)) { - /* There was no existing virtual thunk (which takes - precedence). */ - tree thunk_binfo; - base_kind kind; + /* There was no existing virtual thunk (which takes + precedence). So find the binfo of the base function's + return type within the overriding function's return type. + We cannot call lookup base here, because we're inside a + dfs_walk, and will therefore clobber the BINFO_MARKED + flags. Fortunately we know the covariancy is valid (it + has already been checked), so we can just iterate along + the binfos, which have been chained in inheritance graph + order. Of course it is lame that we have to repeat the + search here anyway -- we should really be caching pieces + of the vtable and avoiding this repeated work. */ + tree thunk_binfo, base_binfo; + + /* Find the base binfo within the overriding function's + return type. We will always find a thunk_binfo, except + when the covariancy is invalid (which we will have + already diagnosed). */ + for (base_binfo = TYPE_BINFO (base_return), + thunk_binfo = TYPE_BINFO (over_return); + thunk_binfo; + thunk_binfo = TREE_CHAIN (thunk_binfo)) + if (same_type_p (BINFO_TYPE (thunk_binfo), + BINFO_TYPE (base_binfo))) + break; - thunk_binfo = lookup_base (TREE_TYPE (over_return), - TREE_TYPE (base_return), - ba_check | ba_quiet, &kind); - - if (thunk_binfo && (kind == bk_via_virtual - || !BINFO_OFFSET_ZEROP (thunk_binfo))) + /* See if virtual inheritance is involved. */ + for (virtual_offset = thunk_binfo; + virtual_offset; + virtual_offset = BINFO_INHERITANCE_CHAIN (virtual_offset)) + if (TREE_VIA_VIRTUAL (virtual_offset)) + break; + + if (virtual_offset + || (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo))) { tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo)); - if (kind == bk_via_virtual) + if (virtual_offset) { - /* We convert via virtual base. Find the virtual - base and adjust the fixed offset to be from there. */ - while (!TREE_VIA_VIRTUAL (thunk_binfo)) - thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo); - - virtual_offset = thunk_binfo; + /* We convert via virtual base. Adjust the fixed + offset to be from there. */ offset = size_diffop (offset, convert (ssizetype, BINFO_OFFSET (virtual_offset))); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9bf76bc008ff..ed33f3271d79 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2917,7 +2917,8 @@ struct lang_decl GTY(()) #define THUNK_ALIAS(DECL) \ (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.u.thunk_alias) -/* For thunk NODE, this is the FUNCTION_DECL thunked to. */ +/* For thunk NODE, this is the FUNCTION_DECL thunked to. It is + possible for the target to be a thunk too. */ #define THUNK_TARGET(NODE) \ (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 42e50926f267..ef69c37fe4d7 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -357,6 +357,10 @@ use_thunk (tree thunk_fndecl, bool emit_p) There's no need to process this thunk again. */ return; + if (DECL_THUNK_P (function)) + /* The target is itself a thunk, process it now. */ + use_thunk (function, emit_p); + /* Thunks are always addressable; they only appear in vtables. */ TREE_ADDRESSABLE (thunk_fndecl) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6be57523a1b7..1ee2e6f36387 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2005-05-08 Nathan Sidwell + + PR c++/21427 + * g++.dg/inherit/covariant13.C: New. + Backport 2005-03-01 Nathan Sidwell + * g++.dg/inherit/covariant12.C: New. + 2005-05-04 Mark Mitchell Backport: diff --git a/gcc/testsuite/g++.dg/inherit/covariant13.C b/gcc/testsuite/g++.dg/inherit/covariant13.C new file mode 100644 index 000000000000..af60840c818c --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/covariant13.C @@ -0,0 +1,25 @@ +// Copyright (C) 2004 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 8 May 2005 + +// Origin:Andrew Pinski: pinskia@gcc.gnu.org +// PR 21427: ICE on valid + +struct B1 { + public: + virtual void foo(); +}; + +struct B2 { + public: + virtual B2 & bar() = 0; +}; + +struct I : public B1, B2 { + public: + virtual ~I(); + virtual I & bar(); +}; + +struct D : public I { + virtual ~D(); +}; -- 2.47.2