From d0cd8b44016194824049ec6ee453d6864b73bc01 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 6 Jun 2001 17:52:52 -0400 Subject: [PATCH] cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose. * cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose. (struct lang_decl_flags): Lose generate_with_vtable_p. (BV_GENERATE_THUNK_WITH_VTABLE_P): Lose. * class.c (copy_virtuals): Adjust. * decl2.c (mark_vtable_entries): Adjust. * method.c (make_thunk, build_vtable_entry): Adjust. * class.c (update_vtable_entry_for_fn): Only look as far as the first defining class. (build_vtbl_initializer): Put nothing in the slot for a function only defined in a lost primary virtual base. (add_vcall_offset_vtbl_entries_1): Use the same code for the lost primary case and the normal case. (dfs_unshared_virtual_bases): Don't lose a non-virtual primary base. (get_vfield_offset, get_derived_offset): Lose. (dfs_find_final_overrider): Use look_for_overrides_here. (get_matching_virtual): New fn. * semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P, not BV_VCALL_INDEX. * search.c (look_for_overrides_here): Split out from... (look_for_overrides_r): Here. * class.c (find_final_overrider): Return error_mark_node on error. From-SVN: r42949 --- gcc/cp/ChangeLog | 27 +++ gcc/cp/class.c | 364 ++++++++++++++++----------------- gcc/cp/cp-tree.h | 25 +-- gcc/cp/decl2.c | 9 +- gcc/cp/method.c | 5 +- gcc/cp/search.c | 72 ++++--- gcc/cp/semantics.c | 5 +- gcc/testsuite/g++.dg/mangle1.C | 1 - 8 files changed, 261 insertions(+), 247 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4e458c549ca..8ba7f9f1966 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,30 @@ +2001-06-06 Jason Merrill + + * cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose. + (struct lang_decl_flags): Lose generate_with_vtable_p. + (BV_GENERATE_THUNK_WITH_VTABLE_P): Lose. + * class.c (copy_virtuals): Adjust. + * decl2.c (mark_vtable_entries): Adjust. + * method.c (make_thunk, build_vtable_entry): Adjust. + * class.c (update_vtable_entry_for_fn): Only look as far as the + first defining class. + (build_vtbl_initializer): Put nothing in the slot for a function only + defined in a lost primary virtual base. + (add_vcall_offset_vtbl_entries_1): Use the same code for + the lost primary case and the normal case. + (dfs_unshared_virtual_bases): Don't lose a non-virtual primary base. + (get_vfield_offset, get_derived_offset): Lose. + (dfs_find_final_overrider): Use look_for_overrides_here. + (get_matching_virtual): New fn. + * semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P, + not BV_VCALL_INDEX. + * search.c (look_for_overrides_here): Split out from... + (look_for_overrides_r): Here. + + * class.c (find_final_overrider): Return error_mark_node on error. + + * decl2.c (key_method): #if 0 accidental change. + 2001-06-06 John David Anglin * call.c (convert_default_arg): Use INTEGRAL_TYPE_P. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index afe2da403f7..cdd92b5d4c2 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -74,7 +74,7 @@ typedef struct vtbl_init_data_s /* 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. */ + /* The last (i.e., most negative) entry in INITS. */ tree* last_init; /* The binfo for the virtual base for which we're building vcall offset initializers. */ @@ -107,9 +107,8 @@ varray_type local_classes; static tree get_vfield_name PARAMS ((tree)); static void finish_struct_anon PARAMS ((tree)); static tree build_vbase_pointer PARAMS ((tree, tree)); -static tree build_vtable_entry PARAMS ((tree, tree, tree, int)); +static tree build_vtable_entry PARAMS ((tree, tree, tree)); static tree get_vtable_name PARAMS ((tree)); -static tree get_derived_offset PARAMS ((tree, tree)); static tree get_basefndecls PARAMS ((tree, tree)); static int build_primary_vtable PARAMS ((tree, tree)); static int build_secondary_vtable PARAMS ((tree, tree)); @@ -684,37 +683,6 @@ get_vtt_name (type) return mangle_vtt_for_type (type); } -/* Return the offset to the main vtable for a given base BINFO. */ - -tree -get_vfield_offset (binfo) - tree binfo; -{ - return - size_binop (PLUS_EXPR, byte_position (TYPE_VFIELD (BINFO_TYPE (binfo))), - BINFO_OFFSET (binfo)); -} - -/* Get the offset to the start of the original binfo that we derived - this binfo from. If we find TYPE first, return the offset only - that far. The shortened search is useful because the this pointer - on method calling is expected to point to a DECL_CONTEXT (fndecl) - object, and not a baseclass of it. */ - -static tree -get_derived_offset (binfo, type) - tree binfo, type; -{ - tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); - tree offset2; - - while (!same_type_p (BINFO_TYPE (binfo), type)) - binfo = get_primary_binfo (binfo); - - offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); - return size_binop (MINUS_EXPR, offset1, offset2); -} - /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE. (For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.) Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */ @@ -796,7 +764,6 @@ copy_virtuals (binfo) { BV_VCALL_INDEX (t) = NULL_TREE; BV_USE_VCALL_INDEX_P (t) = 0; - BV_GENERATE_THUNK_WITH_VTABLE_P (t) = 0; } return copies; @@ -1024,9 +991,11 @@ make_new_vtable (t, binfo) { if (binfo == TYPE_BINFO (t)) /* In this case, it is *type*'s vtable we are modifying. We start - with the approximation that it's vtable is that of the + with the approximation that its vtable is that of the immediate base class. */ - return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))), + /* ??? This actually passes TYPE_BINFO (t), not the primary base binfo, + since we've updated DECL_CONTEXT (TYPE_VFIELD (t)) by now. */ + return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))), t); else /* This is our very own copy of `basetype' to play with. Later, @@ -1077,7 +1046,12 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals) BV_FN (v) = fndecl; /* Now assign virtual dispatch information, if unset. We can - dispatch this, through any overridden base function. */ + dispatch this through any overridden base function. + + FIXME this can choose a secondary vtable if the primary is not + also lexically first, leading to useless conversions. + In the V3 ABI, there's no reason for DECL_VIRTUAL_CONTEXT to + ever be different from DECL_CONTEXT. */ if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) { DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl); @@ -1808,7 +1782,7 @@ mark_primary_virtual_base (binfo, base_binfo, type) return base_binfo; } -/* If BINFO is an unmarked virtual binfo for a class with a primary +/* If BINFO is an unmarked virtual binfo for a class with a primary virtual base, then BINFO has no primary base in this graph. Called from mark_primary_bases. */ @@ -1817,7 +1791,8 @@ static tree dfs_unshared_virtual_bases (binfo, data) void *data ATTRIBUTE_UNUSED; { if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo) - && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))) + && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)) + && TREE_VIA_VIRTUAL (CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo)))) BINFO_LOST_PRIMARY_P (binfo) = 1; CLEAR_BINFO_MARKED (binfo); @@ -2542,13 +2517,8 @@ dfs_find_final_overrider (binfo, data) path; path = TREE_CHAIN (path)) { - for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path))); - method; - method = TREE_CHAIN (method)) - if (DECL_VIRTUAL_P (method) - && same_signature_p (method, ffod->fn)) - break; - + method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)), + ffod->fn); if (method) break; } @@ -2676,7 +2646,7 @@ find_final_overrider (t, binfo, fn) struct T : virtual public R { virtual void f (); }; struct U : public S, public T { }; - is not -- there's no way to decide whether to put `S::f' or + is not -- there's no way to decide whether to put `S::f' or `T::f' in the vtable for `R'. The solution is to look at all paths to BINFO. If we find @@ -2695,14 +2665,36 @@ find_final_overrider (t, binfo, fn) /* If there was no winner, issue an error message. */ if (!ffod.overriding_fn) - cp_error ("no unique final overrider for `%D' in `%T'", fn, t); + { + cp_error ("no unique final overrider for `%D' in `%T'", fn, t); + return error_mark_node; + } return build_tree_list (ffod.overriding_fn, ffod.overriding_base); } -/* Update a entry in the vtable for BINFO, which is in the hierarchy - dominated by T. FN has been overridden in BINFO; VIRTUALS points - to the corresponding position in the BINFO_VIRTUALS list. */ +#if 0 +/* Returns the function from the BINFO_VIRTUALS entry in T which matches + the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words, + the function that the slot in T's primary vtable points to. */ + +static tree get_matching_virtual PARAMS ((tree, tree)); +static tree +get_matching_virtual (t, fn) + tree t, fn; +{ + tree f; + + for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f)) + if (same_signature_p (BV_FN (f), fn)) + return BV_FN (f); + return NULL_TREE; +} +#endif + +/* Update an entry in the vtable for BINFO, which is in the hierarchy + dominated by T. FN has been overriden in BINFO; VIRTUALS points to the + corresponding position in the BINFO_VIRTUALS list. */ static void update_vtable_entry_for_fn (t, binfo, fn, virtuals) @@ -2715,93 +2707,92 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) tree overrider; tree delta; tree virtual_base; - int generate_thunk_with_vtable_p; + tree first_defn; - /* Find the function which originally caused this vtable - entry to be present. */ - b = binfo; - while (1) + /* 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)) { - tree primary_base; - tree f; - - primary_base = get_primary_binfo (b); - if (!primary_base) + if (look_for_overrides_here (BINFO_TYPE (b), fn)) break; - - for (f = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (primary_base))); - f; - f = TREE_CHAIN (f)) - if (same_signature_p (BV_FN (f), fn)) - break; - - if (!f) - break; - - fn = BV_FN (f); - b = primary_base; } + first_defn = b; /* Find the final overrider. */ overrider = find_final_overrider (t, b, fn); if (overrider == error_mark_node) return; - /* Compute the constant adjustment to the `this' pointer. The - `this' pointer, when this function is called, will point at the - class whose vtable this is. */ - delta = size_binop (PLUS_EXPR, - get_derived_offset (binfo, - DECL_VIRTUAL_CONTEXT (fn)), - BINFO_OFFSET (binfo)); - /* Assume that we will produce a thunk that convert all the way to the final overrider, and not to an intermediate virtual base. */ virtual_base = NULL_TREE; - /* Assume that we will always generate thunks with the vtables that - reference them. */ - generate_thunk_with_vtable_p = 1; - /* Under the new ABI, we will convert to an intermediate virtual base first, and then use the vcall offset located there to finish the conversion. */ while (b) { - /* If we find BINFO, then the final overrider is in a class - derived from BINFO, so the thunks can be generated with - the final overrider. */ - if (!virtual_base - && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo))) - generate_thunk_with_vtable_p = 0; - - /* If we find the final overrider, then we can stop - walking. */ + /* If we find the final overrider, then we can stop + walking. */ if (same_type_p (BINFO_TYPE (b), BINFO_TYPE (TREE_VALUE (overrider)))) break; - /* If we find a virtual base, and we haven't yet found the - overrider, then there is a virtual base between the - declaring base and the final overrider. */ + /* If we find a virtual base, and we haven't yet found the + overrider, then there is a virtual base between the + declaring base (first_defn) and the final overrider. */ if (!virtual_base && TREE_VIA_VIRTUAL (b)) - { - generate_thunk_with_vtable_p = 1; - virtual_base = b; - } + virtual_base = b; b = BINFO_INHERITANCE_CHAIN (b); } + /* Compute the constant adjustment to the `this' pointer. The + `this' pointer, when this function is called, will point at BINFO + (or one of its primary bases, which are at the same offset). */ + if (virtual_base) /* The `this' pointer needs to be adjusted to the nearest virtual base. */ - delta = size_diffop (BINFO_OFFSET (virtual_base), delta); + delta = size_diffop (BINFO_OFFSET (virtual_base), + BINFO_OFFSET (binfo)); else - /* The `this' pointer needs to be adjusted from pointing to - BINFO to pointing at the base where the final overrider - appears. */ - delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta); + { + /* The `this' pointer needs to be adjusted from pointing to + BINFO to pointing at the base where the final overrider + appears. */ + delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), + BINFO_OFFSET (binfo)); + +#if 0 + /* Disable this optimization pending an ABI change, or until + we can force emission of the non-virtual thunk even if we don't + use it. */ + if (! integer_zerop (delta)) + { + /* We'll need a thunk. But if we have a (perhaps formerly) + primary virtual base, we have a vcall slot for this function, + so we can use it rather than create a non-virtual thunk. */ + + b = get_primary_binfo (first_defn); + for (; b; b = get_primary_binfo (b)) + { + tree f = get_matching_virtual (BINFO_TYPE (b), fn); + if (!f) + /* b doesn't have this function; no suitable vbase. */ + break; + if (TREE_VIA_VIRTUAL (b)) + { + /* Found one; we can treat ourselves as a virtual base. */ + virtual_base = binfo; + delta = size_zero_node; + break; + } + } + } +#endif + } modify_vtable_entry (t, binfo, @@ -2811,8 +2802,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) if (virtual_base) BV_USE_VCALL_INDEX_P (*virtuals) = 1; - if (generate_thunk_with_vtable_p) - BV_GENERATE_THUNK_WITH_VTABLE_P (*virtuals) = 1; } /* Called from modify_all_vtables via dfs_walk. */ @@ -2823,9 +2812,9 @@ dfs_modify_vtables (binfo, data) void *data; { if (/* There's no need to modify the vtable for a non-virtual - primary base; we're not going to use that vtable anyhow - (virtual primary bases can become non-primary in a - class derivation of this one.) */ + primary base; we're not going to use that vtable anyhow. + We do still need to do this for virtual primary bases, as they + could become non-primary in a construction vtable. */ (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo)) /* Similarly, a base without a vtable needs no modification. */ && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) @@ -5310,9 +5299,7 @@ finish_struct_1 (t) layout_class_type (t, &empty, &vfuns, &new_virtuals, &overridden_virtuals); - /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we - might need to know it for setting up the offsets in the vtable - (or in thunks) below. */ + /* Make sure that we get our own copy of the vfield FIELD_DECL. */ vfield = TYPE_VFIELD (t); if (vfield != NULL_TREE && DECL_FIELD_CONTEXT (vfield) != t) @@ -7667,7 +7654,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) tree rtti_binfo; int *non_fn_entries_p; { - tree v; + tree v, b; tree vfun_inits; tree vbase; vtbl_init_data vid; @@ -7714,7 +7701,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) tree fn; tree pfn; tree init; - int generate_with_vtable_p = BV_GENERATE_THUNK_WITH_VTABLE_P (v); /* Pull the offset for `this', and the function to call, out of the list. */ @@ -7725,15 +7711,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) vcall_index = BV_VCALL_INDEX (v); my_friendly_assert (vcall_index != NULL_TREE, 20000621); } - else if (vid.ctor_vtbl_p && BV_VCALL_INDEX (v)) - { - /* In the original, we did not need to use the vcall index, even - though there was one, but in a ctor vtable things might be - different (a primary virtual base might have moved). Be - conservative and use a vcall adjusting thunk. */ - vcall_index = BV_VCALL_INDEX (v); - generate_with_vtable_p = 1; - } else vcall_index = NULL_TREE; @@ -7751,9 +7728,35 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn); /* The address of a function can't change. */ TREE_CONSTANT (pfn) = 1; + /* Enter it in the vtable. */ - init = build_vtable_entry (delta, vcall_index, pfn, - generate_with_vtable_p); + init = build_vtable_entry (delta, vcall_index, pfn); + + /* If the only definition of this function signature along our + primary base chain is from a lost primary, this vtable slot will + never be used, so just zero it out. This is important to avoid + requiring extra thunks which cannot be generated with the function. + + We could also handle this in update_vtable_entry_for_fn; doing it + here means we zero out unused slots in ctor vtables as well, + rather than filling them with erroneous values (though harmless, + apart from relocation costs). */ + if (fn != abort_fndecl) + for (b = binfo; ; b = get_primary_binfo (b)) + { + /* We found a defn before a lost primary; go ahead as normal. */ + if (look_for_overrides_here (BINFO_TYPE (b), fn)) + break; + + /* The nearest definition is from a lost primary; clear the + slot. */ + if (BINFO_LOST_PRIMARY_P (b)) + { + init = size_zero_node; + break; + } + } + /* And add it to the chain of initializers. */ vfun_inits = tree_cons (NULL_TREE, init, vfun_inits); } @@ -7769,7 +7772,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) return chainon (vid.inits, vfun_inits); } -/* Sets vid->inits to be the initializers for the vbase and vcall +/* Adds to vid->inits the initializers for the vbase and vcall offsets in BINFO, which is in the hierarchy dominated by T. */ static void @@ -7877,8 +7880,8 @@ build_vbase_offset_vtbl_entries (binfo, vid) } /* Adds the initializers for the vcall offset entries in the vtable - for BINFO (which is part of the class hierarchy dominated by T) to - VID->INITS. */ + for BINFO (which is part of the class hierarchy dominated by VID->DERIVED) + to VID->INITS. */ static void build_vcall_offset_vtbl_entries (binfo, vid) @@ -7898,22 +7901,20 @@ build_vcall_offset_vtbl_entries (binfo, vid) vtable. For example: class A { virtual void f (); }; - class B : virtual public A { }; - class C: virtual public A, public B {}; - - Now imagine: - - B* b = new C; - b->f(); - - The location of `A' is not at a fixed offset relative to `B'; the - offset depends on the complete object derived from `B'. So, - `B' vtable contains an entry for `f' that indicates by what - amount the `this' pointer for `B' needs to be adjusted to arrive - at `A'. + class B1 : virtual public A { virtual void f (); }; + class B2 : virtual public A { virtual void f (); }; + class C: public B1, public B2 { virtual void f (); }; + + A C object has a primary base of B1, which has a primary base of A. A + C also has a secondary base of B2, which no longer has a primary base + of A. So the B2-in-C construction vtable needs a secondary vtable for + A, which will adjust the A* to a B2* to call f. We have no way of + knowing what (or even whether) this offset will be when we define B2, + so we store this "vcall offset" in the A sub-vtable and look it up in + a "virtual thunk" for B2::f. We need entries for all the functions in our primary vtable and - in our non-virtual bases vtables. */ + in our non-virtual bases' secondary vtables. */ vid->vbase = binfo; /* Now, walk through the non-virtual bases, adding vcall offsets. */ add_vcall_offset_vtbl_entries_r (binfo, vid); @@ -7930,7 +7931,9 @@ add_vcall_offset_vtbl_entries_r (binfo, vid) tree primary_binfo; /* Don't walk into virtual bases -- except, of course, for the - virtual base for which we are building vcall offsets. */ + virtual base for which we are building vcall offsets. Any + primary virtual base will have already had its offsets generated + through the recursion in build_vcall_and_vbase_vtbl_entries. */ if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo) return; @@ -7964,43 +7967,30 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) tree base_virtuals; tree orig_virtuals; tree binfo_inits; - int lost_primary = 0; - /* If BINFO is a primary base, this is the least derived class of - BINFO that is not a primary base. */ + /* If BINFO is a primary base, the most derived class which has BINFO as + a primary base; otherwise, just BINFO. */ tree non_primary_binfo; binfo_inits = NULL_TREE; - /* We might be a primary base class. Go up the inheritance - hierarchy until we find the class of which we are a primary base: + /* We might be a primary base class. Go up the inheritance hierarchy + until we find the most derived class of which we are a primary base: it is the BINFO_VIRTUALS there that we need to consider. */ non_primary_binfo = binfo; while (BINFO_INHERITANCE_CHAIN (non_primary_binfo)) { tree b; - /* If we have reached a virtual base, then it must be the - virtual base for which we are building vcall offsets. In - turn, the virtual base must be a (possibly indirect) primary - base of the class that we are initializing, or we wouldn't - care about its vtable offsets. */ + /* If we have reached a virtual base, then it must be vid->vbase, + because we ignore other virtual bases in + add_vcall_offset_vtbl_entries_r. In turn, it must be a primary + base (possibly multi-level) of vid->binfo, or we wouldn't + have called build_vcall_and_vbase_vtbl_entries for it. But it + might be a lost primary, so just skip down to vid->binfo. */ if (TREE_VIA_VIRTUAL (non_primary_binfo)) { - if (vid->ctor_vtbl_p) - { - tree probe; - - for (probe = vid->binfo; - probe != non_primary_binfo; - probe = get_primary_binfo (probe)) - { - if (BINFO_LOST_PRIMARY_P (probe)) - { - lost_primary = 1; - break; - } - } - } + if (non_primary_binfo != vid->vbase) + abort (); non_primary_binfo = vid->binfo; break; } @@ -8034,13 +8024,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) tree vcall_offset; /* Find the declaration that originally caused this function to - be present. */ + be present in BINFO_TYPE (binfo). */ orig_fn = BV_FN (orig_virtuals); - /* We do not need an entry if this function is declared in a - virtual base (or one of its virtual bases), and not - overridden in the section of the hierarchy dominated by the - virtual base for which we are building vcall offsets. */ + /* When processing BINFO, we only want to generate vcall slots for + function slots introduced in BINFO. So don't try to generate + one if the function isn't even defined in BINFO. */ if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo))) continue; @@ -8071,16 +8060,19 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) if (i != VARRAY_ACTIVE_SIZE (vid->fns)) continue; - /* The FN comes from BASE. So, we must calculate the adjustment - from the virtual base that derived from BINFO to BASE. */ + /* The FN comes from BASE. So, we must calculate the adjustment from + vid->vbase to BASE. We can just look for BASE in the complete + object because we are converting from a virtual base, so if there + were multiple copies, there would not be a unique final overrider + and vid->derived would be ill-formed. */ base = DECL_CONTEXT (fn); base_binfo = get_binfo (base, vid->derived, /*protect=*/0); /* Compute the vcall offset. */ - vcall_offset = BINFO_OFFSET (vid->vbase); - if (lost_primary) - vcall_offset = size_binop (PLUS_EXPR, vcall_offset, - BINFO_OFFSET (vid->binfo)); + /* As mentioned above, the vbase we're working on is a primary base of + vid->binfo. But it might be a lost primary, so its BINFO_OFFSET + might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */ + vcall_offset = BINFO_OFFSET (vid->binfo); vcall_offset = size_diffop (BINFO_OFFSET (base_binfo), vcall_offset); vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type, @@ -8091,7 +8083,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) /* Keep track of the vtable index where this vcall offset can be found. For a construction vtable, we already made this - annotation when we build the original vtable. */ + annotation when we built the original vtable. */ if (!vid->ctor_vtbl_p) BV_VCALL_INDEX (derived_virtuals) = vid->index; @@ -8172,11 +8164,10 @@ build_rtti_vtbl_entries (binfo, vid) ABI.) */ static tree -build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p) +build_vtable_entry (delta, vcall_index, entry) tree delta; tree vcall_index; tree entry; - int generate_with_vtable_p; { if (flag_vtable_thunks) { @@ -8186,8 +8177,7 @@ build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p) if ((!integer_zerop (delta) || vcall_index != NULL_TREE) && fn != abort_fndecl) { - entry = make_thunk (entry, delta, vcall_index, - generate_with_vtable_p); + entry = make_thunk (entry, delta, vcall_index); entry = build1 (ADDR_EXPR, vtable_entry_type, entry); TREE_READONLY (entry) = 1; TREE_CONSTANT (entry) = 1; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e820303243c..b73626a3310 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA. */ BASELINK_P (in TREE_LIST) ICS_ELLIPSIS_FLAG (in _CONV) BINFO_ACCESS (in BINFO) - BV_GENERATE_THUNK_WITH_VTABLE_P (in TREE_LIST) 2: IDENTIFIER_OPNAME_P. TYPE_POLYMORHPIC_P (in _TYPE) ICS_THIS_FLAG (in _CONV) @@ -133,10 +132,6 @@ Boston, MA 02111-1307, USA. */ The BV_FN is the declaration for the virtual function itself. - The BV_OVERRIDING_BASE is the binfo for the final overrider for - this function. (That binfo's BINFO_TYPE will always be the same - as the DECL_CLASS_CONTEXT for the function.) - BINFO_VTABLE Sometimes this is a VAR_DECL. Under the new ABI, it is instead an expression with POINTER_TYPE pointing that gives the value @@ -1736,14 +1731,6 @@ struct lang_type /* Nonzero if we should use a virtual thunk for this entry. */ #define BV_USE_VCALL_INDEX_P(NODE) \ (TREE_LANG_FLAG_0 (NODE)) - -/* Nonzero if we should generate this thunk when the vtable that - references it is emitted, rather than with the final overrider. */ -#define BV_GENERATE_THUNK_WITH_VTABLE_P(NODE) \ - (TREE_LANG_FLAG_1 (NODE)) - -/* The most derived class. */ - /* Nonzero for TREE_LIST node means that this list of things is a list of parameters, as opposed to a list of expressions. */ @@ -1806,8 +1793,7 @@ struct lang_decl_flags unsigned global_dtor_p : 1; unsigned assignment_operator_p : 1; unsigned anticipated_p : 1; - unsigned generate_with_vtable_p : 1; - /* Two unused bits. */ + /* Three unused bits. */ union { /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this @@ -3036,11 +3022,6 @@ enum ptrmemfunc_vbit_where_t #define THUNK_VCALL_OFFSET(DECL) \ (DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset) -/* Nonzero if this thunk should be generated with the vtable that - references it. */ -#define THUNK_GENERATE_WITH_VTABLE_P(DECL) \ - (DECL_LANG_SPECIFIC (DECL)->decl_flags.generate_with_vtable_p) - /* These macros provide convenient access to the various _STMT nodes created when parsing template declarations. */ #define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0) @@ -3716,7 +3697,6 @@ extern tree get_vtable_decl PARAMS ((tree, int)); extern void add_method PARAMS ((tree, tree, int)); extern int currently_open_class PARAMS ((tree)); extern tree currently_open_derived_class PARAMS ((tree)); -extern tree get_vfield_offset PARAMS ((tree)); extern void duplicate_tag_error PARAMS ((tree)); extern tree finish_struct PARAMS ((tree, tree)); extern void finish_struct_1 PARAMS ((tree)); @@ -4083,7 +4063,7 @@ extern void init_method PARAMS ((void)); extern void set_mangled_name_for_decl PARAMS ((tree)); extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree)); extern tree hack_identifier PARAMS ((tree, tree)); -extern tree make_thunk PARAMS ((tree, tree, tree, int)); +extern tree make_thunk PARAMS ((tree, tree, tree)); extern void use_thunk PARAMS ((tree, int)); extern void synthesize_method PARAMS ((tree)); extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int)); @@ -4202,6 +4182,7 @@ extern tree context_for_name_lookup PARAMS ((tree)); extern tree lookup_conversions PARAMS ((tree)); extern tree binfo_for_vtable PARAMS ((tree)); extern tree binfo_from_vbase PARAMS ((tree)); +extern tree look_for_overrides_here PARAMS ((tree, tree)); extern tree dfs_walk PARAMS ((tree, tree (*) (tree, void *), tree (*) (tree, void *), diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c1aa3281c27..56c4dbc0c0f 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2265,7 +2265,7 @@ mark_vtable_entries (decl) we know all the thunks we'll need when we emit a virtual function, so we emit the thunks there instead. */ if (DECL_THUNK_P (fn)) - use_thunk (fn, THUNK_GENERATE_WITH_VTABLE_P (fn)); + use_thunk (fn, /*emit_p=*/0); mark_used (fn); } } @@ -2369,7 +2369,12 @@ key_method (type) method = TREE_CHAIN (method)) if (DECL_VINDEX (method) != NULL_TREE && ! DECL_DECLARED_INLINE_P (method) - && (! DECL_PURE_VIRTUAL_P (method) || DECL_DESTRUCTOR_P (method))) + && (! DECL_PURE_VIRTUAL_P (method) +#if 0 + /* This would be nice, but we didn't think of it in time. */ + || DECL_DESTRUCTOR_P (method) +#endif + )) return method; return NULL_TREE; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index e7d2bbbd665..4acf6b670b0 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -295,11 +295,10 @@ request for member `%D' is ambiguous in multiple inheritance lattice", DELTA is the offset to this and VCALL_INDEX is zero. */ tree -make_thunk (function, delta, vcall_index, generate_with_vtable_p) +make_thunk (function, delta, vcall_index) tree function; tree delta; tree vcall_index; - int generate_with_vtable_p; { tree thunk_id; tree thunk; @@ -348,7 +347,6 @@ make_thunk (function, delta, vcall_index, generate_with_vtable_p) DECL_INITIAL (thunk) = function; THUNK_DELTA (thunk) = d; THUNK_VCALL_OFFSET (thunk) = vcall_offset; - THUNK_GENERATE_WITH_VTABLE_P (thunk) = generate_with_vtable_p; /* The thunk itself is not a constructor or destructor, even if the thing it is thunking to is. */ DECL_INTERFACE_KNOWN (thunk) = 1; @@ -381,7 +379,6 @@ void use_thunk (thunk_fndecl, emit_p) tree thunk_fndecl; int emit_p; - { tree fnaddr; tree function; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index fe95c955111..81826c175b6 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2024,56 +2024,72 @@ look_for_overrides (type, fndecl) return found; } -/* Look in TYPE for virtual functions overridden by FNDECL. Check both - TYPE itself and its bases. */ +/* Look in TYPE for virtual functions with the same signature as FNDECL. + This differs from get_matching_virtual in that it will only return + a function from TYPE. */ -static int -look_for_overrides_r (type, fndecl) +tree +look_for_overrides_here (type, fndecl) tree type, fndecl; { int ix; - - if (DECL_DESTRUCTOR_P (fndecl)) + + if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl)) ix = CLASSTYPE_DESTRUCTOR_SLOT; else ix = lookup_fnfields_1 (type, DECL_NAME (fndecl)); if (ix >= 0) { tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix); - tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - tree thistype = DECL_STATIC_FUNCTION_P (fndecl) - ? NULL_TREE : TREE_TYPE (TREE_VALUE (dtypes)); for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); - tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); - + if (!DECL_VIRTUAL_P (fn)) - /* Not a virtual */; + /* Not a virtual. */; else if (DECL_CONTEXT (fn) != type) - /* Introduced with a using declaration */; - else if (thistype == NULL_TREE) + /* Introduced with a using declaration. */; + else if (DECL_STATIC_FUNCTION_P (fndecl)) { - if (compparms (TREE_CHAIN (btypes), dtypes)) - { - /* A static member function cannot match an inherited - virtual member function. */ - cp_error_at ("`%#D' cannot be declared", fndecl); - cp_error_at (" since `%#D' declared in base class", fn); - return 1; - } + tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); + tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + if (compparms (TREE_CHAIN (btypes), dtypes)) + return fn; } else if (same_signature_p (fndecl, fn)) - { - /* It's definitely virtual, even if not explicitly set. */ - DECL_VIRTUAL_P (fndecl) = 1; - check_final_overrider (fndecl, fn); + return fn; + } + } + return NULL_TREE; +} - return 1; - } +/* Look in TYPE for virtual functions overridden by FNDECL. Check both + TYPE itself and its bases. */ + +static int +look_for_overrides_r (type, fndecl) + tree type, fndecl; +{ + tree fn = look_for_overrides_here (type, fndecl); + if (fn) + { + if (DECL_STATIC_FUNCTION_P (fndecl)) + { + /* A static member function cannot match an inherited + virtual member function. */ + cp_error_at ("`%#D' cannot be declared", fndecl); + cp_error_at (" since `%#D' declared in base class", fn); + } + else + { + /* It's definitely virtual, even if not explicitly set. */ + DECL_VIRTUAL_P (fndecl) = 1; + check_final_overrider (fndecl, fn); } + return 1; } + /* We failed to find one declared in this class. Look in its bases. */ return look_for_overrides (type, fndecl); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f1a9e77aa7d..9dddf230ddd 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2300,7 +2300,7 @@ emit_associated_thunks (fn) for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v)) if (BV_FN (v) == fn && (!integer_zerop (BV_DELTA (v)) - || BV_VCALL_INDEX (v))) + || BV_USE_VCALL_INDEX_P (v))) { tree thunk; tree vcall_index; @@ -2317,8 +2317,7 @@ emit_associated_thunks (fn) vfunc_ptr_type_node, fn), BV_DELTA (v), - vcall_index, - /*generate_with_vtable_p=*/0); + vcall_index); use_thunk (thunk, /*emit_p=*/1); } } diff --git a/gcc/testsuite/g++.dg/mangle1.C b/gcc/testsuite/g++.dg/mangle1.C index 499367e9d01..808e56d241e 100644 --- a/gcc/testsuite/g++.dg/mangle1.C +++ b/gcc/testsuite/g++.dg/mangle1.C @@ -26,4 +26,3 @@ C c; // { dg-final { scan-assembler mangle1.C "\n_ZTT1C:" } } // { dg-final { scan-assembler mangle1.C "\n_ZTV1A:" } } // { dg-final { scan-assembler mangle1.C "\n_ZTV1C:" } } -// { dg-final { scan-assembler mangle1.C "\n_ZTv0_n\(12|24\)_N1A1fEv:" } } -- 2.30.2