From 9bab6c90356bd4ffe3db5d851fc7dbb64a1747f5 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 12 Jun 2000 20:46:28 +0000 Subject: [PATCH] class.c (vcall_offset_data_s): Add last_init and fns. * class.c (vcall_offset_data_s): Add last_init and fns. (overrides): Rename to same_signature_p. (dfs_find_final_overrider): Adjust accordingly. (mark_overriders): Likewise. (warn_hidden): Likewise. (build_vtbl_initializer): Reorganize machinery for building things at negative offsets. (build_vcall_and_vbase_vtbl_entries): Likewise. (build_vbase_offset_vtbl_entries): Likewise. (dfs_build_vcall_offset_vtbl_entries): Correct order of vcall offset entries. Do not create two entries for functions with the same signature. (build_vcall_offset_vtbl_entries): Initialize vod->fns. (build_rtti_vtbl_entries): Reorganize machinery for building things at negative offsets. From-SVN: r34503 --- gcc/cp/ChangeLog | 16 +++++ gcc/cp/class.c | 176 ++++++++++++++++++++++++----------------------- 2 files changed, 106 insertions(+), 86 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 17000bd4a58..5920a04ffd3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,21 @@ 2000-06-12 Mark Mitchell + * class.c (vcall_offset_data_s): Add last_init and fns. + (overrides): Rename to same_signature_p. + (dfs_find_final_overrider): Adjust accordingly. + (mark_overriders): Likewise. + (warn_hidden): Likewise. + (build_vtbl_initializer): Reorganize machinery for building things + at negative offsets. + (build_vcall_and_vbase_vtbl_entries): Likewise. + (build_vbase_offset_vtbl_entries): Likewise. + (dfs_build_vcall_offset_vtbl_entries): Correct order of vcall + offset entries. Do not create two entries for functions with the + same signature. + (build_vcall_offset_vtbl_entries): Initialize vod->fns. + (build_rtti_vtbl_entries): Reorganize machinery for building things + at negative offsets. + * optimize.c (expand_call_inline): Don't recurse into the code used to initialize the parameters more than once. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c34deb0836d..4d9d3991e32 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -66,11 +66,17 @@ typedef struct vcall_offset_data_s { /* The binfo for the most-derived type. */ tree derived; + /* The negative-index vtable initializers built up so far. These + are in order from least negative index to most negative index. */ + tree inits; + /* The last (i.e., most negative entry in INITS. */ + tree* last_init; /* The binfo for the virtual base for which we're building initializers. */ tree vbase; - /* The vcall offset initializers built up so far. */ - tree inits; + /* The functions in vbase for which we have already provided vcall + offsets. */ + varray_type fns; /* The vtable index of the next vcall or vbase offset. */ tree index; /* Nonzero if we are building the initializer for the primary @@ -107,7 +113,7 @@ static void delete_duplicate_fields PARAMS ((tree)); static void finish_struct_bits PARAMS ((tree)); static int alter_access PARAMS ((tree, tree, tree)); static void handle_using_decl PARAMS ((tree, tree)); -static int overrides PARAMS ((tree, tree)); +static int same_signature_p PARAMS ((tree, tree)); static int strictly_overrides PARAMS ((tree, tree)); static void mark_overriders PARAMS ((tree, tree)); static void check_for_override PARAMS ((tree, tree)); @@ -174,7 +180,7 @@ static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int)); static void layout_empty_base PARAMS ((tree, tree, varray_type)); static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree)); static void set_vindex PARAMS ((tree, tree, int *)); -static tree build_rtti_vtbl_entries PARAMS ((tree, tree)); +static void build_rtti_vtbl_entries PARAMS ((tree, tree, vcall_offset_data *)); static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, vcall_offset_data *)); static tree dfs_mark_primary_bases PARAMS ((tree, void *)); @@ -2383,11 +2389,11 @@ layout_vtable_decl (binfo, n) } } -/* True if we should override the given BASE_FNDECL with the given - FNDECL. */ +/* True iff FNDECL and BASE_FNDECL (both non-static member functions) + have the same signature. */ static int -overrides (fndecl, base_fndecl) +same_signature_p (fndecl, base_fndecl) tree fndecl, base_fndecl; { /* One destructor overrides another if they are the same kind of @@ -2455,7 +2461,8 @@ dfs_find_final_overrider (binfo, data) for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path))); method; method = TREE_CHAIN (method)) - if (DECL_VIRTUAL_P (method) && overrides (method, ffod->fn)) + if (DECL_VIRTUAL_P (method) + && same_signature_p (method, ffod->fn)) break; if (method) @@ -2826,10 +2833,8 @@ mark_overriders (fndecl, base_fndecls) tree fndecl, base_fndecls; { for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls)) - { - if (overrides (fndecl, TREE_VALUE (base_fndecls))) - TREE_PURPOSE (base_fndecls) = fndecl; - } + if (same_signature_p (fndecl, TREE_VALUE (base_fndecls))) + TREE_PURPOSE (base_fndecls) = fndecl; } /* If this declaration supersedes the declaration of @@ -2955,15 +2960,13 @@ warn_hidden (t) /* Now give a warning for all base functions without overriders, as they are hidden. */ for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls)) - { - if (! overrides (TREE_PURPOSE (base_fndecls), - TREE_VALUE (base_fndecls))) - { - /* Here we know it is a hider, and no overrider exists. */ - cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls)); - cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls)); - } - } + if (!same_signature_p (TREE_PURPOSE (base_fndecls), + TREE_VALUE (base_fndecls))) + { + /* Here we know it is a hider, and no overrider exists. */ + cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls)); + cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls)); + } } } @@ -6938,33 +6941,32 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) int *non_fn_entries_p; { tree v; - tree inits; - tree vfun_inits; + tree vfun_inits; tree vbase; vcall_offset_data vod; /* Initialize those parts of VOD that matter. */ vod.derived = t; vod.inits = NULL_TREE; + vod.last_init = &vod.inits; vod.primary_p = (binfo == TYPE_BINFO (t)); /* The first vbase or vcall offset is at index -3 in the vtable. */ vod.index = build_int_2 (-3, -1); + /* Add entries to the vtable for RTTI. */ + build_rtti_vtbl_entries (binfo, rtti_binfo, &vod); + /* Add the vcall and vbase offset entries. */ build_vcall_and_vbase_vtbl_entries (binfo, &vod); - inits = vod.inits; - /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by + /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by build_vbase_offset_vtbl_entries. */ for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; vbase = TREE_CHAIN (vbase)) CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase)); - /* Add entries to the vtable for RTTI. */ - inits = chainon (inits, build_rtti_vtbl_entries (binfo, rtti_binfo)); - if (non_fn_entries_p) - *non_fn_entries_p = list_length (inits); + *non_fn_entries_p = list_length (vod.inits); /* Go through all the ordinary virtual functions, building up initializers. */ @@ -7005,9 +7007,11 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) order; straighten them out now. */ vfun_inits = nreverse (vfun_inits); - /* The complete initializer is the INITS, followed by the - VFUN_INITS. */ - return chainon (inits, vfun_inits); + /* The negative offset initializers are also in reverse order. */ + vod.inits = nreverse (vod.inits); + + /* Chain the two together. */ + return chainon (vod.inits, vfun_inits); } /* Sets vod->inits to be the initializers for the vbase and vcall @@ -7019,14 +7023,9 @@ build_vcall_and_vbase_vtbl_entries (binfo, vod) vcall_offset_data *vod; { tree b; - tree inits; /* If this is a derived class, we must first create entries - corresponding to the base class. These entries must go closer to - the vptr, so we save them up and add them to the end of the list - later. */ - inits = vod->inits; - vod->inits = NULL_TREE; + corresponding to the primary base class. */ b = BINFO_PRIMARY_BINFO (binfo); if (b) build_vcall_and_vbase_vtbl_entries (b, vod); @@ -7035,8 +7034,6 @@ build_vcall_and_vbase_vtbl_entries (binfo, vod) build_vbase_offset_vtbl_entries (binfo, vod); /* Add the vcall entries for this base. */ build_vcall_offset_vtbl_entries (binfo, vod); - - vod->inits = chainon (vod->inits, inits); } /* Returns the initializers for the vbase offset entries in the vtable @@ -7116,11 +7113,12 @@ build_vbase_offset_vtbl_entries (binfo, vod) we are walking in inheritance graph order so these end up in the right order. */ delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo)); - vod->inits = tree_cons (NULL_TREE, - fold (build1 (NOP_EXPR, - vtable_entry_type, - delta)), - vod->inits); + *vod->last_init + = build_tree_list (NULL_TREE, + fold (build1 (NOP_EXPR, + vtable_entry_type, + delta))); + vod->last_init = &TREE_CHAIN (*vod->last_init); } } @@ -7162,22 +7160,48 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data) } /* Make entries for the rest of the virtuals. */ - while (base_virtuals) + for (; base_virtuals; + derived_virtuals = TREE_CHAIN (derived_virtuals), + base_virtuals = TREE_CHAIN (base_virtuals)) { /* Figure out what function we're looking at. */ tree fn = TREE_VALUE (derived_virtuals); - tree base = DECL_CONTEXT (fn); + tree base; + tree base_binfo; + size_t i; + + /* If there is already an entry for a function with the same + signature as FN, then we do not need a second vcall offset. + Check the list of functions already present in the derived + class vtable. */ + for (i = 0; i < VARRAY_ACTIVE_SIZE (vod->fns); ++i) + { + tree derived_entry; + + derived_entry = VARRAY_TREE (vod->fns, i); + if (same_signature_p (TREE_VALUE (derived_entry), fn)) + { + BV_VCALL_INDEX (derived_virtuals) + = BV_VCALL_INDEX (derived_entry); + break; + } + } + if (i != VARRAY_ACTIVE_SIZE (vod->fns)) + continue; + /* The FN comes from BASE. So, we must caculate the adjustment from the virtual base that derived from BINFO to BASE. */ - tree base_binfo = get_binfo (base, vod->derived, /*protect=*/0); + base = DECL_CONTEXT (fn); + base_binfo = get_binfo (base, vod->derived, /*protect=*/0); /* Compute the vcall offset. */ - binfo_inits - = tree_cons (NULL_TREE, - fold (build1 (NOP_EXPR, vtable_entry_type, - size_diffop (BINFO_OFFSET (base_binfo), - BINFO_OFFSET (vod->vbase)))), - binfo_inits); + *vod->last_init + = (build_tree_list + (NULL_TREE, + fold (build1 (NOP_EXPR, vtable_entry_type, + size_diffop (BINFO_OFFSET (base_binfo), + BINFO_OFFSET (vod->vbase)))))); + vod->last_init = &TREE_CHAIN (*vod->last_init); /* If there is already a vcall index, then we are processing a construction vtable. The index should be the same as it was @@ -7197,24 +7221,8 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data) vod->index = fold (build (MINUS_EXPR, integer_type_node, vod->index, integer_one_node)); - /* Go to the next entries in the list. */ - derived_virtuals = TREE_CHAIN (derived_virtuals); - base_virtuals = TREE_CHAIN (base_virtuals); - } - - /* The offests are built up in reverse order, so we straighten them - here. We simultaneously add them to VOD->INITS; we're walking - the bases in inheritance graph order, and the initializers are - supposed to appear in reverse inheritance order, so that's - correct. */ - while (binfo_inits) - { - tree next; - - next = TREE_CHAIN (binfo_inits); - TREE_CHAIN (binfo_inits) = vod->inits; - vod->inits = binfo_inits; - binfo_inits = next; + /* Keep track of this function. */ + VARRAY_PUSH_TREE (vod->fns, derived_virtuals); } return NULL_TREE; @@ -7229,8 +7237,6 @@ build_vcall_offset_vtbl_entries (binfo, vod) tree binfo; vcall_offset_data *vod; { - tree inits; - /* Under the old ABI, the adjustments to the `this' pointer were made elsewhere. */ if (!vcall_offsets_in_vtable_p ()) @@ -7263,24 +7269,24 @@ build_vcall_offset_vtbl_entries (binfo, vod) appear in the same order as in the base; but the bases themselves appear in reverse depth-first, left-to-right order. */ vod->vbase = binfo; - inits = vod->inits; - vod->inits = NULL_TREE; + VARRAY_TREE_INIT (vod->fns, 32, "fns"); dfs_walk_real (binfo, dfs_build_vcall_offset_vtbl_entries, NULL, dfs_skip_vbases, vod); - vod->inits = chainon (vod->inits, inits); + VARRAY_FREE (vod->fns); } /* Return vtbl initializers for the RTTI entries coresponding to the BINFO's vtable. The RTTI entries should indicate the object given by RTTI_BINFO. */ -static tree -build_rtti_vtbl_entries (binfo, rtti_binfo) +static void +build_rtti_vtbl_entries (binfo, rtti_binfo, vod) tree binfo; tree rtti_binfo; + vcall_offset_data *vod; { tree b; tree t; @@ -7288,15 +7294,13 @@ build_rtti_vtbl_entries (binfo, rtti_binfo) tree offset; tree decl; tree init; - tree inits; basetype = BINFO_TYPE (binfo); - inits = NULL_TREE; t = BINFO_TYPE (rtti_binfo); /* For a COM object there is no RTTI entry. */ if (CLASSTYPE_COM_INTERFACE (basetype)) - return inits; + return; /* To find the complete object, we will first convert to our most primary base, and then add the offset in the vtbl to that value. */ @@ -7340,7 +7344,8 @@ build_rtti_vtbl_entries (binfo, rtti_binfo) TREE_CONSTANT (init) = 1; init = build_vtable_entry (offset, integer_zero_node, init); } - inits = tree_cons (NULL_TREE, init, inits); + *vod->last_init = build_tree_list (NULL_TREE, init); + vod->last_init = &TREE_CHAIN (*vod->last_init); /* Add the offset-to-top entry. It comes earlier in the vtable that the the typeinfo entry. */ @@ -7350,10 +7355,9 @@ build_rtti_vtbl_entries (binfo, rtti_binfo) we can put it in the vtable. */ init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); TREE_CONSTANT (init) = 1; - inits = tree_cons (NULL_TREE, init, inits); + *vod->last_init = build_tree_list (NULL_TREE, init); + vod->last_init = &TREE_CHAIN (*vod->last_init); } - - return inits; } /* Build an entry in the virtual function table. DELTA is the offset