diff options
author | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-12-16 18:23:00 +0000 |
---|---|---|
committer | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-12-16 18:23:00 +0000 |
commit | 805e22b2051e9c6a75377ea6599654d7415da483 (patch) | |
tree | c259697c448b0c6f548f153c48c46a8d7a75970f /gcc/cp/class.c | |
parent | 2c27ce73ee2229b0871c4ccad2342d8a4be85eff (diff) | |
download | ppe42-gcc-805e22b2051e9c6a75377ea6599654d7415da483.tar.gz ppe42-gcc-805e22b2051e9c6a75377ea6599654d7415da483.zip |
Merge basic-improvements-branch to trunk
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60174 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 06d09681e6f..9f95c994703 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "cp-tree.h" #include "flags.h" @@ -2326,6 +2328,9 @@ get_vcall_index (tree fn, tree type) { tree v; + if (DECL_RESULT_THUNK_P (fn)) + fn = TREE_OPERAND (DECL_INITIAL (fn), 0); + for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v)) if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v))) || same_signature_p (fn, TREE_PURPOSE (v))) @@ -2373,10 +2378,53 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) overrider = find_final_overrider (TYPE_BINFO (t), b, fn); if (overrider == error_mark_node) return; + { + /* Check for adjusting covariant return types. */ + tree over_return = TREE_TYPE (TREE_TYPE (TREE_PURPOSE (overrider))); + tree base_return = TREE_TYPE (TREE_TYPE (fn)); + + if (POINTER_TYPE_P (over_return) + && TREE_CODE (over_return) == TREE_CODE (base_return) + && CLASS_TYPE_P (TREE_TYPE (over_return)) + && CLASS_TYPE_P (TREE_TYPE (base_return))) + { + tree binfo; + base_kind kind; + + binfo = lookup_base (TREE_TYPE (over_return), TREE_TYPE (base_return), + ba_check | ba_quiet, &kind); - /* Check for unsupported covariant returns again now that we've - calculated the base offsets. */ - check_final_overrider (TREE_PURPOSE (overrider), fn); + if (binfo && (kind == bk_via_virtual || !BINFO_OFFSET_ZEROP (binfo))) + { + tree fixed_offset = BINFO_OFFSET (binfo); + tree virtual_offset = NULL_TREE; + tree thunk; + + if (kind == bk_via_virtual) + { + while (!TREE_VIA_VIRTUAL (binfo)) + binfo = BINFO_INHERITANCE_CHAIN (binfo); + + /* 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); + } + + /* Replace the overriding function with a covariant thunk. + We will emit the overriding function in its own slot + as well. */ + thunk = make_thunk (TREE_PURPOSE (overrider), /*this_adjusting=*/0, + fixed_offset, virtual_offset); + TREE_PURPOSE (overrider) = thunk; + if (!virtual_offset && !DECL_NAME (thunk)) + finish_thunk (thunk, fixed_offset, NULL_TREE); + } + } + } /* Assume that we will produce a thunk that convert all the way to the final overrider, and not to an intermediate virtual base. */ @@ -5261,8 +5309,17 @@ finish_struct_1 (t) fn = TREE_CHAIN (fn), vindex += (TARGET_VTABLE_USES_DESCRIPTORS ? TARGET_VTABLE_USES_DESCRIPTORS : 1)) - if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST) - DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex); + { + tree fndecl = BV_FN (fn); + + if (DECL_THUNK_P (fndecl)) + /* A thunk. We should never be calling this entry directly + from this vtable -- we'd use the entry for the non + thunk base function. */ + DECL_VINDEX (fndecl) = NULL_TREE; + else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) + DECL_VINDEX (fndecl) = build_shared_int_cst (vindex); + } /* Add this class to the list of dynamic classes. */ dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes); @@ -7684,11 +7741,24 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) { tree delta; tree vcall_index; - tree fn; + tree fn, fn_original; 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)) + { + 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 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 @@ -7702,7 +7772,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) 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)) + if (look_for_overrides_here (BINFO_TYPE (b), fn_original)) break; /* The nearest definition is from a lost primary; clear the @@ -7726,10 +7796,14 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) /* You can't call an abstract virtual function; it's abstract. So, we replace these functions with __pure_virtual. */ - if (DECL_PURE_VIRTUAL_P (fn)) + if (DECL_PURE_VIRTUAL_P (fn_original)) fn = abort_fndecl; else if (!integer_zerop (delta) || vcall_index) - fn = make_thunk (fn, delta, vcall_index); + { + fn = make_thunk (fn, /*this_adjusting=*/1, delta, vcall_index); + if (!DECL_NAME (fn)) + finish_thunk (fn, delta, THUNK_VIRTUAL_OFFSET (fn)); + } /* Take the address of the function, considering it to be of an appropriate generic type. */ init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn); |