From 16cb20ebad3a2c0da99ec37302e21d719527e555 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Tue, 5 Oct 1999 16:19:04 +0000 Subject: [PATCH] * method.c (synthesize_method): Call setup_vtbl_ptr for destructors. * decl.c (start_function): Set current_in_charge_parm for constructors, too, where appropriate. * search.c (fixup_all_virtual_upcast_offsets): New function. (expand_indirect_vtbls_init): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@29826 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 9 +++ gcc/cp/decl.c | 8 ++ gcc/cp/method.c | 2 +- gcc/cp/search.c | 106 +++++++++++++++------------ gcc/testsuite/g++.old-deja/g++.other/dtor5.C | 36 +++++++++ 5 files changed, 112 insertions(+), 49 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/dtor5.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0588f0d..6caaf0a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +1999-10-05 Mark Mitchell + + * method.c (synthesize_method): Call setup_vtbl_ptr for destructors. + + * decl.c (start_function): Set current_in_charge_parm for + constructors, too, where appropriate. + * search.c (fixup_all_virtual_upcast_offsets): New function. + (expand_indirect_vtbls_init): Use it. + 1999-10-04 Nathan Sidwell * decl2.c (grok_alignof): Don't decay lvalues. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2ab2a86..877f2c4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -12971,8 +12971,16 @@ start_function (declspecs, declarator, attrs, flags) = build_indirect_ref (t, NULL_PTR); cp_function_chain->x_current_class_ptr = t; + /* Constructors and destructors need to know whether they're "in + charge" of initializing virtual base classes. */ if (DECL_DESTRUCTOR_P (decl1)) current_in_charge_parm = TREE_CHAIN (t); + else if (DECL_CONSTRUCTOR_P (decl1) + && TREE_CHAIN (t) + && DECL_ARTIFICIAL (TREE_CHAIN (t)) + && (DECL_NAME (TREE_CHAIN (t)) + == in_charge_identifier)) + current_in_charge_parm = TREE_CHAIN (t); } if (DECL_INTERFACE_KNOWN (decl1)) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 4ddcf7d..f50f0eb 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2384,7 +2384,7 @@ synthesize_method (fndecl) need_body = 0; } else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) - ; + setup_vtbl_ptr (); else { tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index a8e8ac1..e3418a6 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -149,6 +149,7 @@ static int protected_accessible_p PROTO ((tree, tree, tree, tree)); static int friend_accessible_p PROTO ((tree, tree, tree, tree)); static void setup_class_bindings PROTO ((tree, int)); static int template_self_reference_p PROTO ((tree, tree)); +static void fixup_all_virtual_upcast_offsets PROTO ((tree, tree)); /* Allocate a level of searching. */ @@ -2774,18 +2775,62 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori } } -/* Build a COMPOUND_EXPR which when expanded will generate the code - needed to initialize all the virtual function table slots of all - the virtual baseclasses. MAIN_BINFO is the binfo which determines - the virtual baseclasses to use; TYPE is the type of the object to - which the initialization applies. TRUE_EXP is the true object we - are initializing, and DECL_PTR is the pointer to the sub-object we - are initializing. +/* Fixup all the virtual upcast offsets for TYPE. DECL_PTR is the + address of the sub-object being initialized. */ - When USE_COMPUTED_OFFSETS is non-zero, we can assume that the - object was laid out by a top-level constructor and the computed - offsets are valid to store vtables. When zero, we must store new - vtables through virtual baseclass pointers. */ +static void +fixup_all_virtual_upcast_offsets (type, decl_ptr) + tree type; + tree decl_ptr; +{ + tree if_stmt; + tree in_charge_node; + tree vbases; + + /* Only tweak the vtables if we're in charge. */ + in_charge_node = current_in_charge_parm; + if (!in_charge_node) + /* There's no need for any fixups in this case. */ + return; + in_charge_node = build_binary_op (EQ_EXPR, + in_charge_node, integer_zero_node); + if_stmt = begin_if_stmt (); + finish_if_stmt_cond (in_charge_node, if_stmt); + + /* Iterate through the virtual bases, fixing up the upcast offset + for each one. */ + for (vbases = CLASSTYPE_VBASECLASSES (type); + vbases; + vbases = TREE_CHAIN (vbases)) + { + if (flag_vtable_thunks) + /* We don't have dynamic thunks yet! So for now, just fail + silently. */ + ; + else + { + tree vbase_offsets; + tree addr; + + vbase_offsets = NULL_TREE; + addr = convert_pointer_to_vbase (TREE_TYPE (vbases), decl_ptr); + fixup_virtual_upcast_offsets (vbases, + TYPE_BINFO (BINFO_TYPE (vbases)), + 1, 0, addr, decl_ptr, + type, vbases, &vbase_offsets); + } + } + + /* Close out the if-statement. */ + finish_then_clause (if_stmt); + finish_if_stmt (); +} + +/* Generate the code needed to initialize all the virtual function + table slots of all the virtual baseclasses. BINFO is the binfo + which determines the virtual baseclasses to use. TRUE_EXP is the + true object we are initializing, and DECL_PTR is the pointer to the + sub-object we are initializing. */ void expand_indirect_vtbls_init (binfo, true_exp, decl_ptr) @@ -2807,7 +2852,6 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr) if (TYPE_USES_VIRTUAL_BASECLASSES (type)) { - rtx fixup_insns = NULL_RTX; tree vbases = CLASSTYPE_VBASECLASSES (type); struct vbase_info vi; vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) @@ -2828,44 +2872,10 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr) binfos. (in the CLASSTYPE_VFIELD_PARENT sense) */ expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)), 1, 0, addr); - - /* Now we adjust the offsets for virtual functions that - cross virtual boundaries on an implicit upcast on vf call - so that the layout of the most complete type is used, - instead of assuming the layout of the virtual bases from - our current type. */ - - if (flag_vtable_thunks) - { - /* We don't have dynamic thunks yet! - So for now, just fail silently. */ - } - else - { - tree vbase_offsets = NULL_TREE; - push_to_sequence (fixup_insns); - fixup_virtual_upcast_offsets (vbases, - TYPE_BINFO (BINFO_TYPE (vbases)), - 1, 0, addr, vi.decl_ptr, - type, vbases, &vbase_offsets); - fixup_insns = get_insns (); - end_sequence (); - } } - if (fixup_insns) - { - tree in_charge_node = current_in_charge_parm; - if (! in_charge_node) - { - warning ("recoverable internal compiler error, nobody's in charge!"); - in_charge_node = integer_zero_node; - } - in_charge_node = build_binary_op (EQ_EXPR, in_charge_node, integer_zero_node); - expand_start_cond (in_charge_node, 0); - emit_insns (fixup_insns); - expand_end_cond (); - } + fixup_all_virtual_upcast_offsets (type, + vi.decl_ptr); dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0); } diff --git a/gcc/testsuite/g++.old-deja/g++.other/dtor5.C b/gcc/testsuite/g++.old-deja/g++.other/dtor5.C new file mode 100644 index 0000000..ab37e39 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/dtor5.C @@ -0,0 +1,36 @@ +// Origin: Mark Mitchell + +extern "C" void abort (); + +struct B; + +struct S +{ + S (B*); + ~S (); + + B* b_; +}; + +struct B +{ + B () : s (this) { } + + virtual void f () { } + + S s; +}; + +S::S (B* b) : b_ (b) { } + +S::~S () { b_->f (); } + +struct D : public B +{ + virtual void f () { abort (); } +}; + +int main () +{ + D d; +} -- 2.7.4