aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/method.c59
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/abi/covariant2.C32
4 files changed, 93 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5cad5c0..0e90958 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2003-12-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/12881
+ * method.c (make_thunk): Deal with thunk aliases when searching
+ for a thunk. Robustify assertion.
+
2003-12-11 Nathan Sidwell <nathan@codesourcery.com>
* mangle.c (conv_type_names): Holds IDENTIFIER_NODEs only.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 61aebd4..a08ae6b 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 358b093..eee3f58 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-12-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/12881
+ * g++.dg/abi/covariant2.C: New.
+
2003-12-12 Neil Booth <neil@daikokuya.co.uk>
* 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 0000000..233c55a
--- /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 <nathan@codesourcery.com>
+// Origin: Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+
+// 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 {};
+