aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/method.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/method.c')
-rw-r--r--gcc/cp/method.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 5277004..c6651e8 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -107,6 +107,8 @@ make_thunk (tree function, bool this_adjusting,
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
/* We can have this thunks to covariant thunks, but not vice versa. */
my_friendly_assert (!DECL_THIS_THUNK_P (function), 20021127);
+ my_friendly_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting,
+ 20031123);
/* Scale the VIRTUAL_OFFSET to be in terms of bytes. */
if (this_adjusting && virtual_offset)
@@ -140,6 +142,8 @@ make_thunk (tree function, bool this_adjusting,
thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
cxx_dup_lang_specific_decl (thunk);
+ DECL_THUNKS (thunk) = NULL_TREE;
+
DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
TREE_READONLY (thunk) = TREE_READONLY (function);
TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
@@ -171,6 +175,7 @@ make_thunk (tree function, bool this_adjusting,
DECL_DECLARED_INLINE_P (thunk) = 0;
/* Nor has it been deferred. */
DECL_DEFERRED_FN (thunk) = 0;
+
/* Add it to the list of thunks associated with FUNCTION. */
TREE_CHAIN (thunk) = DECL_THUNKS (function);
DECL_THUNKS (function) = thunk;
@@ -193,6 +198,27 @@ finish_thunk (tree thunk)
function = THUNK_TARGET (thunk);
name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
fixed_offset, virtual_offset);
+
+ /* We can end up with declarations of (logically) different
+ covariant thunks, that do identical adjustments. The two thunks
+ will be adjusting between within different hierarchies, which
+ happen to have the same layout. We must nullify one of them to
+ refer to the other. */
+ if (DECL_RESULT_THUNK_P (thunk))
+ {
+ tree cov_probe;
+
+ for (cov_probe = DECL_THUNKS (function);
+ cov_probe; cov_probe = TREE_CHAIN (cov_probe))
+ if (DECL_NAME (cov_probe) == name)
+ {
+ my_friendly_assert (!DECL_THUNKS (thunk), 20031023);
+ THUNK_ALIAS (thunk) = (THUNK_ALIAS_P (cov_probe)
+ ? THUNK_ALIAS (cov_probe) : cov_probe);
+ break;
+ }
+ }
+
DECL_NAME (thunk) = name;
SET_DECL_ASSEMBLER_NAME (thunk, name);
}
@@ -307,6 +333,10 @@ use_thunk (tree thunk_fndecl, bool emit_p)
/* We should have called finish_thunk to give it a name. */
my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127);
+ /* We should never be using an alias, always refer to the
+ aliased thunk. */
+ my_friendly_assert (!THUNK_ALIAS_P (thunk_fndecl), 20031023);
+
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;