diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5cad5c009497..0e9095837107 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2003-12-12 Nathan Sidwell + + PR c++/12881 + * method.c (make_thunk): Deal with thunk aliases when searching + for a thunk. Robustify assertion. + 2003-12-11 Nathan Sidwell * mangle.c (conv_type_names): Holds IDENTIFIER_NODEs only. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 61aebd4bbd4e..a08ae6bab913 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -124,20 +124,61 @@ make_thunk (tree function, bool this_adjusting, thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it will be a BINFO. */ for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk)) - if (DECL_THIS_THUNK_P (thunk) == this_adjusting - && THUNK_FIXED_OFFSET (thunk) == d - && (this_adjusting - ? (!THUNK_VIRTUAL_OFFSET (thunk) == !virtual_offset - && (!virtual_offset - || tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk), - virtual_offset))) - : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset)) - return thunk; + { + if (DECL_THIS_THUNK_P (thunk) != this_adjusting + || THUNK_FIXED_OFFSET (thunk) != d) + /*not me*/; + else if (this_adjusting) + { + if (!virtual_offset) + { + /* We want a non-virtual covariant thunk. */ + if (!THUNK_VIRTUAL_OFFSET (thunk)) + return thunk; + } + else if (THUNK_VIRTUAL_OFFSET (thunk)) + { + if (tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk), + virtual_offset)) + return thunk; + } + } + else + { + if (!virtual_offset) + { + /* We want a non-virtual covariant thunk. */ + if (!THUNK_VIRTUAL_OFFSET (thunk)) + return thunk; + } + else if (!THUNK_VIRTUAL_OFFSET (thunk)) + /*not me*/; + else if (THUNK_ALIAS_P (thunk)) + { + /* We have already determined the thunks for FUNCTION, + and there is a virtual covariant thunk alias. We + must compare the vbase offsets of the binfo we have + been given, and the binfo of the thunk. */ + tree binfo = THUNK_VIRTUAL_OFFSET (THUNK_ALIAS (thunk)); + + if (tree_int_cst_equal (BINFO_VPTR_FIELD (virtual_offset), + BINFO_VPTR_FIELD (binfo))) + return THUNK_ALIAS (thunk); + } + else if (THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset) + return thunk; + } + } /* All thunks must be created before FUNCTION is actually emitted; the ABI requires that all thunks be emitted together with the function to which they transfer control. */ my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025); + /* Likewise, we can only be adding thunks to a function declared in + the class currently being laid out. */ + my_friendly_assert (TYPE_SIZE (DECL_CONTEXT (function)) + && TYPE_BEING_DEFINED (DECL_CONTEXT (function)), + 20031211); thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 358b09377ded..eee3f585f9b5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-12-12 Nathan Sidwell + + PR c++/12881 + * g++.dg/abi/covariant2.C: New. + 2003-12-12 Neil Booth * testsuite/gcc.dg/cpp/trad/macro.c: New tests. diff --git a/gcc/testsuite/g++.dg/abi/covariant2.C b/gcc/testsuite/g++.dg/abi/covariant2.C new file mode 100644 index 000000000000..233c55aef70f --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/covariant2.C @@ -0,0 +1,32 @@ +// { dg-do compile } + +// Copyright (C) 2003 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 12 Dec 2003 +// Origin: Volker Reichelt + +// PR c++/12881. ICE in thunk generation + +struct c1 {}; + +struct c3 : virtual c1 +{ + virtual c1* f6() {}; + int i; +}; + +struct c6 : virtual c3 { }; + +struct c7 : c3 +{ + virtual c3* f6() {}; +}; + +struct c24 : virtual c7 +{ + virtual c6* f6(); +}; + +c6* c24::f6() { return 0; } + +struct c31 : c24 {}; +