Commit 07fa4878 by Nathan Sidwell Committed by Nathan Sidwell

cp-tree.h (THUNK_TARGET): New macro.

cp:
	* cp-tree.h (THUNK_TARGET): New macro.
	(THUNK_VIRTUAL_OFFSET): For result thunks it is always a binfo.
	(finish_thunk): Remove offset parms.
	* class.c (find_final_overrider): Look through thunks.
	(get_vcall_index): Use THUNK_TARGET.
	(update_vtable_entry_for_fn): Look through thunks. Set covariant
	fixed offset here. Adjust finish_thunk call.
	(build_vtbl_initializer): Adjust finish_thunk calls.
	* mangle.c (mangle_call_offset): Remove superfluous if.
	(mangle_thunk): Adjust.
	* method.c (make_thunk): Adjust.
	(finish_thunk): Adjust.
	(thunk_adjust): Remove assert.
	(use_thunk): Use THUNK_TARGET
	* dump1.c (cp_dump_tree): Adjust thunk dumping.
testsuite:
	* g++.dg/inherit/covariant5.C: New test.
	* g++.dg/inherit/covariant6.C: New test.
	* g++.dg/inherit/covariant7.C: New test.

From-SVN: r60628
parent 5a5cccaa
......@@ -2299,6 +2299,9 @@ find_final_overrider (derived, binfo, fn)
The solution is to look at all paths to BINFO. If we find
different overriders along any two, then there is a problem. */
if (DECL_THUNK_P (fn))
fn = THUNK_TARGET (fn);
ffod.fn = fn;
ffod.declaring_base = binfo;
ffod.most_derived_type = BINFO_TYPE (derived);
......@@ -2328,8 +2331,8 @@ get_vcall_index (tree fn, tree type)
{
tree v;
if (DECL_RESULT_THUNK_P (fn))
fn = TREE_OPERAND (DECL_INITIAL (fn), 0);
if (DECL_THUNK_P (fn))
fn = THUNK_TARGET (fn);
for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
......@@ -2360,11 +2363,15 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
tree first_defn;
bool lost = false;
if (DECL_THUNK_P (fn))
fn = THUNK_TARGET (fn);
/* Find the nearest primary base (possibly binfo itself) which defines
this function; this is the class the caller will convert to when
calling FN through BINFO. */
for (b = binfo; ; b = get_primary_binfo (b))
{
my_friendly_assert (b, 20021227);
if (look_for_overrides_here (BINFO_TYPE (b), fn))
break;
......@@ -2408,10 +2415,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
/* If the covariant type is within the class hierarchy
we are currently laying out, the vbase index is not
yet known, so we have to remember the virtual base
binfo for the moment. The thunk will be finished
in build_vtbl_initializer, where we'll know the
vtable index of the virtual base. */
virtual_offset = binfo_for_vbase (BINFO_TYPE (binfo), t);
binfo. */
virtual_offset = binfo_for_vbase (BINFO_TYPE (binfo),
TREE_TYPE (over_return));
fixed_offset = size_diffop (fixed_offset,
BINFO_OFFSET (virtual_offset));
}
/* Replace the overriding function with a covariant thunk.
......@@ -2421,7 +2429,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
fixed_offset, virtual_offset);
TREE_PURPOSE (overrider) = thunk;
if (!virtual_offset && !DECL_NAME (thunk))
finish_thunk (thunk, fixed_offset, NULL_TREE);
finish_thunk (thunk);
}
}
}
......@@ -7739,18 +7747,12 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree init = NULL_TREE;
fn = BV_FN (v);
fn_original = (DECL_RESULT_THUNK_P (fn)
? TREE_OPERAND (DECL_INITIAL (fn), 0)
: fn);
/* Finish an unfinished covariant thunk. */
if (DECL_RESULT_THUNK_P (fn) && !DECL_NAME (fn))
fn_original = fn;
if (DECL_THUNK_P (fn))
{
tree binfo = THUNK_VIRTUAL_OFFSET (fn);
tree fixed_offset = size_int (THUNK_FIXED_OFFSET (fn));
tree virtual_offset = BINFO_VPTR_FIELD (binfo);
fixed_offset = size_diffop (fixed_offset, BINFO_OFFSET (binfo));
finish_thunk (fn, fixed_offset, virtual_offset);
if (!DECL_NAME (fn))
finish_thunk (fn);
fn_original = THUNK_TARGET (fn);
}
/* If the only definition of this function signature along our
......@@ -7796,7 +7798,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
{
fn = make_thunk (fn, /*this_adjusting=*/1, delta, vcall_index);
if (!DECL_NAME (fn))
finish_thunk (fn, delta, THUNK_VIRTUAL_OFFSET (fn));
finish_thunk (fn);
}
/* Take the address of the function, considering it to be of an
appropriate generic type. */
......
......@@ -1791,6 +1791,9 @@ struct lang_decl GTY(())
{
struct full_lang_decl
{
/* For a non-thunk function decl, this is a tree list of
friendly classes. For a thunk function decl, it is the
thunked to function decl. */
tree befriending_classes;
/* For a non-virtual FUNCTION_DECL, this is
......@@ -2977,14 +2980,20 @@ struct lang_decl GTY(())
/* An integer indicating how many bytes should be subtracted from the
this or result pointer when this function is called. */
#define THUNK_FIXED_OFFSET(DECL) \
(DECL_LANG_SPECIFIC (DECL)->u.f.fixed_offset)
/* A tree indicating how many bytes should be added to the
vtable for the this or result pointer to find the vcall or vbase
offset. (The vptr is always located at offset zero from the
this or result pointer.) If NULL, then there is no virtual adjust. */
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL))->u.f.fixed_offset)
/* A tree indicating how to perform the virtual adjustment. For a this
adjusting thunk it is the number of bytes to be added to the vtable
to find the vcall offset. For a result adjusting thunk, it is the
binfo of the relevant virtual base. The vptr is always located at
offset zero from the this or result pointer. If NULL, then there
is no virtual adjust. */
#define THUNK_VIRTUAL_OFFSET(DECL) \
(LANG_DECL_U2_CHECK (DECL, 0)->virtual_offset)
(LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset)
/* For thunk NODE, this is the FUNCTION_DECL thunked to. */
#define THUNK_TARGET(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
/* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */
......@@ -3990,7 +3999,7 @@ extern void set_mangled_name_for_decl (tree);
extern tree build_opfncall (enum tree_code, int, tree, tree, tree);
extern tree hack_identifier (tree, tree);
extern tree make_thunk (tree, bool, tree, tree);
extern void finish_thunk (tree, tree, tree);
extern void finish_thunk (tree);
extern void use_thunk (tree, bool);
extern void synthesize_method (tree);
extern tree implicitly_declare_fn (special_function_kind, tree, bool);
......
......@@ -336,13 +336,20 @@ cp_dump_tree (dump_info, t)
}
else
{
tree virt = THUNK_VIRTUAL_OFFSET (t);
dump_string (di, "thunk");
if (DECL_THIS_THUNK_P (t))
dump_string (di, "this adjusting");
else
{
dump_string (di, "result adjusting");
if (virt)
virt = BINFO_VPTR_FIELD (virt);
}
dump_int (di, "fixd", THUNK_FIXED_OFFSET (t));
dump_child ("virt", THUNK_VIRTUAL_OFFSET (t));
if (virt)
dump_int (di, "virt", tree_low_cst (virt, 0));
dump_child ("fn", DECL_INITIAL (t));
}
break;
......
......@@ -2545,10 +2545,7 @@ mangle_call_offset (fixed_offset, virtual_offset)
tree fixed_offset;
tree virtual_offset;
{
if (virtual_offset)
write_char (virtual_offset ? 'v' : 'h');
else
write_char ('h');
/* For either flavor, write the fixed offset. */
write_integer_cst (fixed_offset);
......@@ -2590,24 +2587,27 @@ mangle_thunk (fn_decl, this_adjusting, fixed_offset, virtual_offset)
write_string ("_Z");
write_char ('T');
if (this_adjusting && !DECL_RESULT_THUNK_P (fn_decl))
/* Plain this adjusting thunk. */
mangle_call_offset (fixed_offset, virtual_offset);
else if (!this_adjusting)
if (!this_adjusting)
{
/* Covariant thunk with no this adjustment */
write_char ('c');
mangle_call_offset (integer_zero_node, NULL_TREE);
mangle_call_offset (fixed_offset, virtual_offset);
}
else if (!DECL_THUNK_P (fn_decl))
/* Plain this adjusting thunk. */
mangle_call_offset (fixed_offset, virtual_offset);
else
{
/* This adjusting thunk to covariant thunk. */
write_char ('c');
mangle_call_offset (fixed_offset, virtual_offset);
mangle_call_offset (ssize_int (THUNK_FIXED_OFFSET (fn_decl)),
THUNK_VIRTUAL_OFFSET (fn_decl));
fn_decl = TREE_OPERAND (DECL_INITIAL (fn_decl), 0);
fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn_decl));
virtual_offset = THUNK_VIRTUAL_OFFSET (fn_decl);
if (virtual_offset)
virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
mangle_call_offset (fixed_offset, virtual_offset);
fn_decl = THUNK_TARGET (fn_decl);
}
/* Scoped name. */
......
......@@ -261,8 +261,7 @@ make_thunk (tree function, bool this_adjusting,
/* See if we already have the thunk in question. For this_adjusting
thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
will be a BINFO (because of the organization of the layout
algorithm). */
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
......@@ -281,7 +280,7 @@ 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 (function);
cxx_dup_lang_specific_decl (thunk);
DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
TREE_READONLY (thunk) = TREE_READONLY (function);
TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
......@@ -289,8 +288,8 @@ make_thunk (tree function, bool this_adjusting,
if (flag_weak)
comdat_linkage (thunk);
SET_DECL_THUNK_P (thunk, this_adjusting);
DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function);
THUNK_FIXED_OFFSET (thunk) = tree_low_cst (fixed_offset, 0);
THUNK_TARGET (thunk) = function;
THUNK_FIXED_OFFSET (thunk) = d;
THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
/* The thunk itself is not a constructor or destructor, even if
......@@ -320,20 +319,21 @@ make_thunk (tree function, bool this_adjusting,
return thunk;
}
/* Finish THUNK, a thunk decl. FIXED_OFFSET and VIRTUAL_OFFSET are the
adjustments to apply. */
/* Finish THUNK, a thunk decl. */
void
finish_thunk (tree thunk, tree fixed_offset, tree virtual_offset)
finish_thunk (tree thunk)
{
tree function, name;
tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk));
tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk);
my_friendly_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk), 20021127);
function = TREE_OPERAND (DECL_INITIAL (thunk), 0);
if (virtual_offset && DECL_RESULT_THUNK_P (thunk))
virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
function = THUNK_TARGET (thunk);
name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
fixed_offset, virtual_offset);
THUNK_FIXED_OFFSET (thunk) = tree_low_cst (fixed_offset, 0);
THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
DECL_NAME (thunk) = name;
SET_DECL_ASSEMBLER_NAME (thunk, name);
}
......@@ -358,9 +358,6 @@ thunk_adjust (tree ptr, bool this_adjusting,
{
tree vtable;
/* It shouldn't be a binfo any more. */
my_friendly_assert (TREE_CODE (virtual_offset) == INTEGER_CST, 20021127);
ptr = save_expr (ptr);
/* The vptr is always at offset zero in the object. */
vtable = build1 (NOP_EXPR,
......@@ -392,10 +389,10 @@ thunk_adjust (tree ptr, bool this_adjusting,
void
use_thunk (tree thunk_fndecl, bool emit_p)
{
tree fnaddr;
tree function;
tree virtual_offset;
HOST_WIDE_INT fixed_offset, virtual_value;
bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);
/* We should have called finish_thunk to give it a name. */
my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127);
......@@ -403,8 +400,8 @@ use_thunk (tree thunk_fndecl, bool emit_p)
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
fnaddr = DECL_INITIAL (thunk_fndecl);
if (TREE_CODE (DECL_INITIAL (thunk_fndecl)) != ADDR_EXPR)
function = THUNK_TARGET (thunk_fndecl);
if (DECL_RESULT (thunk_fndecl))
/* We already turned this thunk into an ordinary function.
There's no need to process this thunk again. */
return;
......@@ -414,7 +411,6 @@ use_thunk (tree thunk_fndecl, bool emit_p)
/* Figure out what function is being thunked to. It's referenced in
this translation unit. */
function = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (function) = 1;
mark_used (function);
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (function)) = 1;
......@@ -424,9 +420,15 @@ use_thunk (tree thunk_fndecl, bool emit_p)
fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);
virtual_value = (virtual_offset
? tree_low_cst (virtual_offset, /*pos=*/0) : 0);
my_friendly_assert (!virtual_offset || virtual_value, 20021026);
if (virtual_offset)
{
if (!this_adjusting)
virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
virtual_value = tree_low_cst (virtual_offset, /*pos=*/0);
my_friendly_assert (virtual_value, 20021026);
}
else
virtual_value = 0;
/* And, if we need to emit the thunk, it's used. */
mark_used (thunk_fndecl);
......@@ -447,10 +449,9 @@ use_thunk (tree thunk_fndecl, bool emit_p)
/* The back-end expects DECL_INITIAL to contain a BLOCK, so we
create one. */
DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
= DECL_ARGUMENTS (thunk_fndecl);
BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = DECL_ARGUMENTS (thunk_fndecl);
if (DECL_THIS_THUNK_P (thunk_fndecl)
if (this_adjusting
&& targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
virtual_value, function))
{
......@@ -502,7 +503,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
t = a;
if (DECL_THIS_THUNK_P (thunk_fndecl))
if (this_adjusting)
t = thunk_adjust (t, /*this_adjusting=*/1,
fixed_offset, virtual_offset);
......@@ -512,7 +513,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
t = tree_cons (NULL_TREE, a, t);
t = nreverse (t);
t = build_call (function, t);
if (DECL_RESULT_THUNK_P (thunk_fndecl))
if (!this_adjusting)
t = thunk_adjust (t, /*this_adjusting=*/0,
fixed_offset, virtual_offset);
......
2002-12-30 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/inherit/covariant5.C: New test.
* g++.dg/inherit/covariant6.C: New test.
* g++.dg/inherit/covariant7.C: New test.
2002-12-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/2739
......
// { dg-do compile }
// Copyright (C) 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 27 Dec 2002 <nathan@codesourcery.com>
// We ICE'd
struct c0 {};
struct c1 : virtual c0
{
virtual c0 &f2();
};
struct c3 : c1
{
virtual c1 &f2();
};
c1 &c3::f2()
{
throw 0;
}
struct c4 : virtual c3
{
};
// { dg-do compile }
// Copyright (C) 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 27 Dec 2002 <nathan@codesourcery.com>
// We ICE'd
struct c0 {};
struct c1 : virtual c0
{
virtual c0 &f2();
};
struct c3 : virtual c1
{
virtual c1 &f2();
};
c1 &c3::f2()
{
throw 0;
}
struct c4 : virtual c3
{
};
// { dg-do compile }
// Copyright (C) 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 27 Dec 2002 <nathan@codesourcery.com>
// We ICE'd
struct c0 {};
struct c1 : virtual c0
{
virtual c0 &f2() volatile;
};
struct c2
{
int m;
};
struct c3 : virtual c0, virtual c1, c2
{
virtual c1 &f2() volatile;
};
struct c4 : virtual c3, virtual c0, virtual c1
{
int m;
};
struct c6 : c0, c3, c4
{ // { dg-warning "direct base" "" }
virtual c1 &f2() volatile;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment