| |
| This patch is a quick backport of Nathan Sidwell's patch to fix PR c++/3145, |
| the infamous "virtual inheritance" bug. This affected especially KDE2 |
| (eg. artsd). |
| |
| Apply in the in GCC's toplevel source dir with: |
| |
| patch -p0 <contrib/PR3145.patch |
| |
| Franz Sirl <Franz.Sirl-kernel@lauterbach.com> |
| |
| |
| |
| 2001-12-04 Jason Merrill <jason@redhat.com> |
| |
| * init.c (resolve_offset_ref): Don't check access for the base |
| conversion to access a FIELD_DECL. |
| |
| 2001-11-22 Nathan Sidwell <nathan@codesourcery.com> |
| |
| PR g++/3145 |
| * class.c (build_vbase_pointer): Remove. |
| (build_vbase_path): Remove. |
| (build_base_path): New function. |
| * cp-tree.h (base_access, base_kind): New enumerations. |
| (build_base_path): Declare. |
| (convert_pointer_to_real): Remove. |
| (convert_pointer_to): Remove. |
| (lookup_base): Declare. |
| (convert_pointer_to_vbase): Remove. |
| * call.c (build_scoped_method_call): Use lookup_base & |
| build_base_path instead of convert_pointer_to_real, |
| get_base_distance & get_binfo. |
| (build_over_call): Likewise. |
| * cvt.c (cp_convert_to_pointer): Likewise. |
| (convert_to_pointer_force): Likewise. |
| (build_up_reference): Likewise. |
| (convert_pointer_to_real): Remove. |
| (convert_pointer_to): Remove. |
| * init.c (dfs_initialize_vtbl_ptrs): Use build_base_path |
| instead of convert_pointer_to_vbase & build_vbase_path. |
| (emit_base_init): Use build_base_path instead of |
| convert_pointer_to_real. |
| (expand_virtual_init): Lose unrequired conversions. |
| (resolve_offset_ref): Use lookup_base and build_base_path |
| instead of convert_pointer_to. |
| *rtti.c (build_dynamic_cast_1): Use lookup_base & |
| build_base_path instead of get_base_distance & build_vbase_path. |
| *search.c (get_vbase_1): Remove. |
| (get_vbase): Remove. |
| (convert_pointer_to_vbase): Remove. |
| (lookup_base_recursive): New function. |
| (lookup_base): New function. |
| * typeck.c (require_complete_type): Use lookup_base & |
| build_base_path instead of convert_pointer_to. |
| (build_component_ref): Likewise. |
| (build_x_function_call): Likewise. |
| (get_member_function_from_ptrfunc): Likewise. |
| (build_component_addr): Likewise. |
| * typeck2.c (build_scoped_ref): Likewise. |
| |
| 2001-07-31 Nathan Sidwell <nathan@codesourcery.com> |
| |
| The 3.0 ABI no longer has vbase pointer fields. |
| * cp-tree.h (VBASE_NAME, VBASE_NAME_FORMAT, VBASE_NAME_P, |
| FORMAT_VBASE_NAME): Remove. |
| * method.c (do_build_copy_constructor): Adjust. |
| (do_build_assign_ref): Adjust. |
| * search.c (lookup_field_r): Adjust. |
| * typeck.c (build_component_ref): Adjust. |
| |
| The 3.0 ABI always has a vtable pointer at the start of every |
| polymorphic class. |
| * rtti.c (build_headof_sub): Remove. |
| (build_headof): Adjust. |
| (get_tinfo_decl_dynamic): No need to check flag_rtti |
| here. Adjust. |
| (create_real_tinfo_var): Explain why we need a hidden name. |
| |
| 2001-07-20 Nathan Sidwell <nathan@codesourcery.com> |
| |
| Remove flag_vtable_thunk. It is always on for the 3.0 ABI. |
| * cp-tree.h (CPTI_DELTA2_IDENTIFIER): Remove. |
| (CPTI_INDEX_IDENTIFIER): Remove. |
| (CPT_PFN_OR_DELTA2_IDENTIFIER): Remove. |
| (delta2_identifier): Remove. |
| (index_identifier): Remove. |
| (pfn_or_delta2_identifier): Remove. |
| (flag_vtable_thunks): Remove. |
| (VTABLE_DELTA2_NAME): Remove. |
| (VTABLE_INDEX_NAME): Remove. |
| (FNADDR_FROM_VTABLE_ENTRY): Adjust. |
| (vfunc_ptr_type_node): Adjust. |
| (VTABLE_NAME_PREFIX): Adjust. |
| (build_vfn_ref): Lose first parameter. |
| (fixup_all_virtual_upcast_offsets): Remove. |
| * decl.c (initialize_predefined_identifiers): Remove |
| delta2_identifier, index_identifier, pfn_or_delta2_identifier. |
| (init_decl_processing): Remove no-vtable-thunk code. |
| * decl2.c (flag_vtable_thunks): Remove. |
| (mark_vtable_entries): Remove no-vtable-thunk code. |
| * error.c (dump_decl): Remove no-vtable-thunk code. |
| (dump_expr): Adjust ptr to member function code. |
| * init.c (initialize_vtable_ptrs): Remove no-vtable-thunk |
| code. |
| * rtti.c (build_headof): Remove no-vtable-thunk code. |
| (get_tinfo_decl_dynamic): Adjust build_vfn_ref call. |
| * search.c (get_base_distance): Remove expand_upcast_fixups case. |
| (virtual_context) Remove. |
| (expand_upcast_fixups): Remove. |
| (fixup_virtual_upcast_offsets): Remove. |
| (fixup_all_virtual_upcast_offsets): Remove. |
| * typeck.c (get_member_function_from_ptrfunc): Remove |
| no-vtable-thunk code. |
| * call.c (build_over_call): Adjust call to build_vfn_ref. |
| * class.c (build_vfn_ref): Lose first parameter. Remove |
| no-vtable-thunk code. |
| (build_rtti_vtbl_entries): Remove no-vtable-thunk code. |
| (build_vtable_entry): Remove no-vtable-thunk code. |
| |
| 2001-07-20 Nathan Sidwell <nathan@codesourcery.com> |
| |
| Remove old-abi remnants. Remove comments about old abi |
| behaviour. Remove refences to 'new-abi' in comments. |
| * cp-tree.h: Adjust comments. |
| (vbase_offsets_in_vtable_p): Delete. |
| (vcall_offsets_in_vtable_p): Delete. |
| (vptrs_present_everywhere_p): Delete. |
| (all_overridden_vfuns_in_vtables_p): Delete. |
| (merge_primary_and_secondary_vtables_p): Delete. |
| (TYPE_CONTAINS_VPTR_P): Adjust. |
| (VTT_NAME_PREFIX): Remove. |
| (CTOR_VTBL_NAME_PREFIX): Remove. |
| (init_vbase_pointers): Remove. |
| * class.c: Adjust coments. |
| (build_vbase_pointer_fields): Delete. |
| (build_vbase_pointer): Remove old-abi code. |
| (build_secondary_vtable): Likewise. |
| (modify_all_vtables): Likewise. |
| (create_vtable_ptr): Likewise. |
| (layout_class_type): Likewise. |
| (finish_struct_1): Likewise. |
| (finish_vtbls): Likewise. |
| (dfs_finish_vtbls): Delete. |
| (build_vbase_offset_vtbl_entries): Remove old-abi code. |
| * cvt.c: Adjust comments. |
| * decl.c: Adjust comments. |
| * decl2.c: Adjust comments. |
| * init.c: Adjust comments. |
| (construct_virtual_bases): Remove old-abi code. |
| * lang-specs.h: Remove -fno-new-abi. |
| * mangle.c: Adjust comments. |
| * rtti.c: Adjust comments. |
| (get_base_offset): Remove old-abi-code. |
| * search.c: Adjust comments. |
| (dfs_init_vbase_pointers): Remove. |
| (dfs_vtable_path_unmark): Remove. |
| (init_vbase_pointers): Remove. |
| * semantics.c: Adjust comments. |
| (emit_associated_thunks): Remove old-abi code. |
| * typeck.c: Adjust comments. |
| |
| Index: gcc/cp/call.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v |
| retrieving revision 1.255.2.20 |
| diff -u -p -r1.255.2.20 call.c |
| --- gcc/cp/call.c 2001/11/29 20:16:18 1.255.2.20 |
| +++ gcc/cp/call.c 2002/02/01 22:44:17 |
| @@ -288,7 +288,7 @@ build_scoped_method_call (exp, basetype, |
| |
| if (! binfo) |
| { |
| - binfo = get_binfo (basetype, type, 1); |
| + binfo = lookup_base (type, basetype, ba_check, NULL); |
| if (binfo == error_mark_node) |
| return error_mark_node; |
| if (! binfo) |
| @@ -298,9 +298,12 @@ build_scoped_method_call (exp, basetype, |
| if (binfo) |
| { |
| if (TREE_CODE (exp) == INDIRECT_REF) |
| - decl = build_indirect_ref |
| - (convert_pointer_to_real |
| - (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR); |
| + { |
| + decl = build_base_path (PLUS_EXPR, |
| + build_unary_op (ADDR_EXPR, exp, 0), |
| + binfo, 1); |
| + decl = build_indirect_ref (decl, NULL); |
| + } |
| else |
| decl = build_scoped_ref (exp, basetype); |
| |
| @@ -4126,7 +4129,9 @@ build_over_call (cand, args, flags) |
| So we can assume that anything passed as 'this' is non-null, and |
| optimize accordingly. */ |
| my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811); |
| - t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg)); |
| + t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))), |
| + TREE_TYPE (parmtype), ba_ignore, NULL); |
| + t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1); |
| converted_args = tree_cons (NULL_TREE, t, converted_args); |
| parm = TREE_CHAIN (parm); |
| arg = TREE_CHAIN (arg); |
| @@ -4300,16 +4305,19 @@ build_over_call (cand, args, flags) |
| if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0) |
| { |
| tree t, *p = &TREE_VALUE (converted_args); |
| - tree binfo = get_binfo |
| - (DECL_VIRTUAL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0); |
| - *p = convert_pointer_to_real (binfo, *p); |
| + tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)), |
| + DECL_VIRTUAL_CONTEXT (fn), |
| + ba_any, NULL); |
| + my_friendly_assert (binfo && binfo != error_mark_node, 20010730); |
| + |
| + *p = build_base_path (PLUS_EXPR, *p, binfo, 1); |
| if (TREE_SIDE_EFFECTS (*p)) |
| *p = save_expr (*p); |
| t = build_pointer_type (TREE_TYPE (fn)); |
| if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn))) |
| fn = build_java_interface_fn_ref (fn, *p); |
| else |
| - fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn)); |
| + fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn)); |
| TREE_TYPE (fn) = t; |
| } |
| else if (DECL_INLINE (fn)) |
| Index: gcc/cp/class.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v |
| retrieving revision 1.358.2.40 |
| diff -u -p -r1.358.2.40 class.c |
| --- gcc/cp/class.c 2002/01/03 11:39:44 1.358.2.40 |
| +++ gcc/cp/class.c 2002/02/01 22:44:24 |
| @@ -106,13 +106,11 @@ 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)); |
| static tree get_vtable_name PARAMS ((tree)); |
| static tree get_basefndecls PARAMS ((tree, tree)); |
| static int build_primary_vtable PARAMS ((tree, tree)); |
| static int build_secondary_vtable PARAMS ((tree, tree)); |
| -static tree dfs_finish_vtbls PARAMS ((tree, void *)); |
| static void finish_vtbls PARAMS ((tree)); |
| static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *)); |
| static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree)); |
| @@ -146,7 +144,6 @@ static bool build_base_field PARAMS ((re |
| splay_tree, tree)); |
| static bool build_base_fields PARAMS ((record_layout_info, int *, |
| splay_tree, tree)); |
| -static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *)); |
| static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree, |
| int *)); |
| static void check_methods PARAMS ((tree)); |
| @@ -237,277 +234,122 @@ int n_build_method_call = 0; |
| int n_inner_fields_searched = 0; |
| #endif |
| |
| -/* Virtual base class layout. */ |
| +/* Convert to or from a base subobject. EXPR is an expression of type |
| + `A' or `A*', an expression of type `B' or `B*' is returned. To |
| + convert A to a base B, CODE is PLUS_EXPR and BINFO is the binfo for |
| + the B base instance within A. To convert base A to derived B, CODE |
| + is MINUS_EXPR and BINFO is the binfo for the A instance within B. |
| + In this latter case, A must not be a morally virtual base of B. |
| + NONNULL is true if EXPR is known to be non-NULL (this is only |
| + needed when EXPR is of pointer type). CV qualifiers are preserved |
| + from EXPR. */ |
| |
| -/* Returns a list of virtual base class pointers as a chain of |
| - FIELD_DECLS. */ |
| - |
| -static tree |
| -build_vbase_pointer_fields (rli, empty_p) |
| - record_layout_info rli; |
| - int *empty_p; |
| -{ |
| - /* Chain to hold all the new FIELD_DECLs which point at virtual |
| - base classes. */ |
| - tree rec = rli->t; |
| - tree vbase_decls = NULL_TREE; |
| - tree binfos = TYPE_BINFO_BASETYPES (rec); |
| - int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec); |
| - tree decl; |
| - int i; |
| - |
| - /* Under the new ABI, there are no vbase pointers in the object. |
| - Instead, the offsets are stored in the vtable. */ |
| - if (vbase_offsets_in_vtable_p ()) |
| - return NULL_TREE; |
| - |
| - /* Loop over the baseclasses, adding vbase pointers as needed. */ |
| - for (i = 0; i < n_baseclasses; i++) |
| - { |
| - register tree base_binfo = TREE_VEC_ELT (binfos, i); |
| - register tree basetype = BINFO_TYPE (base_binfo); |
| - |
| - if (!COMPLETE_TYPE_P (basetype)) |
| - /* This error is now reported in xref_tag, thus giving better |
| - location information. */ |
| - continue; |
| - |
| - /* All basetypes are recorded in the association list of the |
| - derived type. */ |
| - |
| - if (TREE_VIA_VIRTUAL (base_binfo)) |
| - { |
| - int j; |
| - const char *name; |
| - |
| - /* The offset for a virtual base class is only used in computing |
| - virtual function tables and for initializing virtual base |
| - pointers. It is built once `get_vbase_types' is called. */ |
| - |
| - /* If this basetype can come from another vbase pointer |
| - without an additional indirection, we will share |
| - that pointer. If an indirection is involved, we |
| - make our own pointer. */ |
| - for (j = 0; j < n_baseclasses; j++) |
| - { |
| - tree other_base_binfo = TREE_VEC_ELT (binfos, j); |
| - if (! TREE_VIA_VIRTUAL (other_base_binfo) |
| - && binfo_for_vbase (basetype, BINFO_TYPE (other_base_binfo))) |
| - goto got_it; |
| - } |
| - FORMAT_VBASE_NAME (name, basetype); |
| - decl = build_vtbl_or_vbase_field (get_identifier (name), |
| - get_identifier (VTABLE_BASE), |
| - build_pointer_type (basetype), |
| - rec, |
| - basetype, |
| - empty_p); |
| - BINFO_VPTR_FIELD (base_binfo) = decl; |
| - TREE_CHAIN (decl) = vbase_decls; |
| - place_field (rli, decl); |
| - vbase_decls = decl; |
| - *empty_p = 0; |
| - |
| - got_it: |
| - /* The space this decl occupies has already been accounted for. */ |
| - ; |
| - } |
| - } |
| - |
| - return vbase_decls; |
| -} |
| - |
| -/* Returns a pointer to the virtual base class of EXP that has the |
| - indicated TYPE. EXP is of class type, not a pointer type. */ |
| - |
| -static tree |
| -build_vbase_pointer (exp, type) |
| - tree exp, type; |
| -{ |
| - if (vbase_offsets_in_vtable_p ()) |
| - { |
| - tree vbase; |
| - tree vbase_ptr; |
| - |
| - /* Find the shared copy of TYPE; that's where the vtable offset |
| - is recorded. */ |
| - vbase = binfo_for_vbase (type, TREE_TYPE (exp)); |
| - /* Find the virtual function table pointer. */ |
| - vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp)); |
| - /* Compute the location where the offset will lie. */ |
| - vbase_ptr = build (PLUS_EXPR, |
| - TREE_TYPE (vbase_ptr), |
| - vbase_ptr, |
| - BINFO_VPTR_FIELD (vbase)); |
| - vbase_ptr = build1 (NOP_EXPR, |
| - build_pointer_type (ptrdiff_type_node), |
| - vbase_ptr); |
| - /* Add the contents of this location to EXP. */ |
| - return build (PLUS_EXPR, |
| - build_pointer_type (type), |
| - build_unary_op (ADDR_EXPR, exp, /*noconvert=*/0), |
| - build1 (INDIRECT_REF, ptrdiff_type_node, vbase_ptr)); |
| - } |
| - else |
| - { |
| - char *name; |
| - FORMAT_VBASE_NAME (name, type); |
| - return build_component_ref (exp, get_identifier (name), NULL_TREE, 0); |
| - } |
| -} |
| - |
| -/* Build multi-level access to EXPR using hierarchy path PATH. |
| - CODE is PLUS_EXPR if we are going with the grain, |
| - and MINUS_EXPR if we are not (in which case, we cannot traverse |
| - virtual baseclass links). |
| - |
| - TYPE is the type we want this path to have on exit. |
| - |
| - NONNULL is non-zero if we know (for any reason) that EXPR is |
| - not, in fact, zero. */ |
| - |
| tree |
| -build_vbase_path (code, type, expr, path, nonnull) |
| +build_base_path (code, expr, binfo, nonnull) |
| enum tree_code code; |
| - tree type, expr, path; |
| + tree expr; |
| + tree binfo; |
| int nonnull; |
| { |
| - register int changed = 0; |
| - tree last = NULL_TREE, last_virtual = NULL_TREE; |
| + tree v_binfo = NULL_TREE; |
| + tree t; |
| + tree probe; |
| + tree offset; |
| + tree target_type; |
| + tree null_test = NULL; |
| + tree ptr_target_type; |
| int fixed_type_p; |
| - tree null_expr = 0, nonnull_expr; |
| - tree basetype; |
| - tree offset = integer_zero_node; |
| + int want_pointer = TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE; |
| |
| - if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE) |
| - return build1 (NOP_EXPR, type, expr); |
| + if (expr == error_mark_node || binfo == error_mark_node || !binfo) |
| + return error_mark_node; |
| + |
| + for (probe = binfo; probe; |
| + t = probe, probe = BINFO_INHERITANCE_CHAIN (probe)) |
| + if (!v_binfo && TREE_VIA_VIRTUAL (probe)) |
| + v_binfo = probe; |
| + |
| + probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr)); |
| + if (want_pointer) |
| + probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe)); |
| + |
| + my_friendly_assert (code == MINUS_EXPR |
| + ? same_type_p (BINFO_TYPE (binfo), probe) |
| + : code == PLUS_EXPR |
| + ? same_type_p (BINFO_TYPE (t), probe) |
| + : false, 20010723); |
| + |
| + if (code == MINUS_EXPR && v_binfo) |
| + { |
| + cp_error ("cannot convert from base `%T' to derived type `%T' via virtual base `%T'", |
| + BINFO_TYPE (binfo), BINFO_TYPE (t), BINFO_TYPE (v_binfo)); |
| + return error_mark_node; |
| + } |
| |
| - /* We could do better if we had additional logic to convert back to the |
| - unconverted type (the static type of the complete object), and then |
| - convert back to the type we want. Until that is done, we only optimize |
| - if the complete type is the same type as expr has. */ |
| fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull); |
| if (fixed_type_p < 0) |
| /* Virtual base layout is not fixed, even in ctors and dtors. */ |
| fixed_type_p = 0; |
| - |
| if (!fixed_type_p && TREE_SIDE_EFFECTS (expr)) |
| expr = save_expr (expr); |
| - nonnull_expr = expr; |
| - |
| - path = reverse_path (path); |
| - |
| - basetype = BINFO_TYPE (path); |
| - |
| - while (path) |
| + |
| + if (!want_pointer) |
| + expr = build_unary_op (ADDR_EXPR, expr, 0); |
| + else if (!nonnull) |
| + null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node); |
| + |
| + offset = BINFO_OFFSET (binfo); |
| + |
| + if (v_binfo && !fixed_type_p) |
| { |
| - if (TREE_VIA_VIRTUAL (TREE_VALUE (path))) |
| - { |
| - last_virtual = BINFO_TYPE (TREE_VALUE (path)); |
| - if (code == PLUS_EXPR) |
| - { |
| - changed = ! fixed_type_p; |
| - |
| - if (changed) |
| - { |
| - tree ind; |
| - |
| - /* We already check for ambiguous things in the caller, just |
| - find a path. */ |
| - if (last) |
| - { |
| - tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (nonnull_expr))), 0); |
| - nonnull_expr = convert_pointer_to_real (binfo, nonnull_expr); |
| - } |
| - ind = build_indirect_ref (nonnull_expr, NULL_PTR); |
| - nonnull_expr = build_vbase_pointer (ind, last_virtual); |
| - if (nonnull == 0 |
| - && TREE_CODE (type) == POINTER_TYPE |
| - && null_expr == NULL_TREE) |
| - { |
| - null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node); |
| - expr = build (COND_EXPR, build_pointer_type (last_virtual), |
| - build (EQ_EXPR, boolean_type_node, expr, |
| - integer_zero_node), |
| - null_expr, nonnull_expr); |
| - } |
| - } |
| - /* else we'll figure out the offset below. */ |
| + /* Going via virtual base V_BINFO. We need the static offset |
| + from V_BINFO to BINFO, and the dynamic offset from T to |
| + V_BINFO. That offset is an entry in T's vtable. */ |
| + tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL), |
| + TREE_TYPE (TREE_TYPE (expr))); |
| + |
| + v_binfo = binfo_for_vbase (BINFO_TYPE (v_binfo), BINFO_TYPE (t)); |
| + |
| + v_offset = build (PLUS_EXPR, TREE_TYPE (v_offset), |
| + v_offset, BINFO_VPTR_FIELD (v_binfo)); |
| + v_offset = build1 (NOP_EXPR, |
| + build_pointer_type (ptrdiff_type_node), |
| + v_offset); |
| + v_offset = build_indirect_ref (v_offset, NULL); |
| + |
| + offset = cp_convert (ptrdiff_type_node, |
| + size_diffop (offset, BINFO_OFFSET (v_binfo))); |
| |
| - /* Happens in the case of parse errors. */ |
| - if (nonnull_expr == error_mark_node) |
| - return error_mark_node; |
| - } |
| - else |
| - { |
| - cp_error ("cannot cast up from virtual baseclass `%T'", |
| - last_virtual); |
| - return error_mark_node; |
| - } |
| - } |
| - last = TREE_VALUE (path); |
| - path = TREE_CHAIN (path); |
| + if (!integer_zerop (offset)) |
| + offset = build (code, ptrdiff_type_node, v_offset, offset); |
| + else |
| + offset = v_offset; |
| } |
| - /* LAST is now the last basetype assoc on the path. */ |
| |
| - /* A pointer to a virtual base member of a non-null object |
| - is non-null. Therefore, we only need to test for zeroness once. |
| - Make EXPR the canonical expression to deal with here. */ |
| - if (null_expr) |
| - { |
| - TREE_OPERAND (expr, 2) = nonnull_expr; |
| - TREE_TYPE (expr) = TREE_TYPE (TREE_OPERAND (expr, 1)) |
| - = TREE_TYPE (nonnull_expr); |
| - } |
| - else |
| - expr = nonnull_expr; |
| + target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (t); |
| + |
| + target_type = cp_build_qualified_type |
| + (target_type, CP_TYPE_QUALS (TREE_TYPE (TREE_TYPE (expr)))); |
| + ptr_target_type = build_pointer_type (target_type); |
| + if (want_pointer) |
| + target_type = ptr_target_type; |
| + |
| + expr = build1 (NOP_EXPR, ptr_target_type, expr); |
| |
| - /* If we go through any virtual base pointers, make sure that |
| - casts to BASETYPE from the last virtual base class use |
| - the right value for BASETYPE. */ |
| - if (changed) |
| - { |
| - tree intype = TREE_TYPE (TREE_TYPE (expr)); |
| - |
| - if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last)) |
| - offset |
| - = BINFO_OFFSET (get_binfo (last, TYPE_MAIN_VARIANT (intype), 0)); |
| - } |
| + if (!integer_zerop (offset)) |
| + expr = build (code, ptr_target_type, expr, offset); |
| else |
| - offset = BINFO_OFFSET (last); |
| - |
| - if (! integer_zerop (offset)) |
| - { |
| - /* Bash types to make the backend happy. */ |
| - offset = cp_convert (type, offset); |
| - |
| - /* If expr might be 0, we need to preserve that zeroness. */ |
| - if (nonnull == 0) |
| - { |
| - if (null_expr) |
| - TREE_TYPE (null_expr) = type; |
| - else |
| - null_expr = build1 (NOP_EXPR, type, integer_zero_node); |
| - if (TREE_SIDE_EFFECTS (expr)) |
| - expr = save_expr (expr); |
| - |
| - return build (COND_EXPR, type, |
| - build (EQ_EXPR, boolean_type_node, expr, integer_zero_node), |
| - null_expr, |
| - build (code, type, expr, offset)); |
| - } |
| - else return build (code, type, expr, offset); |
| - } |
| + null_test = NULL; |
| + |
| + if (!want_pointer) |
| + expr = build_indirect_ref (expr, NULL); |
| |
| - /* Cannot change the TREE_TYPE of a NOP_EXPR here, since it may |
| - be used multiple times in initialization of multiple inheritance. */ |
| - if (null_expr) |
| - { |
| - TREE_TYPE (expr) = type; |
| - return expr; |
| - } |
| - else |
| - return build1 (NOP_EXPR, type, expr); |
| + if (null_test) |
| + expr = build (COND_EXPR, target_type, null_test, |
| + build1 (NOP_EXPR, target_type, integer_zero_node), |
| + expr); |
| + |
| + return expr; |
| } |
| |
| |
| @@ -533,8 +375,6 @@ build_vtable_entry_ref (basetype, vtbl, |
| s = build_tree_list (build_string (1, "s"), s); |
| |
| i = build_array_ref (vtbl, idx); |
| - if (!flag_vtable_thunks) |
| - i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0); |
| i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0)); |
| i2 = build_array_ref (vtbl, build_int_2(0,0)); |
| i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0)); |
| @@ -603,8 +443,8 @@ build_vtbl_ref (instance, idx) |
| { |
| vtbl = TYPE_BINFO_VTABLE (basetype); |
| /* Knowing the dynamic type of INSTANCE we can easily obtain |
| - the correct vtable entry. In the new ABI, we resolve |
| - this back to be in terms of the primary vtable. */ |
| + the correct vtable entry. We resolve this back to be in |
| + terms of the primary vtable. */ |
| if (TREE_CODE (vtbl) == PLUS_EXPR) |
| { |
| idx = fold (build (PLUS_EXPR, |
| @@ -632,45 +472,22 @@ build_vtbl_ref (instance, idx) |
| } |
| |
| /* Given an object INSTANCE, return an expression which yields the |
| - virtual function corresponding to INDEX. There are many special |
| - cases for INSTANCE which we take care of here, mainly to avoid |
| - creating extra tree nodes when we don't have to. */ |
| + virtual function corresponding to IDX. */ |
| |
| tree |
| -build_vfn_ref (ptr_to_instptr, instance, idx) |
| - tree *ptr_to_instptr, instance; |
| +build_vfn_ref (instance, idx) |
| + tree instance; |
| tree idx; |
| { |
| tree aref = build_vtbl_ref (instance, idx); |
| - |
| - /* When using thunks, there is no extra delta, and we get the pfn |
| - directly. */ |
| - if (flag_vtable_thunks) |
| - { |
| - /* When using function descriptors, the address of the |
| - vtable entry is treated as a function pointer. */ |
| - if (TARGET_VTABLE_USES_DESCRIPTORS) |
| - return build1 (NOP_EXPR, TREE_TYPE (aref), |
| - build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1)); |
| - |
| - return aref; |
| - } |
| - |
| - if (ptr_to_instptr) |
| - { |
| - /* Save the intermediate result in a SAVE_EXPR so we don't have to |
| - compute each component of the virtual function pointer twice. */ |
| - if (TREE_CODE (aref) == INDIRECT_REF) |
| - TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); |
| |
| - *ptr_to_instptr |
| - = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), |
| - *ptr_to_instptr, |
| - cp_convert (ptrdiff_type_node, |
| - build_component_ref (aref, delta_identifier, NULL_TREE, 0))); |
| - } |
| + /* When using function descriptors, the address of the |
| + vtable entry is treated as a function pointer. */ |
| + if (TARGET_VTABLE_USES_DESCRIPTORS) |
| + return build1 (NOP_EXPR, TREE_TYPE (aref), |
| + build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1)); |
| |
| - return build_component_ref (aref, pfn_identifier, NULL_TREE, 0); |
| + return aref; |
| } |
| |
| /* Return the name of the virtual function table (as an IDENTIFIER_NODE) |
| @@ -826,15 +643,15 @@ build_primary_vtable (binfo, type) |
| return 1; |
| } |
| |
| -/* Give TYPE a new virtual function table which is initialized |
| +/* Give BINFO a new virtual function table which is initialized |
| with a skeleton-copy of its original initialization. The only |
| entry that changes is the `delta' entry, so we can really |
| share a lot of structure. |
| |
| - FOR_TYPE is the derived type which caused this table to |
| + FOR_TYPE is the most derived type which caused this table to |
| be needed. |
| |
| - BINFO is the type association which provided TYPE for FOR_TYPE. |
| + Returns non-zero if we haven't met BINFO before. |
| |
| The order in which vtables are built (by calling this function) for |
| an object must remain the same, otherwise a binary incompatibility |
| @@ -844,143 +661,28 @@ static int |
| build_secondary_vtable (binfo, for_type) |
| tree binfo, for_type; |
| { |
| - tree basetype; |
| - tree orig_decl = BINFO_VTABLE (binfo); |
| - tree name; |
| - tree new_decl; |
| - tree offset; |
| - tree path = binfo; |
| - char *buf; |
| - const char *buf2; |
| - char joiner = '_'; |
| - int i; |
| - |
| -#ifdef JOINER |
| - joiner = JOINER; |
| -#endif |
| - |
| - if (TREE_VIA_VIRTUAL (binfo)) |
| - my_friendly_assert (binfo == binfo_for_vbase (BINFO_TYPE (binfo), |
| - current_class_type), |
| - 170); |
| + my_friendly_assert (binfo == CANONICAL_BINFO (binfo, for_type), 20010605); |
| |
| - if (BINFO_NEW_VTABLE_MARKED (binfo, current_class_type)) |
| + if (BINFO_NEW_VTABLE_MARKED (binfo, for_type)) |
| /* We already created a vtable for this base. There's no need to |
| do it again. */ |
| return 0; |
| |
| /* Remember that we've created a vtable for this BINFO, so that we |
| don't try to do so again. */ |
| - SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type); |
| + SET_BINFO_NEW_VTABLE_MARKED (binfo, for_type); |
| |
| /* Make fresh virtual list, so we can smash it later. */ |
| BINFO_VIRTUALS (binfo) = copy_virtuals (binfo); |
| - |
| - my_friendly_assert (binfo == CANONICAL_BINFO (binfo, for_type), 20010605); |
| - offset = BINFO_OFFSET (binfo); |
| - |
| - /* In the new ABI, secondary vtables are laid out as part of the |
| - same structure as the primary vtable. */ |
| - if (merge_primary_and_secondary_vtables_p ()) |
| - { |
| - BINFO_VTABLE (binfo) = NULL_TREE; |
| - return 1; |
| - } |
| - |
| - /* Create the declaration for the secondary vtable. */ |
| - basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo)); |
| - buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype); |
| - i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1; |
| - |
| - /* We know that the vtable that we are going to create doesn't exist |
| - yet in the global namespace, and when we finish, it will be |
| - pushed into the global namespace. In complex MI hierarchies, we |
| - have to loop while the name we are thinking of adding is globally |
| - defined, adding more name components to the vtable name as we |
| - loop, until the name is unique. This is because in complex MI |
| - cases, we might have the same base more than once. This means |
| - that the order in which this function is called for vtables must |
| - remain the same, otherwise binary compatibility can be |
| - compromised. */ |
| - |
| - while (1) |
| - { |
| - char *buf1 = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (for_type) |
| - + 1 + i); |
| - char *new_buf2; |
| - |
| - sprintf (buf1, "%s%c%s", TYPE_ASSEMBLER_NAME_STRING (for_type), joiner, |
| - buf2); |
| - buf = (char *) alloca (strlen (VTABLE_NAME_PREFIX) + strlen (buf1) + 1); |
| - sprintf (buf, "%s%s", VTABLE_NAME_PREFIX, buf1); |
| - name = get_identifier (buf); |
| - |
| - /* If this name doesn't clash, then we can use it, otherwise |
| - we add more to the name until it is unique. */ |
| - |
| - if (! IDENTIFIER_GLOBAL_VALUE (name)) |
| - break; |
| - |
| - /* Set values for next loop through, if the name isn't unique. */ |
| - |
| - path = BINFO_INHERITANCE_CHAIN (path); |
| - |
| - /* We better not run out of stuff to make it unique. */ |
| - my_friendly_assert (path != NULL_TREE, 368); |
| - |
| - basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (path)); |
| - |
| - if (for_type == basetype) |
| - { |
| - /* If we run out of basetypes in the path, we have already |
| - found created a vtable with that name before, we now |
| - resort to tacking on _%d to distinguish them. */ |
| - int j = 2; |
| - i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i + 1 + 3; |
| - buf1 = (char *) alloca (i); |
| - do { |
| - sprintf (buf1, "%s%c%s%c%d", |
| - TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, |
| - buf2, joiner, j); |
| - buf = (char *) alloca (strlen (VTABLE_NAME_PREFIX) |
| - + strlen (buf1) + 1); |
| - sprintf (buf, "%s%s", VTABLE_NAME_PREFIX, buf1); |
| - name = get_identifier (buf); |
| - |
| - /* If this name doesn't clash, then we can use it, |
| - otherwise we add something different to the name until |
| - it is unique. */ |
| - } while (++j <= 999 && IDENTIFIER_GLOBAL_VALUE (name)); |
| - |
| - /* Hey, they really like MI don't they? Increase the 3 |
| - above to 6, and the 999 to 999999. :-) */ |
| - my_friendly_assert (j <= 999, 369); |
| - |
| - break; |
| - } |
| |
| - i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i; |
| - new_buf2 = (char *) alloca (i); |
| - sprintf (new_buf2, "%s%c%s", |
| - TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, buf2); |
| - buf2 = new_buf2; |
| - } |
| - |
| - new_decl = build_vtable (for_type, name, TREE_TYPE (orig_decl)); |
| - DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl); |
| - DECL_USER_ALIGN (new_decl) = DECL_USER_ALIGN (orig_decl); |
| - BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl); |
| - |
| -#ifdef GATHER_STATISTICS |
| - n_vtables += 1; |
| - n_vtable_elems += list_length (BINFO_VIRTUALS (binfo)); |
| -#endif |
| - |
| + /* Secondary vtables are laid out as part of the same structure as |
| + the primary vtable. */ |
| + BINFO_VTABLE (binfo) = NULL_TREE; |
| return 1; |
| } |
| |
| /* Create a new vtable for BINFO which is the hierarchy dominated by |
| - T. */ |
| + T. Return non-zero if we actually created a new vtable. */ |
| |
| static int |
| make_new_vtable (t, binfo) |
| @@ -1965,9 +1667,8 @@ determine_primary_base (t, vfuns_p) |
| if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) |
| CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype); |
| |
| - /* A virtual baseclass can't be the primary base under the |
| - old ABI. And under the new ABI we still prefer a |
| - non-virtual base. */ |
| + /* We prefer a non-virtual base, although a virtual one will |
| + do. */ |
| if (TREE_VIA_VIRTUAL (base_binfo)) |
| continue; |
| |
| @@ -2036,9 +1737,8 @@ determine_primary_base (t, vfuns_p) |
| } |
| } |
| |
| - /* The new ABI allows for the use of a "nearly-empty" virtual base |
| - class as the primary base class if no non-virtual polymorphic |
| - base can be found. */ |
| + /* A "nearly-empty" virtual base class can be the primary base |
| + class, if no non-virtual polymorphic base can be found. */ |
| if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) |
| { |
| /* If not NULL, this is the best primary base candidate we have |
| @@ -2921,9 +2621,6 @@ dfs_modify_vtables (binfo, data) |
| |
| t = (tree) data; |
| |
| - /* If we're supporting RTTI then we always need a new vtable to |
| - point to the RTTI information. Under the new ABI we may need |
| - a new vtable to contain vcall and vbase offsets. */ |
| make_new_vtable (t, binfo); |
| |
| /* Now, go through each of the virtual functions in the virtual |
| @@ -2960,10 +2657,9 @@ modify_all_vtables (t, vfuns_p, overridd |
| int *vfuns_p; |
| tree overridden_virtuals; |
| { |
| - tree binfo; |
| + tree binfo = TYPE_BINFO (t); |
| + tree *fnsp; |
| |
| - binfo = TYPE_BINFO (t); |
| - |
| /* Update all of the vtables. */ |
| dfs_walk (binfo, |
| dfs_modify_vtables, |
| @@ -2971,43 +2667,35 @@ modify_all_vtables (t, vfuns_p, overridd |
| t); |
| dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t); |
| |
| - /* If we should include overriding functions for secondary vtables |
| - in our primary vtable, add them now. */ |
| - if (all_overridden_vfuns_in_vtables_p ()) |
| + /* Include overriding functions for secondary vtables in our primary |
| + vtable. */ |
| + for (fnsp = &overridden_virtuals; *fnsp; ) |
| { |
| - tree *fnsp = &overridden_virtuals; |
| + tree fn = TREE_VALUE (*fnsp); |
| |
| - while (*fnsp) |
| + if (!BINFO_VIRTUALS (binfo) |
| + || !value_member (fn, BINFO_VIRTUALS (binfo))) |
| { |
| - tree fn = TREE_VALUE (*fnsp); |
| - |
| - if (!BINFO_VIRTUALS (binfo) |
| - || !value_member (fn, BINFO_VIRTUALS (binfo))) |
| - { |
| - /* Set the vtable index. */ |
| - set_vindex (fn, vfuns_p); |
| - /* We don't need to convert to a base class when calling |
| - this function. */ |
| - DECL_VIRTUAL_CONTEXT (fn) = t; |
| - |
| - /* We don't need to adjust the `this' pointer when |
| - calling this function. */ |
| - BV_DELTA (*fnsp) = integer_zero_node; |
| - BV_VCALL_INDEX (*fnsp) = NULL_TREE; |
| - |
| - /* This is an overridden function not already in our |
| - vtable. Keep it. */ |
| - fnsp = &TREE_CHAIN (*fnsp); |
| - } |
| - else |
| - /* We've already got an entry for this function. Skip |
| - it. */ |
| - *fnsp = TREE_CHAIN (*fnsp); |
| + /* Set the vtable index. */ |
| + set_vindex (fn, vfuns_p); |
| + /* We don't need to convert to a base class when calling |
| + this function. */ |
| + DECL_VIRTUAL_CONTEXT (fn) = t; |
| + |
| + /* We don't need to adjust the `this' pointer when |
| + calling this function. */ |
| + BV_DELTA (*fnsp) = integer_zero_node; |
| + BV_VCALL_INDEX (*fnsp) = NULL_TREE; |
| + |
| + /* This is an overridden function not already in our |
| + vtable. Keep it. */ |
| + fnsp = &TREE_CHAIN (*fnsp); |
| } |
| + else |
| + /* We've already got an entry for this function. Skip it. */ |
| + *fnsp = TREE_CHAIN (*fnsp); |
| } |
| - else |
| - overridden_virtuals = NULL_TREE; |
| - |
| + |
| return overridden_virtuals; |
| } |
| |
| @@ -4222,8 +3910,7 @@ build_base_fields (rli, empty_p, offsets |
| int i; |
| bool atend = 0; |
| |
| - /* Under the new ABI, the primary base class is always allocated |
| - first. */ |
| + /* The primary base class is always allocated first. */ |
| if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec)) |
| build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), |
| empty_p, offsets, t); |
| @@ -4235,8 +3922,8 @@ build_base_fields (rli, empty_p, offsets |
| |
| base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i); |
| |
| - /* Under the new ABI, the primary base was already allocated |
| - above, so we don't need to allocate it again here. */ |
| + /* The primary base was already allocated above, so we don't |
| + need to allocate it again here. */ |
| if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec)) |
| continue; |
| |
| @@ -4722,9 +4409,7 @@ create_vtable_ptr (t, empty_p, vfuns_p, |
| here. Even if there weren't any new virtual functions, we might need a |
| new virtual function table if we're supposed to include vptrs in |
| all classes that need them. */ |
| - if (!TYPE_VFIELD (t) |
| - && (*vfuns_p |
| - || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))) |
| + if (!TYPE_VFIELD (t) && (*vfuns_p || TYPE_CONTAINS_VPTR_P (t))) |
| { |
| /* We build this decl with vtbl_ptr_type_node, which is a |
| `vtable_entry_type*'. It might seem more precise to use |
| @@ -4929,10 +4614,8 @@ layout_virtual_bases (t, offsets) |
| TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT); |
| |
| /* Go through the virtual bases, allocating space for each virtual |
| - base that is not already a primary base class. Under the old |
| - ABI, these are allocated according to a depth-first left-to-right |
| - postorder traversal; in the new ABI, inheritance graph order is |
| - used instead. */ |
| + base that is not already a primary base class. These are |
| + allocated in inheritance graph order. */ |
| for (vbases = TYPE_BINFO (t); |
| vbases; |
| vbases = TREE_CHAIN (vbases)) |
| @@ -4959,8 +4642,8 @@ layout_virtual_bases (t, offsets) |
| appropriately aligned offset. */ |
| dsize = CEIL (dsize, desired_align) * desired_align; |
| |
| - /* Under the new ABI, we try to squish empty virtual bases in |
| - just like ordinary empty bases. */ |
| + /* We try to squish empty virtual bases in just like |
| + ordinary empty bases. */ |
| if (is_empty_class (basetype)) |
| layout_empty_base (vbase, |
| size_int (CEIL (dsize, BITS_PER_UNIT)), |
| @@ -5142,8 +4825,7 @@ layout_class_type (t, empty_p, vfuns_p, |
| vptr = create_vtable_ptr (t, empty_p, vfuns_p, |
| new_virtuals_p, overridden_virtuals_p); |
| |
| - /* Under the new ABI, the vptr is always the first thing in the |
| - class. */ |
| + /* The vptr is always the first thing in the class. */ |
| if (vptr) |
| { |
| TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t)); |
| @@ -5156,10 +4838,6 @@ layout_class_type (t, empty_p, vfuns_p, |
| if (build_base_fields (rli, empty_p, empty_base_offsets, t)) |
| CLASSTYPE_NEARLY_EMPTY_P (t) = 0; |
| |
| - /* Add pointers to all of our virtual base-classes. */ |
| - TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p), |
| - TYPE_FIELDS (t)); |
| - |
| /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus, |
| we have to save this before we zap TYPE_NONCOPIED_PARTS. */ |
| fixup_inline_methods (t); |
| @@ -5181,10 +4859,8 @@ layout_class_type (t, empty_p, vfuns_p, |
| type = TREE_TYPE (field); |
| |
| /* If this field is a bit-field whose width is greater than its |
| - type, then there are some special rules for allocating it |
| - under the new ABI. Under the old ABI, there were no special |
| - rules, but the back-end can't handle bitfields longer than a |
| - `long long', so we use the same mechanism. */ |
| + type, then there are some special rules for allocating |
| + it. */ |
| if (DECL_C_BIT_FIELD (field) |
| && INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field))) |
| { |
| @@ -5249,10 +4925,10 @@ layout_class_type (t, empty_p, vfuns_p, |
| } |
| |
| /* We make all structures have at least one element, so that they |
| - have non-zero size. In the new ABI, the class may be empty even |
| - if it has basetypes. Therefore, we add the fake field after all |
| - the other fields; if there are already FIELD_DECLs on the list, |
| - their offsets will not be disturbed. */ |
| + have non-zero size. The class may be empty even if it has |
| + basetypes. Therefore, we add the fake field after all the other |
| + fields; if there are already FIELD_DECLs on the list, their |
| + offsets will not be disturbed. */ |
| if (!eoc && *empty_p) |
| { |
| tree padding; |
| @@ -5413,9 +5089,7 @@ finish_struct_1 (t) |
| = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t)); |
| |
| /* If necessary, create the primary vtable for this class. */ |
| - if (new_virtuals |
| - || overridden_virtuals |
| - || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())) |
| + if (new_virtuals || overridden_virtuals || TYPE_CONTAINS_VPTR_P (t)) |
| { |
| new_virtuals = nreverse (new_virtuals); |
| /* We must enter these virtuals into the table. */ |
| @@ -5727,11 +5401,12 @@ fixed_type_or_null (instance, nonnull, c |
| } |
| } |
| |
| -/* Return non-zero if the dynamic type of INSTANCE is known, and equivalent |
| - to the static type. We also handle the case where INSTANCE is really |
| - a pointer. Return negative if this is a ctor/dtor. There the dynamic type |
| - is known, but this might not be the most derived base of the original object, |
| - and hence virtual bases may not be layed out according to this type. |
| +/* Return non-zero if the dynamic type of INSTANCE is known, and |
| + equivalent to the static type. We also handle the case where |
| + INSTANCE is really a pointer. Return negative if this is a |
| + ctor/dtor. There the dynamic type is known, but this might not be |
| + the most derived base of the original object, and hence virtual |
| + bases may not be layed out according to this type. |
| |
| Used to determine whether the virtual function table is needed |
| or not. |
| @@ -6783,10 +6458,9 @@ note_name_declared_in_class (name, decl) |
| } |
| } |
| |
| -/* Returns the VAR_DECL for the complete vtable associated with |
| - BINFO. (Under the new ABI, secondary vtables are merged with |
| - primary vtables; this function will return the VAR_DECL for the |
| - primary vtable.) */ |
| +/* Returns the VAR_DECL for the complete vtable associated with BINFO. |
| + Secondary vtables are merged with primary vtables; this function |
| + will return the VAR_DECL for the primary vtable. */ |
| |
| tree |
| get_vtbl_decl_for_binfo (binfo) |
| @@ -7134,77 +6808,47 @@ static void |
| finish_vtbls (t) |
| tree t; |
| { |
| - if (merge_primary_and_secondary_vtables_p ()) |
| - { |
| - tree list; |
| - tree vbase; |
| - int i; |
| - |
| - /* Under the new ABI, we lay out the primary and secondary |
| - vtables in one contiguous vtable. The primary vtable is |
| - first, followed by the non-virtual secondary vtables in |
| - inheritance graph order. */ |
| - list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE); |
| - accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t), |
| - TYPE_BINFO (t), t, list); |
| - /* Then come the virtual bases, also in inheritance graph |
| - order. */ |
| - for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase)) |
| - { |
| - tree real_base; |
| - |
| - if (!TREE_VIA_VIRTUAL (vbase)) |
| - continue; |
| - |
| - /* Although we walk in inheritance order, that might not get the |
| - canonical base. */ |
| - real_base = binfo_for_vbase (BINFO_TYPE (vbase), t); |
| - |
| - accumulate_vtbl_inits (real_base, real_base, |
| - TYPE_BINFO (t), t, list); |
| - } |
| + tree list; |
| + tree vbase; |
| + int i; |
| |
| - /* Fill in BINFO_VPTR_FIELD in the immediate binfos for our virtual |
| - base classes, for the benefit of the debugging backends. */ |
| - for (i = 0; i < BINFO_N_BASETYPES (TYPE_BINFO (t)); ++i) |
| - { |
| - tree base = BINFO_BASETYPE (TYPE_BINFO (t), i); |
| - if (TREE_VIA_VIRTUAL (base)) |
| - { |
| - tree vbase = binfo_for_vbase (BINFO_TYPE (base), t); |
| - BINFO_VPTR_FIELD (base) = BINFO_VPTR_FIELD (vbase); |
| - } |
| - } |
| + /* We lay out the primary and secondary vtables in one contiguous |
| + vtable. The primary vtable is first, followed by the non-virtual |
| + secondary vtables in inheritance graph order. */ |
| + list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE); |
| + accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t), |
| + TYPE_BINFO (t), t, list); |
| |
| - if (TYPE_BINFO_VTABLE (t)) |
| - initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list)); |
| - } |
| - else |
| + /* Then come the virtual bases, also in inheritance graph order. */ |
| + for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase)) |
| { |
| - dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, |
| - dfs_unmarked_real_bases_queue_p, t); |
| - dfs_walk (TYPE_BINFO (t), dfs_unmark, |
| - dfs_marked_real_bases_queue_p, t); |
| - } |
| -} |
| + tree real_base; |
| |
| -/* Called from finish_vtbls via dfs_walk. */ |
| + if (!TREE_VIA_VIRTUAL (vbase)) |
| + continue; |
| |
| -static tree |
| -dfs_finish_vtbls (binfo, data) |
| - tree binfo; |
| - void *data; |
| -{ |
| - tree t = (tree) data; |
| + /* Although we walk in inheritance order, that might not get the |
| + canonical base. */ |
| + real_base = binfo_for_vbase (BINFO_TYPE (vbase), t); |
| |
| - if (BINFO_NEW_VTABLE_MARKED (binfo, t)) |
| - initialize_vtable (binfo, |
| - build_vtbl_initializer (binfo, binfo, t, |
| - TYPE_BINFO (t), NULL)); |
| + accumulate_vtbl_inits (real_base, real_base, |
| + TYPE_BINFO (t), t, list); |
| + } |
| |
| - SET_BINFO_MARKED (binfo); |
| + /* Fill in BINFO_VPTR_FIELD in the immediate binfos for our virtual |
| + base classes, for the benefit of the debugging backends. */ |
| + for (i = 0; i < BINFO_N_BASETYPES (TYPE_BINFO (t)); ++i) |
| + { |
| + tree base = BINFO_BASETYPE (TYPE_BINFO (t), i); |
| + if (TREE_VIA_VIRTUAL (base)) |
| + { |
| + tree vbase = binfo_for_vbase (BINFO_TYPE (base), t); |
| + BINFO_VPTR_FIELD (base) = BINFO_VPTR_FIELD (vbase); |
| + } |
| + } |
| |
| - return NULL_TREE; |
| + if (TYPE_BINFO_VTABLE (t)) |
| + initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list)); |
| } |
| |
| /* Initialize the vtable for BINFO with the INITS. */ |
| @@ -7677,9 +7321,8 @@ accumulate_vtbl_inits (binfo, orig_binfo |
| } |
| } |
| |
| -/* Called from accumulate_vtbl_inits when using the new ABI. |
| - Accumulates the vtable initializers for all of the vtables into |
| - TREE_VALUE (DATA). Returns the initializers for the BINFO vtable. */ |
| +/* Called from accumulate_vtbl_inits. Returns the initializers for |
| + the BINFO vtable. */ |
| |
| static tree |
| dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l) |
| @@ -7987,11 +7630,6 @@ build_vbase_offset_vtbl_entries (binfo, |
| tree t; |
| tree non_primary_binfo; |
| |
| - /* Under the old ABI, pointers to virtual bases are stored in each |
| - object. */ |
| - if (!vbase_offsets_in_vtable_p ()) |
| - return; |
| - |
| /* If there are no virtual baseclasses, then there is nothing to |
| do. */ |
| if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) |
| @@ -8093,11 +7731,6 @@ build_vcall_offset_vtbl_entries (binfo, |
| tree binfo; |
| vtbl_init_data *vid; |
| { |
| - /* Under the old ABI, the adjustments to the `this' pointer were made |
| - elsewhere. */ |
| - if (!vcall_offsets_in_vtable_p ()) |
| - return; |
| - |
| /* We only need these entries if this base is a virtual base. */ |
| if (!TREE_VIA_VIRTUAL (binfo)) |
| return; |
| @@ -8352,16 +7985,12 @@ build_rtti_vtbl_entries (binfo, vid) |
| vid->last_init = &TREE_CHAIN (*vid->last_init); |
| |
| /* Add the offset-to-top entry. It comes earlier in the vtable that |
| - the the typeinfo entry. */ |
| - if (flag_vtable_thunks) |
| - { |
| - /* Convert the offset to look like a function pointer, so that |
| - we can put it in the vtable. */ |
| - init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); |
| - TREE_CONSTANT (init) = 1; |
| - *vid->last_init = build_tree_list (NULL_TREE, init); |
| - vid->last_init = &TREE_CHAIN (*vid->last_init); |
| - } |
| + the the typeinfo entry. Convert the offset to look like a |
| + function pointer, so that we can put it in the vtable. */ |
| + init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); |
| + TREE_CONSTANT (init) = 1; |
| + *vid->last_init = build_tree_list (NULL_TREE, init); |
| + vid->last_init = &TREE_CHAIN (*vid->last_init); |
| } |
| |
| /* Build an entry in the virtual function table. DELTA is the offset |
| @@ -8378,55 +8007,20 @@ build_vtable_entry (delta, vcall_index, |
| tree vcall_index; |
| tree entry; |
| { |
| - if (flag_vtable_thunks) |
| - { |
| - tree fn; |
| + tree fn; |
| |
| - fn = TREE_OPERAND (entry, 0); |
| - if ((!integer_zerop (delta) || vcall_index != NULL_TREE) |
| - && fn != abort_fndecl |
| - && !DECL_TINFO_FN_P (fn)) |
| - { |
| - entry = make_thunk (entry, delta, vcall_index); |
| - entry = build1 (ADDR_EXPR, vtable_entry_type, entry); |
| - TREE_READONLY (entry) = 1; |
| - TREE_CONSTANT (entry) = 1; |
| - } |
| -#ifdef GATHER_STATISTICS |
| - n_vtable_entries += 1; |
| -#endif |
| - return entry; |
| - } |
| - else |
| + fn = TREE_OPERAND (entry, 0); |
| + if ((!integer_zerop (delta) || vcall_index != NULL_TREE) |
| + && fn != abort_fndecl |
| + && !DECL_TINFO_FN_P (fn)) |
| { |
| - tree elems = tree_cons (NULL_TREE, delta, |
| - tree_cons (NULL_TREE, integer_zero_node, |
| - build_tree_list (NULL_TREE, entry))); |
| - tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems); |
| - |
| - /* We don't use vcall offsets when not using vtable thunks. */ |
| - my_friendly_assert (vcall_index == NULL_TREE, 20000125); |
| - |
| - /* DELTA used to be constructed by `size_int' and/or size_binop, |
| - which caused overflow problems when it was negative. That should |
| - be fixed now. */ |
| - |
| - if (! int_fits_type_p (delta, delta_type_node)) |
| - { |
| - if (flag_huge_objects) |
| - sorry ("object size exceeds built-in limit for virtual function table implementation"); |
| - else |
| - sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects"); |
| - } |
| - |
| - TREE_CONSTANT (entry) = 1; |
| - TREE_STATIC (entry) = 1; |
| + entry = make_thunk (entry, delta, vcall_index); |
| + entry = build1 (ADDR_EXPR, vtable_entry_type, entry); |
| TREE_READONLY (entry) = 1; |
| - |
| + TREE_CONSTANT (entry) = 1; |
| + } |
| #ifdef GATHER_STATISTICS |
| - n_vtable_entries += 1; |
| + n_vtable_entries += 1; |
| #endif |
| - |
| - return entry; |
| - } |
| + return entry; |
| } |
| Index: gcc/cp/cp-tree.h |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v |
| retrieving revision 1.572.2.36 |
| diff -u -p -r1.572.2.36 cp-tree.h |
| --- gcc/cp/cp-tree.h 2001/12/08 16:12:51 1.572.2.36 |
| +++ gcc/cp/cp-tree.h 2002/02/01 22:44:27 |
| @@ -135,11 +135,9 @@ Boston, MA 02111-1307, USA. */ |
| does not have a BV_FN; it is just an offset. |
| |
| 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 |
| + This is an expression with POINTER_TYPE that gives the value |
| to which the vptr should be initialized. Use get_vtbl_decl_for_binfo |
| - to extract the VAR_DECL for the complete vtable; that macro works |
| - in both ABIs. |
| + to extract the VAR_DECL for the complete vtable. |
| |
| DECL_ARGUMENTS |
| For a VAR_DECL this is DECL_ANON_UNION_ELEMS. |
| @@ -226,40 +224,6 @@ extern int flag_rtti; |
| |
| extern int flag_huge_objects; |
| |
| -/* Nonzero if virtual base class offsets are stored in the virtual |
| - function table. Zero if, instead, a pointer to the virtual base is |
| - stored in the object itself. */ |
| -#define vbase_offsets_in_vtable_p() (1) |
| - |
| -/* Nonzero if displacements to the `this' pointer to use when calling |
| - virtual functions in a virtual base class are present in the |
| - vtable. */ |
| -#define vcall_offsets_in_vtable_p() (1) |
| - |
| -/* Nonzero if a derived class that needs a vptr should always get one, |
| - even if a non-primary base class already has one. For example, |
| - given: |
| - |
| - struct S { int i; virtual void f(); }; |
| - struct T : virtual public S {}; |
| - |
| - one could either reuse the vptr in `S' for `T', or create a new |
| - vptr for `T'. If this flag is nonzero we choose the latter |
| - alternative; otherwise, we choose the former. */ |
| -#define vptrs_present_everywhere_p() (1) |
| - |
| -/* Nonzero if the vtable for a derived class should contain the |
| - virtual functions from the primary base and all virtual functions |
| - present in the class itself. Zero if, instead, it should contain |
| - only those virtual functions from the primary base together with |
| - the functions declared in the derived class (but not in any base |
| - class). */ |
| -#define all_overridden_vfuns_in_vtables_p() (1) |
| - |
| -/* Nonzero if primary and secondary vtables are combined into a single |
| - vtable. */ |
| -#define merge_primary_and_secondary_vtables_p() (1) |
| - |
| |
| /* Language-dependent contents of an identifier. */ |
| |
| @@ -601,15 +565,12 @@ enum cp_tree_index |
| CPTI_COMPLETE_DTOR_IDENTIFIER, |
| CPTI_BASE_DTOR_IDENTIFIER, |
| CPTI_DELETING_DTOR_IDENTIFIER, |
| - CPTI_DELTA2_IDENTIFIER, |
| CPTI_DELTA_IDENTIFIER, |
| CPTI_IN_CHARGE_IDENTIFIER, |
| CPTI_VTT_PARM_IDENTIFIER, |
| - CPTI_INDEX_IDENTIFIER, |
| CPTI_NELTS_IDENTIFIER, |
| CPTI_THIS_IDENTIFIER, |
| CPTI_PFN_IDENTIFIER, |
| - CPTI_PFN_OR_DELTA2_IDENTIFIER, |
| CPTI_VPTR_IDENTIFIER, |
| CPTI_STD_IDENTIFIER, |
| |
| @@ -643,8 +604,7 @@ extern tree cp_global_trees[CPTI_MAX]; |
| #define wchar_decl_node cp_global_trees[CPTI_WCHAR_DECL] |
| #define vtable_entry_type cp_global_trees[CPTI_VTABLE_ENTRY_TYPE] |
| /* The type used to represent an offset by which to adjust the `this' |
| - pointer in pointer-to-member types and, when not using vtable |
| - thunks, in vtables. */ |
| + pointer in pointer-to-member types. */ |
| #define delta_type_node cp_global_trees[CPTI_DELTA_TYPE] |
| /* The type used to represent an index into the vtable. */ |
| #define vtable_index_type cp_global_trees[CPTI_VTABLE_INDEX_TYPE] |
| @@ -720,20 +680,14 @@ extern tree cp_global_trees[CPTI_MAX]; |
| /* The name of a destructor that destroys virtual base classes, and |
| then deletes the entire object. */ |
| #define deleting_dtor_identifier cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER] |
| - |
| -#define delta2_identifier cp_global_trees[CPTI_DELTA2_IDENTIFIER] |
| #define delta_identifier cp_global_trees[CPTI_DELTA_IDENTIFIER] |
| #define in_charge_identifier cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER] |
| - |
| /* The name of the parameter that contains a pointer to the VTT to use |
| for this subobject constructor or destructor. */ |
| #define vtt_parm_identifier cp_global_trees[CPTI_VTT_PARM_IDENTIFIER] |
| - |
| -#define index_identifier cp_global_trees[CPTI_INDEX_IDENTIFIER] |
| #define nelts_identifier cp_global_trees[CPTI_NELTS_IDENTIFIER] |
| #define this_identifier cp_global_trees[CPTI_THIS_IDENTIFIER] |
| #define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER] |
| -#define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER] |
| #define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER] |
| /* The name of the std namespace. */ |
| #define std_identifier cp_global_trees[CPTI_STD_IDENTIFIER] |
| @@ -1081,11 +1035,6 @@ extern int warn_reorder; |
| |
| extern int flag_signed_bitfields; |
| |
| -/* True for more efficient but incompatible (not fully tested) |
| - vtable implementation (using thunks). |
| - 0 is old behavior; 1 is new behavior. */ |
| -extern int flag_vtable_thunks; |
| - |
| /* INTERFACE_ONLY nonzero means that we are in an "interface" |
| section of the compiler. INTERFACE_UNKNOWN nonzero means |
| we cannot trust the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN |
| @@ -1234,11 +1183,9 @@ enum languages { lang_c, lang_cplusplus, |
| /* Virtual function addresses can be gotten from a virtual function |
| table entry using this macro. */ |
| #define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \ |
| - (!flag_vtable_thunks ? \ |
| - TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) \ |
| - : !DECL_THUNK_P (TREE_OPERAND ((ENTRY), 0)) \ |
| - ? (ENTRY) \ |
| - : DECL_INITIAL (TREE_OPERAND ((ENTRY), 0))) |
| + (DECL_THUNK_P (TREE_OPERAND ((ENTRY), 0)) \ |
| + : DECL_INITIAL (TREE_OPERAND ((ENTRY), 0)) \ |
| + ? (ENTRY)) |
| |
| #define FUNCTION_ARG_CHAIN(NODE) \ |
| (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE)))) |
| @@ -2478,8 +2425,7 @@ struct lang_decl |
| /* Nonzero if this class has a virtual function table pointer. */ |
| #define TYPE_CONTAINS_VPTR_P(NODE) \ |
| (TYPE_POLYMORPHIC_P (NODE) \ |
| - || (vbase_offsets_in_vtable_p () \ |
| - && TYPE_USES_VIRTUAL_BASECLASSES (NODE))) |
| + || TYPE_USES_VIRTUAL_BASECLASSES (NODE)) |
| |
| extern int flag_new_for_scope; |
| |
| @@ -2634,67 +2580,15 @@ extern int flag_new_for_scope; |
| |
| /* A pointer-to-function member type looks like: |
| |
| - struct { |
| - short __delta; |
| - short __index; |
| - union { |
| - P __pfn; |
| - short __delta2; |
| - } __pfn_or_delta2; |
| - }; |
| - |
| - where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the |
| - pointer to member. The fields are used as follows: |
| - |
| - If __INDEX is -1, then the function to call is non-virtual, and |
| - is located at the address given by __PFN. |
| - |
| - If __INDEX is zero, then this a NULL pointer-to-member. |
| - |
| - Otherwise, the function to call is virtual. Then, __DELTA2 gives |
| - the offset from an instance of the object to the virtual function |
| - table, and __INDEX - 1 is the index into the vtable to use to |
| - find the function. |
| - |
| - The value to use for the THIS parameter is the address of the |
| - object plus __DELTA. |
| - |
| - For example, given: |
| - |
| - struct B1 { |
| - int i; |
| - }; |
| - |
| - struct B2 { |
| - double d; |
| - void f(); |
| - }; |
| - |
| - struct S : public B1, B2 {}; |
| - |
| - the pointer-to-member for `&S::f' looks like: |
| - |
| - { 4, -1, { &f__2B2 } }; |
| - |
| - The `4' means that given an `S*' you have to add 4 bytes to get to |
| - the address of the `B2*'. Then, the -1 indicates that this is a |
| - non-virtual function. Of course, `&f__2B2' is the name of that |
| - function. |
| - |
| - (Of course, the exact values may differ depending on the mangling |
| - scheme, sizes of types, and such.). |
| - |
| - Under the new ABI, we do: |
| - |
| struct { |
| __P __pfn; |
| ptrdiff_t __delta; |
| }; |
| |
| - (We don't need DELTA2, because the vtable is always the first thing |
| - in the object.) If the function is virtual, then PFN is one plus |
| - twice the index into the vtable; otherwise, it is just a pointer to |
| - the function. |
| + (As the vtable is always the first thing in the object, we don't |
| + need an offset to it.) If the function is virtual, then PFN is one |
| + plus twice the index into the vtable; otherwise, it is just a |
| + pointer to the function. |
| |
| Unfortunately, using the lowest bit of PFN doesn't work in |
| architectures that don't impose alignment requirements on function |
| @@ -3201,6 +3095,29 @@ typedef enum instantiate_type_flags { |
| itf_ptrmem_ok = 1 << 2, /* pointers to member ok (internal use) */ |
| } instantiate_type_flags; |
| |
| +/* The kind of checking we can do looking in a class heirarchy. */ |
| +typedef enum base_access { |
| + ba_any = -2, /* Do not check access, allow an ambiguous base, |
| + prefer a non-virtual base */ |
| + ba_ignore = -1, /* Do not check access */ |
| + ba_check = 0, /* Check access */ |
| + ba_not_special /* Do not consider special privilege |
| + current_class_type might give. */ |
| +} base_access; |
| + |
| +/* The kind of base we can find, looking in a class heirarchy. |
| + values <0 indicate we failed. */ |
| +typedef enum base_kind { |
| + bk_inaccessible = -3, /* The base is inaccessible */ |
| + bk_ambig = -2, /* The base is ambiguous */ |
| + bk_not_base = -1, /* It is not a base */ |
| + bk_same_type = 0, /* It is the same type */ |
| + bk_proper_base = 1, /* It is a proper base */ |
| + bk_via_virtual = 2 /* It is a proper base, but via a virtual |
| + path. This might not be the canonical |
| + binfo. */ |
| +} base_kind; |
| + |
| /* Nonzero means allow Microsoft extensions without a pedwarn. */ |
| extern int flag_ms_extensions; |
| |
| @@ -3226,8 +3143,7 @@ extern tree pending_vtables; |
| |
| /* Node for "pointer to (virtual) function". |
| This may be distinct from ptr_type_node so gdb can distinguish them. */ |
| -#define vfunc_ptr_type_node \ |
| - (flag_vtable_thunks ? vtable_entry_type : ptr_type_node) |
| +#define vfunc_ptr_type_node vtable_entry_type |
| |
| |
| /* For building calls to `delete'. */ |
| @@ -3295,12 +3211,10 @@ extern varray_type local_classes; |
| #define AUTO_TEMP_NAME "_$tmp_" |
| #define AUTO_TEMP_FORMAT "_$tmp_%d" |
| #define VTABLE_BASE "$vb" |
| -#define VTABLE_NAME_PREFIX (flag_vtable_thunks ? "__vt_" : "_vt$") |
| +#define VTABLE_NAME_PREFIX "__vt_" |
| #define VFIELD_BASE "$vf" |
| #define VFIELD_NAME "_vptr$" |
| #define VFIELD_NAME_FORMAT "_vptr$%s" |
| -#define VBASE_NAME "_vb$" |
| -#define VBASE_NAME_FORMAT "_vb$%s" |
| #define STATIC_NAME_FORMAT "_%s$%s" |
| #define ANON_AGGRNAME_FORMAT "$_%d" |
| |
| @@ -3317,12 +3231,10 @@ extern varray_type local_classes; |
| #define AUTO_TEMP_NAME "_.tmp_" |
| #define AUTO_TEMP_FORMAT "_.tmp_%d" |
| #define VTABLE_BASE ".vb" |
| -#define VTABLE_NAME_PREFIX (flag_vtable_thunks ? "__vt_" : "_vt.") |
| +#define VTABLE_NAME_PREFIX "__vt_" |
| #define VFIELD_BASE ".vf" |
| #define VFIELD_NAME "_vptr." |
| #define VFIELD_NAME_FORMAT "_vptr.%s" |
| -#define VBASE_NAME "_vb." |
| -#define VBASE_NAME_FORMAT "_vb.%s" |
| #define STATIC_NAME_FORMAT "_%s.%s" |
| |
| #define ANON_AGGRNAME_FORMAT "._%d" |
| @@ -3346,7 +3258,7 @@ extern varray_type local_classes; |
| #define AUTO_TEMP_FORMAT "__tmp_%d" |
| #define VTABLE_BASE "__vtb" |
| #define VTABLE_NAME "__vt_" |
| -#define VTABLE_NAME_PREFIX (flag_vtable_thunks ? "__vt_" : "_vt_") |
| +#define VTABLE_NAME_PREFIX "__vt_" |
| #define VTABLE_NAME_P(ID_NODE) \ |
| (!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \ |
| sizeof (VTABLE_NAME) - 1)) |
| @@ -3356,11 +3268,6 @@ extern varray_type local_classes; |
| (!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, \ |
| sizeof (VFIELD_NAME) - 1)) |
| #define VFIELD_NAME_FORMAT "_vptr_%s" |
| -#define VBASE_NAME "__vb_" |
| -#define VBASE_NAME_P(ID_NODE) \ |
| - (!strncmp (IDENTIFIER_POINTER (ID_NODE), VBASE_NAME, \ |
| - sizeof (VBASE_NAME) - 1)) |
| -#define VBASE_NAME_FORMAT "__vb_%s" |
| #define STATIC_NAME_FORMAT "__static_%s_%s" |
| |
| #define ANON_AGGRNAME_PREFIX "__anon_" |
| @@ -3386,21 +3293,10 @@ extern varray_type local_classes; |
| |
| #define VTBL_PTR_TYPE "__vtbl_ptr_type" |
| #define VTABLE_DELTA_NAME "__delta" |
| -#define VTABLE_INDEX_NAME "__index" |
| #define VTABLE_PFN_NAME "__pfn" |
| -#define VTABLE_DELTA2_NAME "__delta2" |
| |
| #define EXCEPTION_CLEANUP_NAME "exception cleanup" |
| |
| -/* The name used as a prefix for VTTs. When the new ABI mangling |
| - scheme is implemented, this should be removed. */ |
| - |
| -#define VTT_NAME_PREFIX "__vtt_" |
| - |
| -/* The name used as a prefix for construction vtables. */ |
| - |
| -#define CTOR_VTBL_NAME_PREFIX "__ctorvt_" |
| - |
| #define THIS_NAME_P(ID_NODE) (strcmp(IDENTIFIER_POINTER (ID_NODE), "this") == 0) |
| |
| #if !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) |
| @@ -3414,10 +3310,6 @@ extern varray_type local_classes; |
| && IDENTIFIER_POINTER (ID_NODE)[2] == 't' \ |
| && IDENTIFIER_POINTER (ID_NODE)[3] == JOINER) |
| |
| -#define VBASE_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == 'v' \ |
| - && IDENTIFIER_POINTER (ID_NODE)[2] == 'b' \ |
| - && IDENTIFIER_POINTER (ID_NODE)[3] == JOINER) |
| - |
| #define TEMP_NAME_P(ID_NODE) (!strncmp (IDENTIFIER_POINTER (ID_NODE), AUTO_TEMP_NAME, sizeof (AUTO_TEMP_NAME)-1)) |
| #define VFIELD_NAME_P(ID_NODE) (!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, sizeof(VFIELD_NAME)-1)) |
| |
| @@ -3431,14 +3323,6 @@ extern varray_type local_classes; |
| && IDENTIFIER_POINTER (ID_NODE)[1] <= '9') |
| #endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */ |
| |
| -/* Store the vbase pointer field name for type TYPE into pointer BUF. */ |
| -#define FORMAT_VBASE_NAME(BUF,TYPE) do { \ |
| - char *wbuf = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (TYPE) \ |
| - + sizeof (VBASE_NAME) + 1); \ |
| - sprintf (wbuf, VBASE_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (TYPE)); \ |
| - (BUF) = wbuf; \ |
| -} while (0) |
| - |
| /* Returns non-zero iff NODE is a declaration for the global function |
| `main'. */ |
| #define DECL_MAIN_P(NODE) \ |
| @@ -3742,9 +3626,10 @@ extern tree strip_top_quals |
| extern tree perform_implicit_conversion PARAMS ((tree, tree)); |
| |
| /* in class.c */ |
| +extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int)); |
| extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int)); |
| extern tree build_vtbl_ref PARAMS ((tree, tree)); |
| -extern tree build_vfn_ref PARAMS ((tree *, tree, tree)); |
| +extern tree build_vfn_ref PARAMS ((tree, tree)); |
| extern tree get_vtable_decl PARAMS ((tree, int)); |
| extern void add_method PARAMS ((tree, tree, int)); |
| extern int currently_open_class PARAMS ((tree)); |
| @@ -3781,8 +3666,6 @@ extern tree get_primary_binfo |
| extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree)); |
| extern tree convert_from_reference PARAMS ((tree)); |
| extern tree convert_lvalue PARAMS ((tree, tree)); |
| -extern tree convert_pointer_to_real PARAMS ((tree, tree)); |
| -extern tree convert_pointer_to PARAMS ((tree, tree)); |
| extern tree ocp_convert PARAMS ((tree, tree, int, int)); |
| extern tree cp_convert PARAMS ((tree, tree)); |
| extern tree convert_to_void PARAMS ((tree, const char */*implicit context*/)); |
| @@ -4216,6 +4099,7 @@ extern int tinfo_decl_p |
| extern int emit_tinfo_decl PARAMS((tree *, void *)); |
| |
| /* in search.c */ |
| +extern tree lookup_base PARAMS ((tree, tree, base_access, base_kind *)); |
| extern int types_overlap_p PARAMS ((tree, tree)); |
| extern tree get_vbase PARAMS ((tree, tree)); |
| extern tree get_binfo PARAMS ((tree, tree, int)); |
| @@ -4229,7 +4113,6 @@ extern tree lookup_fnfields PARAMS ((t |
| extern tree lookup_member PARAMS ((tree, tree, int, int)); |
| extern int look_for_overrides PARAMS ((tree, tree)); |
| extern void get_pure_virtuals PARAMS ((tree)); |
| -extern tree init_vbase_pointers PARAMS ((tree, tree)); |
| extern void get_vbase_types PARAMS ((tree)); |
| extern void maybe_suppress_debug_info PARAMS ((tree)); |
| extern void note_debug_info_needed PARAMS ((tree)); |
| @@ -4265,11 +4148,9 @@ extern tree dfs_marked_real_bases_queue_ |
| extern tree dfs_skip_vbases PARAMS ((tree, void *)); |
| extern tree marked_vtable_pathp PARAMS ((tree, void *)); |
| extern tree unmarked_vtable_pathp PARAMS ((tree, void *)); |
| -extern tree convert_pointer_to_vbase PARAMS ((tree, tree)); |
| extern tree find_vbase_instance PARAMS ((tree, tree)); |
| extern tree binfo_for_vbase PARAMS ((tree, tree)); |
| extern tree binfo_via_virtual PARAMS ((tree, tree)); |
| -extern void fixup_all_virtual_upcast_offsets PARAMS ((tree)); |
| |
| /* in semantics.c */ |
| extern void init_cp_semantics PARAMS ((void)); |
| Index: gcc/cp/cvt.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v |
| retrieving revision 1.97.2.3 |
| diff -u -p -r1.97.2.3 cvt.c |
| --- gcc/cp/cvt.c 2001/08/17 04:31:27 1.97.2.3 |
| +++ gcc/cp/cvt.c 2002/02/01 22:44:28 |
| @@ -141,44 +141,35 @@ cp_convert_to_pointer (type, expr, force |
| && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE |
| && IS_AGGR_TYPE (TREE_TYPE (type)) |
| && IS_AGGR_TYPE (TREE_TYPE (intype)) |
| - && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE |
| - /* If EXPR is NULL, then we don't need to do any arithmetic |
| - to convert it: |
| - |
| - [conv.ptr] |
| - |
| - The null pointer value is converted to the null pointer |
| - value of the destination type. */ |
| - && !integer_zerop (expr)) |
| + && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE) |
| { |
| enum tree_code code = PLUS_EXPR; |
| - tree binfo = get_binfo (TREE_TYPE (type), TREE_TYPE (intype), 1); |
| - if (binfo == error_mark_node) |
| - return error_mark_node; |
| - if (binfo == NULL_TREE) |
| + tree binfo; |
| + |
| + /* Try derived to base conversion. */ |
| + binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type), |
| + ba_check, NULL); |
| + if (!binfo) |
| { |
| - binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 1); |
| - if (binfo == error_mark_node) |
| - return error_mark_node; |
| + /* Try base to derived conversion. */ |
| + binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), |
| + ba_check, NULL); |
| code = MINUS_EXPR; |
| } |
| + if (binfo == error_mark_node) |
| + return error_mark_node; |
| if (binfo) |
| { |
| - if (TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (type)) |
| - || TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (intype)) |
| - || ! BINFO_OFFSET_ZEROP (binfo)) |
| + expr = build_base_path (code, expr, binfo, 0); |
| + /* Add any qualifier conversions. */ |
| + if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)), |
| + TREE_TYPE (type))) |
| { |
| - /* Need to get the path we took. */ |
| - tree path; |
| - |
| - if (code == PLUS_EXPR) |
| - get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), |
| - 0, &path); |
| - else |
| - get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), |
| - 0, &path); |
| - return build_vbase_path (code, type, expr, path, 0); |
| + expr = build1 (NOP_EXPR, type, expr); |
| + TREE_CONSTANT (expr) = |
| + TREE_CONSTANT (TREE_OPERAND (expr, 0)); |
| } |
| + return expr; |
| } |
| } |
| |
| @@ -187,36 +178,29 @@ cp_convert_to_pointer (type, expr, force |
| tree b1; |
| tree b2; |
| tree binfo; |
| - tree virt_binfo; |
| - enum tree_code code; |
| + enum tree_code code = PLUS_EXPR; |
| + base_kind bk; |
| |
| b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); |
| b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); |
| - binfo = get_binfo (b2, b1, 1); |
| - |
| - if (binfo == NULL_TREE) |
| + binfo = lookup_base (b1, b2, ba_check, &bk); |
| + if (!binfo) |
| { |
| - binfo = get_binfo (b1, b2, 1); |
| + binfo = lookup_base (b2, b1, ba_check, &bk); |
| code = MINUS_EXPR; |
| } |
| - else |
| - code = PLUS_EXPR; |
| - |
| if (binfo == error_mark_node) |
| return error_mark_node; |
| |
| - virt_binfo = binfo_from_vbase (binfo); |
| - if (virt_binfo) |
| + if (bk == bk_via_virtual) |
| { |
| if (force) |
| - cp_warning ("pointer to member cast via virtual base `%T' of `%T'", |
| - BINFO_TYPE (virt_binfo), |
| - BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo))); |
| + cp_warning ("pointer to member cast from `%T' to `%T' is via virtual base", |
| + TREE_TYPE (intype), TREE_TYPE (type)); |
| else |
| { |
| - cp_error ("pointer to member cast via virtual base `%T' of `%T'", |
| - BINFO_TYPE (virt_binfo), |
| - BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo))); |
| + cp_error ("pointer to member cast from `%T' to `%T' is via virtual base", |
| + TREE_TYPE (intype), TREE_TYPE (type)); |
| return error_mark_node; |
| } |
| /* This is a reinterpret cast, whose result is unspecified. |
| @@ -259,8 +243,8 @@ cp_convert_to_pointer (type, expr, force |
| return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0); |
| |
| if (TYPE_PTRMEM_P (type)) |
| - /* Under the new ABI, a NULL pointer-to-member is represented |
| - by -1, not by zero. */ |
| + /* A NULL pointer-to-member is represented by -1, not by |
| + zero. */ |
| expr = build_int_2 (-1, -1); |
| else |
| expr = build_int_2 (0, 0); |
| @@ -319,34 +303,32 @@ convert_to_pointer_force (type, expr) |
| && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE) |
| { |
| enum tree_code code = PLUS_EXPR; |
| - tree path; |
| - int distance = get_base_distance (TREE_TYPE (type), |
| - TREE_TYPE (intype), 0, &path); |
| - if (distance == -2) |
| + tree binfo; |
| + |
| + binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type), |
| + ba_ignore, NULL); |
| + if (!binfo) |
| { |
| - cp_error ("type `%T' is ambiguous base of `%T'", |
| - TREE_TYPE (type), |
| - TREE_TYPE (intype)); |
| - return error_mark_node; |
| + binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), |
| + ba_ignore, NULL); |
| + code = MINUS_EXPR; |
| } |
| - if (distance == -1) |
| + if (binfo == error_mark_node) |
| + return error_mark_node; |
| + if (binfo) |
| { |
| - distance = get_base_distance (TREE_TYPE (intype), |
| - TREE_TYPE (type), 0, &path); |
| - if (distance == -2) |
| - { |
| - cp_error ("type `%T' is ambiguous base of `%T'", |
| - TREE_TYPE (intype), |
| - TREE_TYPE (type)); |
| - return error_mark_node; |
| - } |
| - if (distance < 0) |
| - /* Doesn't need any special help from us. */ |
| - return build1 (NOP_EXPR, type, expr); |
| - |
| - code = MINUS_EXPR; |
| + expr = build_base_path (code, expr, binfo, 0); |
| + /* Add any qualifier conversions. */ |
| + if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)), |
| + TREE_TYPE (type))) |
| + { |
| + expr = build1 (NOP_EXPR, type, expr); |
| + TREE_CONSTANT (expr) = |
| + TREE_CONSTANT (TREE_OPERAND (expr, 0)); |
| + } |
| + return expr; |
| } |
| - return build_vbase_path (code, type, expr, path, 0); |
| + |
| } |
| } |
| |
| @@ -406,12 +388,12 @@ build_up_reference (type, arg, flags) |
| && IS_AGGR_TYPE (target_type)) |
| { |
| /* We go through get_binfo for the access control. */ |
| - tree binfo = get_binfo (target_type, argtype, 1); |
| + tree binfo = lookup_base (argtype, target_type, ba_check, NULL); |
| if (binfo == error_mark_node) |
| return error_mark_node; |
| if (binfo == NULL_TREE) |
| return error_not_base_type (target_type, argtype); |
| - rval = convert_pointer_to_real (binfo, rval); |
| + rval = build_base_path (PLUS_EXPR, rval, binfo, 1); |
| } |
| else |
| rval |
| @@ -610,87 +592,6 @@ convert_lvalue (totype, expr) |
| expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL, |
| NULL_TREE); |
| return convert_from_reference (expr); |
| -} |
| - |
| -/* Call this when we know (for any reason) that expr is not, in fact, |
| - zero. This routine is like convert_pointer_to, but it pays |
| - attention to which specific instance of what type we want to |
| - convert to. This routine should eventually become |
| - convert_to_pointer after all references to convert_to_pointer |
| - are removed. */ |
| - |
| -tree |
| -convert_pointer_to_real (binfo, expr) |
| - tree binfo, expr; |
| -{ |
| - register tree intype = TREE_TYPE (expr); |
| - tree ptr_type; |
| - tree type, rval; |
| - |
| - if (intype == error_mark_node) |
| - return error_mark_node; |
| - |
| - if (TREE_CODE (binfo) == TREE_VEC) |
| - type = BINFO_TYPE (binfo); |
| - else if (IS_AGGR_TYPE (binfo)) |
| - { |
| - type = binfo; |
| - } |
| - else |
| - { |
| - type = binfo; |
| - binfo = NULL_TREE; |
| - } |
| - |
| - ptr_type = cp_build_qualified_type (type, |
| - CP_TYPE_QUALS (TREE_TYPE (intype))); |
| - ptr_type = build_pointer_type (ptr_type); |
| - if (same_type_p (ptr_type, TYPE_MAIN_VARIANT (intype))) |
| - return expr; |
| - |
| - my_friendly_assert (!integer_zerop (expr), 191); |
| - |
| - intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype)); |
| - if (TREE_CODE (type) == RECORD_TYPE |
| - && TREE_CODE (intype) == RECORD_TYPE |
| - && type != intype) |
| - { |
| - tree path; |
| - int distance |
| - = get_base_distance (binfo, intype, 0, &path); |
| - |
| - /* This function shouldn't be called with unqualified arguments |
| - but if it is, give them an error message that they can read. */ |
| - if (distance < 0) |
| - { |
| - cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'", |
| - intype, type); |
| - |
| - if (distance == -2) |
| - cp_error ("because `%T' is an ambiguous base class", type); |
| - return error_mark_node; |
| - } |
| - |
| - return build_vbase_path (PLUS_EXPR, ptr_type, expr, path, 1); |
| - } |
| - rval = build1 (NOP_EXPR, ptr_type, |
| - TREE_CODE (expr) == NOP_EXPR ? TREE_OPERAND (expr, 0) : expr); |
| - TREE_CONSTANT (rval) = TREE_CONSTANT (expr); |
| - return rval; |
| -} |
| - |
| -/* Call this when we know (for any reason) that expr is |
| - not, in fact, zero. This routine gets a type out of the first |
| - argument and uses it to search for the type to convert to. If there |
| - is more than one instance of that type in the expr, the conversion is |
| - ambiguous. This routine should eventually go away, and all |
| - callers should use convert_to_pointer_real. */ |
| - |
| -tree |
| -convert_pointer_to (binfo, expr) |
| - tree binfo, expr; |
| -{ |
| - return convert_pointer_to_real (binfo, expr); |
| } |
| |
| /* C++ conversions, preference to static cast conversions. */ |
| Index: gcc/cp/decl.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v |
| retrieving revision 1.747.2.36 |
| diff -u -p -r1.747.2.36 decl.c |
| --- gcc/cp/decl.c 2002/01/18 03:36:08 1.747.2.36 |
| +++ gcc/cp/decl.c 2002/02/01 22:44:37 |
| @@ -51,8 +51,7 @@ extern tree global_namespace; |
| extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree)); |
| |
| #ifndef BOOL_TYPE_SIZE |
| -/* In the new ABI, `bool' has size and alignment `1', on all |
| - platforms. */ |
| +/* `bool' has size and alignment `1', on all platforms. */ |
| #define BOOL_TYPE_SIZE CHAR_TYPE_SIZE |
| #endif |
| |
| @@ -166,28 +165,13 @@ tree error_mark_list; |
| |
| tree vtable_entry_type; |
| tree delta_type_node; |
| -#if 0 |
| - Old rtti stuff. |
| - tree __baselist_desc_type_node; |
| - tree __i_desc_type_node, __m_desc_type_node; |
| - tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type; |
| -#endif |
| tree __t_desc_type_node; |
| -#if 0 |
| - tree __tp_desc_type_node; |
| -#endif |
| tree ti_desc_type_node; |
| tree bltn_desc_type_node, ptr_desc_type_node; |
| tree ary_desc_type_node, func_desc_type_node, enum_desc_type_node; |
| tree class_desc_type_node, si_class_desc_type_node, vmi_class_desc_type_node; |
| tree ptm_desc_type_node; |
| tree base_desc_type_node; |
| -#if 0 |
| - Not needed yet? May be needed one day? |
| - tree __bltn_desc_array_type, __user_desc_array_type, __class_desc_array_type; |
| - tree __ptr_desc_array_type, __attr_dec_array_type, __func_desc_array_type; |
| - tree __ptmf_desc_array_type, __ptmd_desc_array_type; |
| -#endif |
| |
| tree class_type_node, record_type_node, union_type_node, enum_type_node; |
| tree unknown_type_node; |
| @@ -6317,14 +6301,11 @@ initialize_predefined_identifiers () |
| { "__comp_dtor", &complete_dtor_identifier, 1 }, |
| { "__base_dtor", &base_dtor_identifier, 1 }, |
| { "__deleting_dtor", &deleting_dtor_identifier, 1 }, |
| - { VTABLE_DELTA2_NAME, &delta2_identifier, 0 }, |
| - { VTABLE_DELTA_NAME, &delta_identifier, 0 }, |
| { IN_CHARGE_NAME, &in_charge_identifier, 0 }, |
| - { VTABLE_INDEX_NAME, &index_identifier, 0 }, |
| { "nelts", &nelts_identifier, 0 }, |
| { THIS_NAME, &this_identifier, 0 }, |
| + { VTABLE_DELTA_NAME, &delta_identifier, 0 }, |
| { VTABLE_PFN_NAME, &pfn_identifier, 0 }, |
| - { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 }, |
| { "_vptr", &vptr_identifier, 0 }, |
| { "__vtt_parm", &vtt_parm_identifier, 0 }, |
| { "std", &std_identifier, 0 }, |
| @@ -6349,11 +6330,6 @@ init_decl_processing () |
| { |
| tree fields[20]; |
| |
| - /* Check to see that the user did not specify an invalid combination |
| - of command-line options. */ |
| - if (!flag_vtable_thunks) |
| - error ("the ABI requires vtable thunks"); |
| - |
| /* Create all the identifiers we need. */ |
| initialize_predefined_identifiers (); |
| |
| @@ -6493,41 +6469,16 @@ init_decl_processing () |
| TYPE_POINTER_TO (unknown_type_node) = unknown_type_node; |
| TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node; |
| |
| - if (flag_vtable_thunks) |
| - { |
| - /* Make sure we get a unique function type, so we can give |
| - its pointer type a name. (This wins for gdb.) */ |
| - tree vfunc_type = make_node (FUNCTION_TYPE); |
| - TREE_TYPE (vfunc_type) = integer_type_node; |
| - TYPE_ARG_TYPES (vfunc_type) = NULL_TREE; |
| - layout_type (vfunc_type); |
| - |
| - vtable_entry_type = build_pointer_type (vfunc_type); |
| - } |
| - else |
| - { |
| - vtable_entry_type = make_aggr_type (RECORD_TYPE); |
| - fields[0] = build_decl (FIELD_DECL, delta_identifier, |
| - delta_type_node); |
| - fields[1] = build_decl (FIELD_DECL, index_identifier, |
| - delta_type_node); |
| - fields[2] = build_decl (FIELD_DECL, pfn_identifier, |
| - ptr_type_node); |
| - finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2, |
| - double_type_node); |
| - |
| - /* Make this part of an invisible union. */ |
| - fields[3] = copy_node (fields[2]); |
| - TREE_TYPE (fields[3]) = delta_type_node; |
| - DECL_NAME (fields[3]) = delta2_identifier; |
| - DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node); |
| - DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node); |
| - DECL_SIZE_UNIT (fields[3]) = TYPE_SIZE_UNIT (delta_type_node); |
| - TREE_UNSIGNED (fields[3]) = 0; |
| - TREE_CHAIN (fields[2]) = fields[3]; |
| - vtable_entry_type = build_qualified_type (vtable_entry_type, |
| - TYPE_QUAL_CONST); |
| - } |
| + { |
| + /* Make sure we get a unique function type, so we can give |
| + its pointer type a name. (This wins for gdb.) */ |
| + tree vfunc_type = make_node (FUNCTION_TYPE); |
| + TREE_TYPE (vfunc_type) = integer_type_node; |
| + TYPE_ARG_TYPES (vfunc_type) = NULL_TREE; |
| + layout_type (vfunc_type); |
| + |
| + vtable_entry_type = build_pointer_type (vfunc_type); |
| + } |
| record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type); |
| |
| vtbl_type_node |
| @@ -9473,7 +9424,6 @@ check_special_function_return_type (sfk, |
| if (type) |
| cp_error ("return type specification for constructor invalid"); |
| |
| - /* In the new ABI constructors do not return a value. */ |
| type = void_type_node; |
| break; |
| |
| Index: gcc/cp/decl2.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v |
| retrieving revision 1.437.2.29 |
| diff -u -p -r1.437.2.29 decl2.c |
| --- gcc/cp/decl2.c 2001/11/30 03:12:42 1.437.2.29 |
| +++ gcc/cp/decl2.c 2002/02/01 22:44:40 |
| @@ -200,11 +200,6 @@ int warn_long_long = 1; |
| |
| int warn_ctor_dtor_privacy = 1; |
| |
| -/* True if we want to implement vtables using "thunks". |
| - The default is off. */ |
| - |
| -int flag_vtable_thunks = 1; |
| - |
| /* Nonzero means generate separate instantiation control files and juggle |
| them at link time. */ |
| |
| @@ -2262,12 +2257,9 @@ mark_vtable_entries (decl) |
| |
| for (; entries; entries = TREE_CHAIN (entries)) |
| { |
| - tree fnaddr; |
| + tree fnaddr = TREE_VALUE (entries); |
| tree fn; |
| |
| - fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) |
| - : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries))); |
| - |
| if (TREE_CODE (fnaddr) != ADDR_EXPR |
| && TREE_CODE (fnaddr) != FDESC_EXPR) |
| /* This entry is an offset: a virtual base class offset, a |
| @@ -2307,12 +2299,12 @@ comdat_linkage (decl) |
| address, and this will not hold when we emit multiple copies of |
| the function. However, there's little else we can do. |
| |
| - Also, by default, the typeinfo implementation for the new ABI |
| - assumes that there will be only one copy of the string used as |
| - the name for each type. Therefore, if weak symbols are |
| - unavailable, the run-time library should perform a more |
| - conservative check; it should perform a string comparison, |
| - rather than an address comparison. */ |
| + Also, by default, the typeinfo implementation assumes that |
| + there will be only one copy of the string used as the name for |
| + each type. Therefore, if weak symbols are unavailable, the |
| + run-time library should perform a more conservative check; it |
| + should perform a string comparison, rather than an address |
| + comparison. */ |
| TREE_PUBLIC (decl) = 0; |
| else |
| { |
| @@ -2751,8 +2743,8 @@ get_guard (decl) |
| { |
| tree guard_type; |
| |
| - /* Under the new ABI, we use a type that is big enough to |
| - contain a mutex as well as an integer counter. */ |
| + /* We use a type that is big enough to contain a mutex as well |
| + as an integer counter. */ |
| guard_type = long_long_integer_type_node; |
| guard = build_decl (VAR_DECL, sname, guard_type); |
| |
| @@ -2779,8 +2771,8 @@ static tree |
| get_guard_bits (guard) |
| tree guard; |
| { |
| - /* Under the new ABI, we only set the first byte of the guard, |
| - in order to leave room for a mutex in the high-order bits. */ |
| + /* We only set the first byte of the guard, in order to leave room |
| + for a mutex in the high-order bits. */ |
| guard = build1 (ADDR_EXPR, |
| build_pointer_type (TREE_TYPE (guard)), |
| guard); |
| Index: gcc/cp/error.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v |
| retrieving revision 1.149.2.5 |
| diff -u -p -r1.149.2.5 error.c |
| --- gcc/cp/error.c 2001/09/15 19:43:41 1.149.2.5 |
| +++ gcc/cp/error.c 2002/02/01 22:44:43 |
| @@ -950,13 +950,8 @@ dump_decl (t, flags) |
| if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t))) |
| { |
| output_add_string (scratch_buffer, "vtable for "); |
| - if (TYPE_P (DECL_CONTEXT (t))) |
| - dump_type (DECL_CONTEXT (t), flags); |
| - else |
| - /* This case can arise with -fno-vtable-thunks. See |
| - expand_upcast_fixups. It's not clear what to print |
| - here. */ |
| - print_identifier (scratch_buffer, "<unknown type>"); |
| + my_friendly_assert (TYPE_P (DECL_CONTEXT (t)), 20010720); |
| + dump_type (DECL_CONTEXT (t), flags); |
| break; |
| } |
| /* else fall through */ |
| @@ -1918,16 +1913,9 @@ dump_expr (t, flags) |
| case CONSTRUCTOR: |
| if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) |
| { |
| - tree idx = build_component_ref (t, index_identifier, NULL_TREE, 0); |
| + tree idx = build_component_ref (t, pfn_identifier, NULL_TREE, 0); |
| |
| - if (integer_all_onesp (idx)) |
| - { |
| - tree pfn = PFN_FROM_PTRMEMFUNC (t); |
| - dump_unary_op ("&", pfn, flags | TFF_EXPR_IN_PARENS); |
| - break; |
| - } |
| - else if (TREE_CODE (idx) == INTEGER_CST |
| - && tree_int_cst_equal (idx, integer_zero_node)) |
| + if (integer_zerop (idx)) |
| { |
| /* A NULL pointer-to-member constant. */ |
| output_add_string (scratch_buffer, "(("); |
| Index: gcc/cp/init.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v |
| retrieving revision 1.232.2.10 |
| diff -u -p -r1.232.2.10 init.c |
| --- gcc/cp/init.c 2002/01/23 12:47:11 1.232.2.10 |
| +++ gcc/cp/init.c 2002/02/01 22:44:44 |
| @@ -130,7 +130,9 @@ finish_init_stmts (stmt_expr, compound_s |
| |
| /* Constructors */ |
| |
| -/* Called from initialize_vtbl_ptrs via dfs_walk. */ |
| +/* Called from initialize_vtbl_ptrs via dfs_walk. BINFO is the base |
| + which we want to initialize the vtable pointer for, DATA is |
| + TREE_LIST whose TREE_VALUE is the this ptr expression. */ |
| |
| static tree |
| dfs_initialize_vtbl_ptrs (binfo, data) |
| @@ -142,16 +144,7 @@ dfs_initialize_vtbl_ptrs (binfo, data) |
| { |
| tree base_ptr = TREE_VALUE ((tree) data); |
| |
| - if (TREE_VIA_VIRTUAL (binfo)) |
| - base_ptr = convert_pointer_to_vbase (BINFO_TYPE (binfo), |
| - base_ptr); |
| - else |
| - base_ptr |
| - = build_vbase_path (PLUS_EXPR, |
| - build_pointer_type (BINFO_TYPE (binfo)), |
| - base_ptr, |
| - binfo, |
| - /*nonnull=*/1); |
| + base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1); |
| |
| expand_virtual_init (binfo, base_ptr); |
| } |
| @@ -175,21 +168,13 @@ initialize_vtbl_ptrs (addr) |
| list = build_tree_list (type, addr); |
| |
| /* Walk through the hierarchy, initializing the vptr in each base |
| - class. We do these in pre-order because under the new ABI we |
| - can't find the virtual bases for a class until we've initialized |
| - the vtbl for that class. */ |
| + class. We do these in pre-order because can't find the virtual |
| + bases for a class until we've initialized the vtbl for that |
| + class. */ |
| dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, |
| NULL, dfs_unmarked_real_bases_queue_p, list); |
| dfs_walk (TYPE_BINFO (type), dfs_unmark, |
| dfs_marked_real_bases_queue_p, type); |
| - |
| - /* If we're not using thunks, we may need to adjust the deltas in |
| - the vtable to handle virtual base classes correctly. When we are |
| - using thunks, we either use construction vtables (which are |
| - preloaded with the right answers) or nothing (in which case |
| - vitual function calls sometimes don't work right.) */ |
| - if (TYPE_USES_VIRTUAL_BASECLASSES (type) && !flag_vtable_thunks) |
| - fixup_all_virtual_upcast_offsets (addr); |
| } |
| |
| /* [dcl.init]: |
| @@ -748,7 +733,8 @@ emit_base_init (mem_init_list, base_init |
| |
| if (init != void_list_node) |
| { |
| - member = convert_pointer_to_real (base_binfo, current_class_ptr); |
| + member = build_base_path (PLUS_EXPR, current_class_ptr, |
| + base_binfo, 1); |
| expand_aggr_init_1 (base_binfo, NULL_TREE, |
| build_indirect_ref (member, NULL_PTR), init, |
| LOOKUP_NORMAL); |
| @@ -839,20 +825,14 @@ static void |
| expand_virtual_init (binfo, decl) |
| tree binfo, decl; |
| { |
| - tree type = BINFO_TYPE (binfo); |
| tree vtbl, vtbl_ptr; |
| - tree vtype, vtype_binfo; |
| tree vtt_index; |
| |
| - /* Compute the location of the vtable. */ |
| - vtype = DECL_CONTEXT (TYPE_VFIELD (type)); |
| - vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0); |
| - |
| /* Compute the initializer for vptr. */ |
| vtbl = build_vtbl_address (binfo); |
| |
| - /* Under the new ABI, we may get this vptr from a VTT, if this is a |
| - subobject constructor or subobject destructor. */ |
| + /* We may get this vptr from a VTT, if this is a subobject |
| + constructor or subobject destructor. */ |
| vtt_index = BINFO_VPTR_INDEX (binfo); |
| if (vtt_index) |
| { |
| @@ -879,10 +859,9 @@ expand_virtual_init (binfo, decl) |
| } |
| |
| /* Compute the location of the vtpr. */ |
| - decl = convert_pointer_to_real (vtype_binfo, decl); |
| - vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype); |
| - if (vtbl_ptr == error_mark_node) |
| - return; |
| + vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL), |
| + TREE_TYPE (binfo)); |
| + my_friendly_assert (vtbl_ptr != error_mark_node, 20010730); |
| |
| /* Assign the vtable to the vptr. */ |
| vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); |
| @@ -951,22 +930,6 @@ construct_virtual_bases (type, this_ref, |
| /* If there are no virtual baseclasses, we shouldn't even be here. */ |
| my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621); |
| |
| - /* First set the pointers in our object that tell us where to find |
| - our virtual baseclasses. */ |
| - if (!vbase_offsets_in_vtable_p ()) |
| - { |
| - tree if_stmt; |
| - tree result; |
| - |
| - if_stmt = begin_if_stmt (); |
| - finish_if_stmt_cond (flag, if_stmt); |
| - result = init_vbase_pointers (type, this_ptr); |
| - if (result) |
| - finish_expr_stmt (build_compound_expr (result)); |
| - finish_then_clause (if_stmt); |
| - finish_if_stmt (); |
| - } |
| - |
| /* Now, run through the baseclasses, initializing each. */ |
| for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; |
| vbases = TREE_CHAIN (vbases)) |
| @@ -1919,14 +1882,17 @@ resolve_offset_ref (exp) |
| if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) |
| base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type)); |
| |
| - addr = build_unary_op (ADDR_EXPR, base, 0); |
| - addr = convert_pointer_to (basetype, addr); |
| + /* Don't check access on the conversion; we might be after a member |
| + promoted by an access- or using-declaration, and we have already |
| + checked access for the member itself. */ |
| + basetype = lookup_base (TREE_TYPE (base), basetype, ba_ignore, NULL); |
| + expr = build_base_path (PLUS_EXPR, base, basetype, 1); |
| |
| - if (addr == error_mark_node) |
| + if (expr == error_mark_node) |
| return error_mark_node; |
| |
| expr = build (COMPONENT_REF, TREE_TYPE (member), |
| - build_indirect_ref (addr, NULL_PTR), member); |
| + expr, member); |
| return convert_from_reference (expr); |
| } |
| |
| @@ -1949,7 +1915,10 @@ resolve_offset_ref (exp) |
| } |
| |
| basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member))); |
| - addr = convert_pointer_to (basetype, addr); |
| + basetype = lookup_base (TREE_TYPE (TREE_TYPE (addr)), |
| + basetype, ba_check, NULL); |
| + addr = build_base_path (PLUS_EXPR, addr, basetype, 1); |
| + |
| member = cp_convert (ptrdiff_type_node, member); |
| |
| addr = build (PLUS_EXPR, build_pointer_type (type), addr, member); |
| @@ -2212,7 +2181,7 @@ build_java_class_ref (type) |
| jclass_node = TREE_TYPE (jclass_node); |
| } |
| |
| - /* Mangle the class$ field, new and old ABI */ |
| + /* Mangle the class$ field */ |
| { |
| tree field; |
| for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) |
| @@ -2251,8 +2220,8 @@ get_cookie_size (type) |
| { |
| tree cookie_size; |
| |
| - /* Under the new ABI, we need to allocate an additional max |
| - (sizeof (size_t), alignof (true_type)) bytes. */ |
| + /* We need to allocate an additional max (sizeof (size_t), alignof |
| + (true_type)) bytes. */ |
| tree sizetype_size; |
| tree type_align; |
| |
| @@ -2359,9 +2328,7 @@ build_new_1 (exp) |
| if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type)) |
| use_cookie = 0; |
| /* When using placement new, users may not realize that they need |
| - the extra storage. Under the old ABI, we don't allocate the |
| - cookie whenever they use one placement argument of type `void |
| - *'. Under the new ABI, we require that the operator called be |
| + the extra storage. We require that the operator called be |
| the global placement operator delete[]. */ |
| else if (placement && !TREE_CHAIN (placement) |
| && same_type_p (TREE_TYPE (TREE_VALUE (placement)), |
| @@ -2478,9 +2445,8 @@ build_new_1 (exp) |
| tree cookie; |
| |
| /* Store the number of bytes allocated so that we can know how |
| - many elements to destroy later. Under the new ABI, we use |
| - the last sizeof (size_t) bytes to store the number of |
| - elements. */ |
| + many elements to destroy later. We use the last sizeof |
| + (size_t) bytes to store the number of elements. */ |
| cookie = build (MINUS_EXPR, build_pointer_type (sizetype), |
| alloc_node, size_in_bytes (sizetype)); |
| cookie = build_indirect_ref (cookie, NULL_PTR); |
| Index: gcc/cp/lang-specs.h |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/lang-specs.h,v |
| retrieving revision 1.39.2.4 |
| diff -u -p -r1.39.2.4 lang-specs.h |
| --- gcc/cp/lang-specs.h 2001/06/08 00:00:32 1.39.2.4 |
| +++ gcc/cp/lang-specs.h 2002/02/01 22:44:45 |
| @@ -38,14 +38,14 @@ Boston, MA 02111-1307, USA. */ |
| "%{E|M|MM:cpp0 -lang-c++ %{!no-gcc:-D__GNUG__=%v1}\ |
| %{!Wno-deprecated:-D__GXX_DEPRECATED}\ |
| %{!fno-exceptions:-D__EXCEPTIONS}\ |
| - %{!fno-new-abi:-D__GXX_ABI_VERSION=100}\ |
| + -D__GXX_ABI_VERSION=100\ |
| %{ansi:-D__STRICT_ANSI__ -trigraphs -$} %(cpp_options)}\ |
| %{!E:%{!M:%{!MM:\ |
| %{save-temps:cpp0 -lang-c++ \ |
| %{!no-gcc:-D__GNUG__=%v1}\ |
| %{!Wno-deprecated:-D__GXX_DEPRECATED}\ |
| %{!fno-exceptions:-D__EXCEPTIONS}\ |
| - %{!fno-new-abi:-D__GXX_ABI_VERSION=100}\ |
| + -D__GXX_ABI_VERSION=100\ |
| %{ansi:-D__STRICT_ANSI__ -trigraphs -$}\ |
| %(cpp_options) %b.ii \n}\ |
| cc1plus %{save-temps:-fpreprocessed %b.ii}\ |
| @@ -53,7 +53,7 @@ Boston, MA 02111-1307, USA. */ |
| %{!no-gcc:-D__GNUG__=%v1} \ |
| %{!Wno-deprecated:-D__GXX_DEPRECATED}\ |
| %{!fno-exceptions:-D__EXCEPTIONS}\ |
| - %{!fno-new-abi:-D__GXX_ABI_VERSION=100}\ |
| + -D__GXX_ABI_VERSION=100\ |
| %{ansi:-D__STRICT_ANSI__}}\ |
| %{ansi:-trigraphs -$}\ |
| %(cc1_options) %2 %{+e1*}\ |
| Index: gcc/cp/mangle.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/mangle.c,v |
| retrieving revision 1.26.4.9 |
| diff -u -p -r1.26.4.9 mangle.c |
| --- gcc/cp/mangle.c 2001/12/03 17:38:50 1.26.4.9 |
| +++ gcc/cp/mangle.c 2002/02/01 22:44:46 |
| @@ -1,4 +1,4 @@ |
| -/* Name mangling for the new standard C++ ABI. |
| +/* Name mangling for the 3.0 C++ ABI. |
| Copyright (C) 2000, 2001 Free Software Foundation, Inc. |
| Written by Alex Samuel <sameul@codesourcery.com> |
| |
| @@ -1195,10 +1195,7 @@ write_special_name_constructor (ctor) |
| <special-name> ::= D0 # deleting (in-charge) destructor |
| ::= D1 # complete object (in-charge) destructor |
| ::= D2 # base object (not-in-charge) destructor |
| - |
| - We also need to provide unique mngled names for old-ABI |
| - destructors, sometimes. These should only be used internally. We |
| - use "D*INTERNAL*" for these. */ |
| + */ |
| |
| static void |
| write_special_name_destructor (dtor) |
| Index: gcc/cp/method.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v |
| retrieving revision 1.190.2.15 |
| diff -u -p -r1.190.2.15 method.c |
| --- gcc/cp/method.c 2002/01/07 20:51:38 1.190.2.15 |
| +++ gcc/cp/method.c 2002/02/01 22:44:46 |
| @@ -600,8 +600,6 @@ do_build_copy_constructor (fndecl) |
| { |
| if (VFIELD_NAME_P (DECL_NAME (field))) |
| continue; |
| - if (VBASE_NAME_P (DECL_NAME (field))) |
| - continue; |
| |
| /* True for duplicate members. */ |
| if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) |
| @@ -689,8 +687,6 @@ do_build_assign_ref (fndecl) |
| if (DECL_NAME (field)) |
| { |
| if (VFIELD_NAME_P (DECL_NAME (field))) |
| - continue; |
| - if (VBASE_NAME_P (DECL_NAME (field))) |
| continue; |
| |
| /* True for duplicate members. */ |
| Index: gcc/cp/rtti.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v |
| retrieving revision 1.109.2.7 |
| diff -u -p -r1.109.2.7 rtti.c |
| --- gcc/cp/rtti.c 2001/12/06 12:54:19 1.109.2.7 |
| +++ gcc/cp/rtti.c 2002/02/01 22:44:47 |
| @@ -41,7 +41,6 @@ Boston, MA 02111-1307, USA. */ |
| |
| extern struct obstack permanent_obstack; |
| |
| -static tree build_headof_sub PARAMS((tree)); |
| static tree build_headof PARAMS((tree)); |
| static tree ifnonnull PARAMS((tree, tree)); |
| static tree tinfo_name PARAMS((tree)); |
| @@ -86,23 +85,6 @@ init_rtti_processing () |
| build_qualified_type (type_info_type_node, TYPE_QUAL_CONST); |
| } |
| |
| -/* Given a pointer to an object with at least one virtual table |
| - pointer somewhere, return a pointer to a possible sub-object that |
| - has a virtual table pointer in it that is the vtable parent for |
| - that sub-object. */ |
| - |
| -static tree |
| -build_headof_sub (exp) |
| - tree exp; |
| -{ |
| - tree type = TREE_TYPE (TREE_TYPE (exp)); |
| - tree basetype = CLASSTYPE_RTTI (type); |
| - tree binfo = get_binfo (basetype, type, 0); |
| - |
| - exp = convert_pointer_to_real (binfo, exp); |
| - return exp; |
| -} |
| - |
| /* Given the expression EXP of type `class *', return the head of the |
| object pointed to by EXP with type cv void*, if the class has any |
| virtual functions (TYPE_POLYMORPHIC_P), else just return the |
| @@ -113,7 +95,6 @@ build_headof (exp) |
| tree exp; |
| { |
| tree type = TREE_TYPE (exp); |
| - tree aref; |
| tree offset; |
| tree index; |
| |
| @@ -128,24 +109,14 @@ build_headof (exp) |
| return error_mark_node; |
| } |
| |
| - /* If we don't have rtti stuff, get to a sub-object that does. */ |
| - if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp)))) |
| - exp = build_headof_sub (exp); |
| - |
| /* We use this a couple of times below, protect it. */ |
| exp = save_expr (exp); |
| |
| - /* Under the new ABI, the offset-to-top field is at index -2 from |
| - the vptr. */ |
| + /* The offset-to-top field is at index -2 from the vptr. */ |
| index = build_int_2 (-2, -1); |
| |
| - aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), index); |
| + offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index); |
| |
| - if (flag_vtable_thunks) |
| - offset = aref; |
| - else |
| - offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0); |
| - |
| type = build_qualified_type (ptr_type_node, |
| CP_TYPE_QUALS (TREE_TYPE (exp))); |
| return build (PLUS_EXPR, type, exp, |
| @@ -220,22 +191,12 @@ get_tinfo_decl_dynamic (exp) |
| tree t; |
| tree index; |
| |
| - if (! flag_rtti) |
| - error ("taking dynamic typeid of object with -fno-rtti"); |
| if (CLASSTYPE_COM_INTERFACE (type)) |
| { |
| cp_error ("RTTI not supported for COM interface type `%T'", type); |
| return error_mark_node; |
| } |
| |
| - /* If we don't have rtti stuff, get to a sub-object that does. */ |
| - if (! CLASSTYPE_VFIELDS (type)) |
| - { |
| - exp = build_unary_op (ADDR_EXPR, exp, 0); |
| - exp = build_headof_sub (exp); |
| - exp = build_indirect_ref (exp, NULL_PTR); |
| - } |
| - |
| /* The RTTI information is at index -1. */ |
| index = integer_minus_one_node; |
| t = build_vtbl_ref (exp, index); |
| @@ -462,36 +423,12 @@ get_base_offset (binfo, parent) |
| { |
| if (! TREE_VIA_VIRTUAL (binfo)) |
| return BINFO_OFFSET (binfo); |
| - else if (! vbase_offsets_in_vtable_p ()) |
| - { |
| - const char *name; |
| - tree result; |
| - tree field; |
| - |
| - FORMAT_VBASE_NAME (name, BINFO_TYPE (binfo)); |
| - field = lookup_field (parent, get_identifier (name), 0, 0); |
| - result = byte_position (field); |
| - |
| - if (DECL_CONTEXT (field) != parent) |
| - { |
| - /* The vbase pointer might be in a non-virtual base of PARENT. |
| - * Adjust for the offset of that base in PARENT. */ |
| - tree path; |
| - |
| - get_base_distance (DECL_CONTEXT (field), parent, -1, &path); |
| - result = build (PLUS_EXPR, TREE_TYPE (result), |
| - result, BINFO_OFFSET (path)); |
| - result = fold (result); |
| - } |
| - return result; |
| - } |
| else |
| - /* Under the new ABI, we store the vtable offset at which |
| - the virtual base offset can be found. */ |
| + /* We store the vtable offset at which the virtual base offset can |
| + be found. */ |
| return convert (sizetype, |
| BINFO_VPTR_FIELD (binfo_for_vbase (BINFO_TYPE (binfo), |
| parent))); |
| - |
| } |
| |
| /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working |
| @@ -600,28 +537,15 @@ build_dynamic_cast_1 (type, expr) |
| /* If *type is an unambiguous accessible base class of *exprtype, |
| convert statically. */ |
| { |
| - int distance; |
| - tree path; |
| - |
| - distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1, |
| - &path); |
| + tree binfo; |
| |
| - if (distance == -2) |
| - { |
| - cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'", |
| - TREE_TYPE (exprtype), TREE_TYPE (type)); |
| - return error_mark_node; |
| - } |
| - if (distance == -3) |
| - { |
| - cp_error ("dynamic_cast from `%T' to private base class `%T'", |
| - TREE_TYPE (exprtype), TREE_TYPE (type)); |
| - return error_mark_node; |
| - } |
| + binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type), |
| + ba_not_special, NULL); |
| |
| - if (distance >= 0) |
| + if (binfo) |
| { |
| - expr = build_vbase_path (PLUS_EXPR, type, expr, path, 0); |
| + expr = build_base_path (PLUS_EXPR, convert_from_reference (expr), |
| + binfo, 0); |
| if (TREE_CODE (exprtype) == POINTER_TYPE) |
| expr = non_lvalue (expr); |
| return expr; |
| @@ -843,8 +767,8 @@ tinfo_base_init (desc, target) |
| DECL_EXTERNAL (name_decl) = 0; |
| TREE_PUBLIC (name_decl) = 1; |
| comdat_linkage (name_decl); |
| - /* The new ABI specifies the external name of the string |
| - containing the type's name. */ |
| + /* External name of the string containing the type's name has a |
| + special name. */ |
| SET_DECL_ASSEMBLER_NAME (name_decl, |
| mangle_typeinfo_string_for_type (target)); |
| DECL_INITIAL (name_decl) = name_string; |
| @@ -1232,7 +1156,11 @@ create_real_tinfo_var (target_type, name |
| tree decl; |
| tree hidden_name; |
| char hidden[30]; |
| - |
| + |
| + /* We cannot give this the name NAME, as that already is globally |
| + bound to the tinfo_decl we originally created for this type in |
| + get_tinfo_decl. */ |
| + |
| sprintf (hidden, "%.*s_%d", |
| IDENTIFIER_LENGTH (tinfo_decl_id), IDENTIFIER_POINTER (tinfo_decl_id), |
| count++); |
| @@ -1314,8 +1242,7 @@ create_pseudo_type_info VPARAMS((const c |
| vtable_decl = get_vtable_decl (real_type, /*complete=*/1); |
| vtable_decl = build_unary_op (ADDR_EXPR, vtable_decl, 0); |
| |
| - /* Under the new ABI, we need to point into the middle of the |
| - vtable. */ |
| + /* We need to point into the middle of the vtable. */ |
| vtable_decl = build (PLUS_EXPR, |
| TREE_TYPE (vtable_decl), |
| vtable_decl, |
| Index: gcc/cp/search.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v |
| retrieving revision 1.202.2.6 |
| diff -u -p -r1.202.2.6 search.c |
| --- gcc/cp/search.c 2001/06/08 17:12:41 1.202.2.6 |
| +++ gcc/cp/search.c 2002/02/01 22:44:49 |
| @@ -83,26 +83,21 @@ struct vbase_info |
| tree inits; |
| }; |
| |
| -static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *)); |
| static tree lookup_field_1 PARAMS ((tree, tree)); |
| static int is_subobject_of_p PARAMS ((tree, tree, tree)); |
| -static tree virtual_context PARAMS ((tree, tree, tree)); |
| static tree dfs_check_overlap PARAMS ((tree, void *)); |
| static tree dfs_no_overlap_yet PARAMS ((tree, void *)); |
| static int get_base_distance_recursive |
| PARAMS ((tree, int, int, int, int *, tree *, tree, |
| int, int *, int, int)); |
| +static base_kind lookup_base_r |
| + PARAMS ((tree, tree, base_access, |
| + int, int, int, tree *)); |
| static int dynamic_cast_base_recurse PARAMS ((tree, tree, int, tree *)); |
| -static void expand_upcast_fixups |
| - PARAMS ((tree, tree, tree, tree, tree, tree, tree *)); |
| -static void fixup_virtual_upcast_offsets |
| - PARAMS ((tree, tree, int, int, tree, tree, tree, tree, |
| - tree *)); |
| static tree marked_pushdecls_p PARAMS ((tree, void *)); |
| static tree unmarked_pushdecls_p PARAMS ((tree, void *)); |
| static tree dfs_debug_unmarkedp PARAMS ((tree, void *)); |
| static tree dfs_debug_mark PARAMS ((tree, void *)); |
| -static tree dfs_init_vbase_pointers PARAMS ((tree, void *)); |
| static tree dfs_get_vbase_types PARAMS ((tree, void *)); |
| static tree dfs_push_type_decls PARAMS ((tree, void *)); |
| static tree dfs_push_decls PARAMS ((tree, void *)); |
| @@ -140,7 +135,6 @@ static tree get_shared_vbase_if_not_prim |
| static tree dfs_find_vbase_instance PARAMS ((tree, void *)); |
| static tree dfs_get_pure_virtuals PARAMS ((tree, void *)); |
| static tree dfs_build_inheritance_graph_order PARAMS ((tree, void *)); |
| -static tree dfs_vtable_path_unmark PARAMS ((tree, void *)); |
| |
| /* Allocate a level of searching. */ |
| |
| @@ -177,76 +171,6 @@ static int n_contexts_saved; |
| #endif /* GATHER_STATISTICS */ |
| |
| |
| -/* Get a virtual binfo that is found inside BINFO's hierarchy that is |
| - the same type as the type given in PARENT. To be optimal, we want |
| - the first one that is found by going through the least number of |
| - virtual bases. |
| - |
| - This uses a clever algorithm that updates *depth when we find the vbase, |
| - and cuts off other paths of search when they reach that depth. */ |
| - |
| -static tree |
| -get_vbase_1 (parent, binfo, depth) |
| - tree parent, binfo; |
| - unsigned int *depth; |
| -{ |
| - tree binfos; |
| - int i, n_baselinks; |
| - tree rval = NULL_TREE; |
| - int virtualp = TREE_VIA_VIRTUAL (binfo) != 0; |
| - |
| - *depth -= virtualp; |
| - if (virtualp && BINFO_TYPE (binfo) == parent) |
| - { |
| - *depth = 0; |
| - return binfo; |
| - } |
| - |
| - binfos = BINFO_BASETYPES (binfo); |
| - n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; |
| - |
| - /* Process base types. */ |
| - for (i = 0; i < n_baselinks; i++) |
| - { |
| - tree base_binfo = TREE_VEC_ELT (binfos, i); |
| - tree nrval; |
| - |
| - if (*depth == 0) |
| - break; |
| - |
| - nrval = get_vbase_1 (parent, base_binfo, depth); |
| - if (nrval) |
| - rval = nrval; |
| - } |
| - *depth += virtualp; |
| - return rval; |
| -} |
| - |
| -/* Return the shortest path to vbase PARENT within BINFO, ignoring |
| - access and ambiguity. */ |
| - |
| -tree |
| -get_vbase (parent, binfo) |
| - tree parent; |
| - tree binfo; |
| -{ |
| - unsigned int d = (unsigned int)-1; |
| - return get_vbase_1 (parent, binfo, &d); |
| -} |
| - |
| -/* Convert EXPR to a virtual base class of type TYPE. We know that |
| - EXPR is a non-null POINTER_TYPE to RECORD_TYPE. We also know that |
| - the type of what expr points to has a virtual base of type TYPE. */ |
| - |
| -tree |
| -convert_pointer_to_vbase (type, expr) |
| - tree type; |
| - tree expr; |
| -{ |
| - tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr)))); |
| - return convert_pointer_to_real (vb, expr); |
| -} |
| - |
| /* Check whether the type given in BINFO is derived from PARENT. If |
| it isn't, return 0. If it is, but the derivation is MI-ambiguous |
| AND protect != 0, emit an error message and return error_mark_node. |
| @@ -414,9 +338,6 @@ get_base_distance_recursive (binfo, dept |
| If PROTECT is greater than 1, ignore any special access the current |
| scope might have when determining whether PARENT is inaccessible. |
| |
| - PARENT can also be a binfo, in which case that exact parent is found |
| - and no other. convert_pointer_to_real uses this functionality. |
| - |
| If BINFO is a binfo, its BINFO_INHERITANCE_CHAIN will be left alone. */ |
| |
| int |
| @@ -476,21 +397,198 @@ get_base_distance (parent, binfo, protec |
| if (rval && protect && rval_private) |
| return -3; |
| |
| - /* If they gave us the real vbase binfo, which isn't in the main binfo |
| - tree, deal with it. This happens when we are called from |
| - expand_upcast_fixups. */ |
| - if (rval == -1 && TREE_CODE (parent) == TREE_VEC |
| - && parent == binfo_for_vbase (BINFO_TYPE (parent), type)) |
| - { |
| - new_binfo = parent; |
| - rval = 1; |
| - } |
| - |
| if (path_ptr) |
| *path_ptr = new_binfo; |
| return rval; |
| } |
| |
| +/* Worker for lookup_base. BINFO is the binfo we are searching at, |
| + BASE is the RECORD_TYPE we are searching for. ACCESS is the |
| + required access checks. WITHIN_CURRENT_SCOPE, IS_NON_PUBLIC and |
| + IS_VIRTUAL indicate how BINFO was reached from the start of the |
| + search. WITHIN_CURRENT_SCOPE is true if we met the current scope, |
| + or friend thereof (this allows us to determine whether a protected |
| + base is accessible or not). IS_NON_PUBLIC indicates whether BINFO |
| + is accessible and IS_VIRTUAL indicates if it is morally virtual. |
| + |
| + If BINFO is of the required type, then *BINFO_PTR is examined to |
| + compare with any other instance of BASE we might have already |
| + discovered. *BINFO_PTR is initialized and a base_kind return value |
| + indicates what kind of base was located. |
| + |
| + Otherwise BINFO's bases are searched. */ |
| + |
| +static base_kind |
| +lookup_base_r (binfo, base, access, within_current_scope, |
| + is_non_public, is_virtual, binfo_ptr) |
| + tree binfo, base; |
| + base_access access; |
| + int within_current_scope; |
| + int is_non_public; /* inside a non-public part */ |
| + int is_virtual; /* inside a virtual part */ |
| + tree *binfo_ptr; |
| +{ |
| + int i; |
| + tree bases; |
| + base_kind found = bk_not_base; |
| + |
| + if (access == ba_check |
| + && !within_current_scope |
| + && is_friend (BINFO_TYPE (binfo), current_scope ())) |
| + { |
| + within_current_scope = 1; |
| + is_non_public = 0; |
| + } |
| + |
| + if (same_type_p (BINFO_TYPE (binfo), base)) |
| + { |
| + /* We have found a base. Check against what we have found |
| + already. */ |
| + found = bk_same_type; |
| + if (is_virtual) |
| + found = bk_via_virtual; |
| + if (is_non_public) |
| + found = bk_inaccessible; |
| + |
| + if (!*binfo_ptr) |
| + *binfo_ptr = binfo; |
| + else if (!is_virtual || !tree_int_cst_equal (BINFO_OFFSET (binfo), |
| + BINFO_OFFSET (*binfo_ptr))) |
| + { |
| + if (access != ba_any) |
| + *binfo_ptr = NULL; |
| + else if (found != is_virtual) |
| + /* Prefer a non-virtual base. */ |
| + *binfo_ptr = binfo; |
| + found = bk_ambig; |
| + } |
| + else if (found == bk_via_virtual) |
| + *binfo_ptr = binfo; |
| + |
| + return found; |
| + } |
| + |
| + bases = BINFO_BASETYPES (binfo); |
| + if (!bases) |
| + return bk_not_base; |
| + |
| + for (i = TREE_VEC_LENGTH (bases); i--;) |
| + { |
| + tree base_binfo = TREE_VEC_ELT (bases, i); |
| + int this_non_public = is_non_public; |
| + int this_virtual = is_virtual; |
| + |
| + if (access <= ba_ignore) |
| + ; /* no change */ |
| + else if (TREE_VIA_PUBLIC (base_binfo)) |
| + ; /* no change */ |
| + else if (access == ba_not_special) |
| + this_non_public = 1; |
| + else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope) |
| + ; /* no change */ |
| + else if (is_friend (BINFO_TYPE (binfo), current_scope ())) |
| + ; /* no change */ |
| + else |
| + this_non_public = 1; |
| + |
| + if (TREE_VIA_VIRTUAL (base_binfo)) |
| + this_virtual = 1; |
| + |
| + base_kind bk = lookup_base_r (base_binfo, base, |
| + access, within_current_scope, |
| + this_non_public, this_virtual, |
| + binfo_ptr); |
| + |
| + switch (bk) |
| + { |
| + case bk_ambig: |
| + if (access != ba_any) |
| + return bk; |
| + found = bk; |
| + break; |
| + |
| + case bk_inaccessible: |
| + if (found == bk_not_base) |
| + found = bk; |
| + my_friendly_assert (found == bk_via_virtual |
| + || found == bk_inaccessible, 20010723); |
| + |
| + break; |
| + |
| + case bk_same_type: |
| + bk = bk_proper_base; |
| + /* FALLTHROUGH */ |
| + case bk_proper_base: |
| + my_friendly_assert (found == bk_not_base, 20010723); |
| + found = bk; |
| + break; |
| + |
| + case bk_via_virtual: |
| + my_friendly_assert (found == bk_not_base |
| + || found == bk_via_virtual |
| + || found == bk_inaccessible, 20010723); |
| + found = bk; |
| + break; |
| + |
| + case bk_not_base: |
| + break; |
| + } |
| + } |
| + return found; |
| +} |
| + |
| +/* Lookup BASE in the hierarchy dominated by T. Do access checking as |
| + ACCESS specifies. Return the binfo we discover (which might not be |
| + canonical). If KIND_PTR is non-NULL, fill with information about |
| + what kind of base we discoveded. |
| + |
| + Issue an error message if an inaccessible or ambiguous base is |
| + discovered, and return error_mark_node. */ |
| + |
| +tree |
| +lookup_base (t, base, access, kind_ptr) |
| + tree t, base; |
| + base_access access; |
| + base_kind *kind_ptr; |
| +{ |
| + tree binfo = NULL; /* The binfo we've found so far. */ |
| + base_kind bk; |
| + |
| + if (t == error_mark_node || base == error_mark_node) |
| + { |
| + if (kind_ptr) |
| + *kind_ptr = bk_not_base; |
| + return error_mark_node; |
| + } |
| + |
| + t = TYPE_MAIN_VARIANT (t); |
| + base = TYPE_MAIN_VARIANT (base); |
| + |
| + bk = lookup_base_r (TYPE_BINFO (t), base, access, 0, 0, 0, &binfo); |
| + |
| + switch (bk) |
| + { |
| + case bk_inaccessible: |
| + cp_error ("`%T' is an inaccessible base of `%T'", base, t); |
| + binfo = error_mark_node; |
| + break; |
| + case bk_ambig: |
| + if (access != ba_any) |
| + { |
| + cp_error ("`%T' is an ambiguous base of `%T'", base, t); |
| + binfo = error_mark_node; |
| + } |
| + break; |
| + |
| + default:; |
| + } |
| + |
| + if (kind_ptr) |
| + *kind_ptr = bk; |
| + |
| + return binfo; |
| +} |
| + |
| /* Worker function for get_dynamic_cast_base_type. */ |
| |
| static int |
| @@ -1467,15 +1565,6 @@ lookup_field_r (binfo, data) |
| } |
| else |
| { |
| - /* If the thing we're looking for is a virtual base class, then |
| - we know we've got what we want at this point; there's no way |
| - to get an ambiguity. */ |
| - if (VBASE_NAME_P (lfi->name)) |
| - { |
| - lfi->rval = nval; |
| - return nval; |
| - } |
| - |
| if (from_dep_base_p && TREE_CODE (nval) != TYPE_DECL |
| /* We need to return a member template class so we can |
| define partial specializations. Is there a better |
| @@ -2333,391 +2422,6 @@ dfs_unmark (binfo, data) |
| } |
| |
| |
| -static tree |
| -dfs_init_vbase_pointers (binfo, data) |
| - tree binfo; |
| - void *data; |
| -{ |
| - struct vbase_info *vi = (struct vbase_info *) data; |
| - tree type = BINFO_TYPE (binfo); |
| - tree fields; |
| - tree this_vbase_ptr; |
| - |
| - /* Don't initialize the same base more than once. */ |
| - SET_BINFO_VTABLE_PATH_MARKED (binfo); |
| - |
| - /* We know that VI->DECL_PTR points to the complete object. So, |
| - finding a pointer to this subobject is easy. */ |
| - this_vbase_ptr = build (PLUS_EXPR, |
| - build_pointer_type (type), |
| - vi->decl_ptr, |
| - BINFO_OFFSET (binfo)); |
| - |
| - /* We're going to iterate through all the pointers to virtual |
| - base-classes. They come at the beginning of the class. */ |
| - fields = TYPE_FIELDS (type); |
| - |
| - if (fields == NULL_TREE |
| - || DECL_NAME (fields) == NULL_TREE |
| - || ! VBASE_NAME_P (DECL_NAME (fields))) |
| - return NULL_TREE; |
| - |
| - if (build_pointer_type (type) |
| - != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr))) |
| - my_friendly_abort (125); |
| - |
| - while (fields && DECL_NAME (fields) && VBASE_NAME_P (DECL_NAME (fields))) |
| - { |
| - tree ref = build (COMPONENT_REF, TREE_TYPE (fields), |
| - build_indirect_ref (this_vbase_ptr, NULL_PTR), fields); |
| - tree init; |
| - tree vbase_type; |
| - tree vbase_binfo; |
| - |
| - vbase_type = TREE_TYPE (TREE_TYPE (fields)); |
| - vbase_binfo = binfo_for_vbase (vbase_type, vi->type); |
| - init = build (PLUS_EXPR, |
| - build_pointer_type (vbase_type), |
| - vi->decl_ptr, |
| - BINFO_OFFSET (vbase_binfo)); |
| - vi->inits |
| - = tree_cons (vbase_binfo, |
| - build_modify_expr (ref, NOP_EXPR, init), |
| - vi->inits); |
| - fields = TREE_CHAIN (fields); |
| - } |
| - |
| - return NULL_TREE; |
| -} |
| - |
| -/* Call CLEAR_BINFO_VTABLE_PATH_MARKED for BINFO. */ |
| - |
| -static tree |
| -dfs_vtable_path_unmark (binfo, data) |
| - tree binfo; |
| - void *data ATTRIBUTE_UNUSED; |
| -{ |
| - CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); |
| - return NULL_TREE; |
| -} |
| - |
| -tree |
| -init_vbase_pointers (type, decl_ptr) |
| - tree type; |
| - tree decl_ptr; |
| -{ |
| - my_friendly_assert (!vbase_offsets_in_vtable_p (), 20000516); |
| - |
| - if (TYPE_USES_VIRTUAL_BASECLASSES (type)) |
| - { |
| - struct vbase_info vi; |
| - tree binfo = TYPE_BINFO (type); |
| - |
| - /* Find all the virtual base classes, marking them for later |
| - initialization. */ |
| - vi.type = type; |
| - vi.decl_ptr = decl_ptr; |
| - vi.inits = NULL_TREE; |
| - |
| - /* Build up a list of the initializers. */ |
| - dfs_walk_real (binfo, |
| - dfs_init_vbase_pointers, 0, |
| - unmarked_vtable_pathp, |
| - &vi); |
| - dfs_walk (binfo, |
| - dfs_vtable_path_unmark, |
| - marked_vtable_pathp, |
| - NULL); |
| - |
| - return vi.inits; |
| - } |
| - |
| - return 0; |
| -} |
| - |
| -/* get the virtual context (the vbase that directly contains the |
| - DECL_CONTEXT of the FNDECL) that the given FNDECL is declared in, |
| - or NULL_TREE if there is none. |
| - |
| - FNDECL must come from a virtual table from a virtual base to ensure |
| - that there is only one possible DECL_CONTEXT. |
| - |
| - We know that if there is more than one place (binfo) the fndecl that the |
| - declared, they all refer to the same binfo. See get_class_offset_1 for |
| - the check that ensures this. */ |
| - |
| -static tree |
| -virtual_context (fndecl, t, vbase) |
| - tree fndecl, t, vbase; |
| -{ |
| - tree path; |
| - if (get_base_distance (DECL_CONTEXT (fndecl), t, 0, &path) < 0) |
| - { |
| - /* DECL_CONTEXT can be ambiguous in t. */ |
| - if (get_base_distance (DECL_CONTEXT (fndecl), vbase, 0, &path) >= 0) |
| - { |
| - while (path) |
| - { |
| - /* Not sure if checking path == vbase is necessary here, but just in |
| - case it is. */ |
| - if (TREE_VIA_VIRTUAL (path) || path == vbase) |
| - return binfo_for_vbase (BINFO_TYPE (path), t); |
| - path = BINFO_INHERITANCE_CHAIN (path); |
| - } |
| - } |
| - /* This shouldn't happen, I don't want errors! */ |
| - warning ("recoverable compiler error, fixups for virtual function"); |
| - return vbase; |
| - } |
| - while (path) |
| - { |
| - if (TREE_VIA_VIRTUAL (path)) |
| - return binfo_for_vbase (BINFO_TYPE (path), t); |
| - path = BINFO_INHERITANCE_CHAIN (path); |
| - } |
| - return 0; |
| -} |
| - |
| -/* Fixups upcast offsets for one vtable. |
| - Entries may stay within the VBASE given, or |
| - they may upcast into a direct base, or |
| - they may upcast into a different vbase. |
| - |
| - We only need to do fixups in case 2 and 3. In case 2, we add in |
| - the virtual base offset to effect an upcast, in case 3, we add in |
| - the virtual base offset to effect an upcast, then subtract out the |
| - offset for the other virtual base, to effect a downcast into it. |
| - |
| - This routine mirrors fixup_vtable_deltas in functionality, though |
| - this one is runtime based, and the other is compile time based. |
| - Conceivably that routine could be removed entirely, and all fixups |
| - done at runtime. |
| - |
| - VBASE_OFFSETS is an association list of virtual bases that contains |
| - offset information for the virtual bases, so the offsets are only |
| - calculated once. */ |
| - |
| -static void |
| -expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, |
| - vbase_offsets) |
| - tree binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets; |
| -{ |
| - tree virtuals; |
| - tree vc; |
| - tree delta; |
| - HOST_WIDE_INT n; |
| - |
| - while (BINFO_PRIMARY_P (binfo)) |
| - { |
| - binfo = BINFO_INHERITANCE_CHAIN (binfo); |
| - if (TREE_VIA_VIRTUAL (binfo)) |
| - return; |
| - } |
| - |
| - delta = purpose_member (vbase, *vbase_offsets); |
| - if (! delta) |
| - { |
| - delta = build (PLUS_EXPR, |
| - build_pointer_type (BINFO_TYPE (vbase)), |
| - orig_addr, |
| - BINFO_OFFSET (vbase)); |
| - delta = build (MINUS_EXPR, ptrdiff_type_node, delta, vbase_addr); |
| - delta = save_expr (delta); |
| - delta = tree_cons (vbase, delta, *vbase_offsets); |
| - *vbase_offsets = delta; |
| - } |
| - |
| - for (virtuals = BINFO_VIRTUALS (binfo), n = 0; |
| - virtuals; |
| - virtuals = TREE_CHAIN (virtuals), ++n) |
| - { |
| - tree current_fndecl = TREE_VALUE (virtuals); |
| - |
| - if (current_fndecl |
| - && current_fndecl != abort_fndecl |
| - && (vc=virtual_context (current_fndecl, t, vbase)) != vbase) |
| - { |
| - /* This may in fact need a runtime fixup. */ |
| - tree idx = build_int_2 (n, 0); |
| - tree vtbl = BINFO_VTABLE (binfo); |
| - tree nvtbl = lookup_name (DECL_NAME (vtbl), 0); |
| - tree aref, ref, naref; |
| - tree old_delta, new_delta; |
| - tree init; |
| - |
| - if (nvtbl == NULL_TREE |
| - || nvtbl == IDENTIFIER_GLOBAL_VALUE (DECL_NAME (vtbl))) |
| - { |
| - /* Dup it if it isn't in local scope yet. */ |
| - nvtbl = build_decl |
| - (VAR_DECL, DECL_NAME (vtbl), |
| - TYPE_MAIN_VARIANT (TREE_TYPE (vtbl))); |
| - DECL_ALIGN (nvtbl) = MAX (TYPE_ALIGN (double_type_node), |
| - DECL_ALIGN (nvtbl)); |
| - TREE_READONLY (nvtbl) = 0; |
| - DECL_ARTIFICIAL (nvtbl) = 1; |
| - nvtbl = pushdecl (nvtbl); |
| - init = NULL_TREE; |
| - cp_finish_decl (nvtbl, init, NULL_TREE, |
| - LOOKUP_ONLYCONVERTING); |
| - |
| - /* We don't set DECL_VIRTUAL_P and DECL_CONTEXT on nvtbl |
| - because they wouldn't be useful; everything that wants to |
| - look at the vtable will look at the decl for the normal |
| - vtable. Setting DECL_CONTEXT also screws up |
| - decl_function_context. */ |
| - |
| - init = build (MODIFY_EXPR, TREE_TYPE (nvtbl), |
| - nvtbl, vtbl); |
| - finish_expr_stmt (init); |
| - /* Update the vtable pointers as necessary. */ |
| - ref = build_vfield_ref |
| - (build_indirect_ref (addr, NULL_PTR), |
| - DECL_CONTEXT (TYPE_VFIELD (BINFO_TYPE (binfo)))); |
| - finish_expr_stmt |
| - (build_modify_expr (ref, NOP_EXPR, nvtbl)); |
| - } |
| - assemble_external (vtbl); |
| - aref = build_array_ref (vtbl, idx); |
| - naref = build_array_ref (nvtbl, idx); |
| - old_delta = build_component_ref (aref, delta_identifier, |
| - NULL_TREE, 0); |
| - new_delta = build_component_ref (naref, delta_identifier, |
| - NULL_TREE, 0); |
| - |
| - /* This is a upcast, so we have to add the offset for the |
| - virtual base. */ |
| - old_delta = cp_build_binary_op (PLUS_EXPR, old_delta, |
| - TREE_VALUE (delta)); |
| - if (vc) |
| - { |
| - /* If this is set, we need to subtract out the delta |
| - adjustments for the other virtual base that we |
| - downcast into. */ |
| - tree vc_delta = purpose_member (vc, *vbase_offsets); |
| - if (! vc_delta) |
| - { |
| - tree vc_addr = convert_pointer_to_real (vc, orig_addr); |
| - vc_delta = build (PLUS_EXPR, |
| - build_pointer_type (BINFO_TYPE (vc)), |
| - orig_addr, |
| - BINFO_OFFSET (vc)); |
| - vc_delta = build (MINUS_EXPR, ptrdiff_type_node, |
| - vc_delta, vc_addr); |
| - vc_delta = save_expr (vc_delta); |
| - *vbase_offsets = tree_cons (vc, vc_delta, *vbase_offsets); |
| - } |
| - else |
| - vc_delta = TREE_VALUE (vc_delta); |
| - |
| - /* This is a downcast, so we have to subtract the offset |
| - for the virtual base. */ |
| - old_delta = cp_build_binary_op (MINUS_EXPR, old_delta, vc_delta); |
| - } |
| - |
| - TREE_READONLY (new_delta) = 0; |
| - TREE_TYPE (new_delta) = |
| - cp_build_qualified_type (TREE_TYPE (new_delta), |
| - CP_TYPE_QUALS (TREE_TYPE (new_delta)) |
| - & ~TYPE_QUAL_CONST); |
| - finish_expr_stmt (build_modify_expr (new_delta, NOP_EXPR, |
| - old_delta)); |
| - } |
| - } |
| -} |
| - |
| -/* Fixup upcast offsets for all direct vtables. Patterned after |
| - expand_direct_vtbls_init. */ |
| - |
| -static void |
| -fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, orig_addr, type, vbase, vbase_offsets) |
| - tree real_binfo, binfo; |
| - int init_self, can_elide; |
| - tree addr, orig_addr, type, vbase, *vbase_offsets; |
| -{ |
| - tree real_binfos = BINFO_BASETYPES (real_binfo); |
| - tree binfos = BINFO_BASETYPES (binfo); |
| - int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0; |
| - |
| - for (i = 0; i < n_baselinks; i++) |
| - { |
| - tree real_base_binfo = TREE_VEC_ELT (real_binfos, i); |
| - tree base_binfo = TREE_VEC_ELT (binfos, i); |
| - int is_not_base_vtable |
| - = !BINFO_PRIMARY_P (real_base_binfo); |
| - if (! TREE_VIA_VIRTUAL (real_base_binfo)) |
| - fixup_virtual_upcast_offsets (real_base_binfo, base_binfo, |
| - is_not_base_vtable, can_elide, addr, |
| - orig_addr, type, vbase, vbase_offsets); |
| - } |
| -#if 0 |
| - /* Before turning this on, make sure it is correct. */ |
| - if (can_elide && ! BINFO_MODIFIED (binfo)) |
| - return; |
| -#endif |
| - /* Should we use something besides CLASSTYPE_VFIELDS? */ |
| - if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo))) |
| - { |
| - tree new_addr = convert_pointer_to_real (binfo, addr); |
| - expand_upcast_fixups (real_binfo, new_addr, orig_addr, vbase, addr, |
| - type, vbase_offsets); |
| - } |
| -} |
| - |
| -/* Fixup all the virtual upcast offsets for TYPE. DECL_PTR is the |
| - address of the sub-object being initialized. */ |
| - |
| -void |
| -fixup_all_virtual_upcast_offsets (decl_ptr) |
| - tree decl_ptr; |
| -{ |
| - tree if_stmt; |
| - tree in_charge_node; |
| - tree vbases; |
| - tree type; |
| - |
| - /* 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 = cp_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. */ |
| - type = TREE_TYPE (TREE_TYPE (decl_ptr)); |
| - 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; |
| - tree vbase_offsets; |
| - tree addr; |
| - |
| - vbase = find_vbase_instance (TREE_PURPOSE (vbases), type); |
| - vbase_offsets = NULL_TREE; |
| - addr = convert_pointer_to_vbase (TREE_PURPOSE (vbases), decl_ptr); |
| - fixup_virtual_upcast_offsets (vbase, |
| - TYPE_BINFO (TREE_PURPOSE (vbases)), |
| - 1, 0, addr, decl_ptr, |
| - type, vbase, &vbase_offsets); |
| - } |
| - } |
| - |
| - /* Close out the if-statement. */ |
| - finish_then_clause (if_stmt); |
| - finish_if_stmt (); |
| -} |
| - |
| /* get virtual base class types. |
| This adds type to the vbase_types list in reverse dfs order. |
| Ordering is very important, so don't change it. */ |
| Index: gcc/cp/semantics.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v |
| retrieving revision 1.189.2.19 |
| diff -u -p -r1.189.2.19 semantics.c |
| --- gcc/cp/semantics.c 2002/01/31 22:46:46 1.189.2.19 |
| +++ gcc/cp/semantics.c 2002/02/01 22:44:51 |
| @@ -2349,7 +2349,7 @@ emit_associated_thunks (fn) |
| is so that you can know statically the entire set of thunks that |
| will ever be needed for a given virtual function, thereby |
| enabling you to output all the thunks with the function itself. */ |
| - if (vcall_offsets_in_vtable_p () && DECL_VIRTUAL_P (fn)) |
| + if (DECL_VIRTUAL_P (fn)) |
| { |
| tree binfo; |
| tree v; |
| @@ -2415,8 +2415,8 @@ expand_body (fn) |
| simplify_aggr_init_exprs_r, |
| NULL); |
| |
| - /* If this is a constructor or destructor body, we have to clone it |
| - under the new ABI. */ |
| + /* If this is a constructor or destructor body, we have to clone |
| + it. */ |
| if (maybe_clone_body (fn)) |
| { |
| /* We don't want to process FN again, so pretend we've written |
| Index: gcc/cp/tree.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v |
| retrieving revision 1.232.2.10 |
| diff -u -p -r1.232.2.10 tree.c |
| --- gcc/cp/tree.c 2001/11/30 03:12:44 1.232.2.10 |
| +++ gcc/cp/tree.c 2002/02/01 22:44:52 |
| @@ -2220,12 +2220,6 @@ cp_valid_lang_attribute (attr_name, attr |
| } |
| if (is_attribute_p ("com_interface", attr_name)) |
| { |
| - if (! flag_vtable_thunks) |
| - { |
| - error ("`com_interface' only supported with -fvtable-thunks"); |
| - return 0; |
| - } |
| - |
| if (attr_args != NULL_TREE |
| || decl != NULL_TREE |
| || ! CLASS_TYPE_P (type) |
| Index: gcc/cp/typeck.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v |
| retrieving revision 1.337.2.11 |
| diff -u -p -r1.337.2.11 typeck.c |
| --- gcc/cp/typeck.c 2001/11/20 04:39:23 1.337.2.11 |
| +++ gcc/cp/typeck.c 2002/02/01 22:44:58 |
| @@ -114,8 +114,11 @@ require_complete_type (value) |
| { |
| tree base, member = TREE_OPERAND (value, 1); |
| tree basetype = TYPE_OFFSET_BASETYPE (type); |
| + |
| my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305); |
| - base = convert_pointer_to (basetype, current_class_ptr); |
| + basetype = lookup_base (current_class_type, basetype, ba_check, NULL); |
| + base = build_base_path (PLUS_EXPR, current_class_ptr, basetype, 1); |
| + |
| value = build (COMPONENT_REF, TREE_TYPE (member), |
| build_indirect_ref (base, NULL_PTR), member); |
| return require_complete_type (value); |
| @@ -2235,23 +2238,15 @@ build_component_ref (datum, component, b |
| /* Handle base classes here... */ |
| if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype)) |
| { |
| - tree addr = build_unary_op (ADDR_EXPR, datum, 0); |
| - if (integer_zerop (addr)) |
| + tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, NULL); |
| + |
| + if (TREE_CODE (datum) == INDIRECT_REF |
| + && integer_zerop (TREE_OPERAND (datum, 0))) |
| { |
| error ("invalid reference to NULL ptr, use ptr-to-member instead"); |
| return error_mark_node; |
| - } |
| - if (VBASE_NAME_P (DECL_NAME (field))) |
| - { |
| - /* It doesn't matter which vbase pointer we grab, just |
| - find one of them. */ |
| - tree binfo = get_binfo (base, |
| - TREE_TYPE (TREE_TYPE (addr)), 0); |
| - addr = convert_pointer_to_real (binfo, addr); |
| } |
| - else |
| - addr = convert_pointer_to (base, addr); |
| - datum = build_indirect_ref (addr, NULL_PTR); |
| + datum = build_base_path (PLUS_EXPR, datum, binfo, 1); |
| if (datum == error_mark_node) |
| return error_mark_node; |
| } |
| @@ -2842,8 +2837,11 @@ build_x_function_call (function, params, |
| if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE |
| && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (decl))) |
| { |
| + tree binfo = lookup_base (TREE_TYPE (decl), TREE_TYPE (ctypeptr), |
| + ba_check, NULL); |
| + |
| decl = build_unary_op (ADDR_EXPR, decl, 0); |
| - decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl); |
| + decl = build_base_path (PLUS_EXPR, decl, binfo, 1); |
| } |
| else |
| decl = build_c_cast (ctypeptr, decl); |
| @@ -2862,13 +2860,11 @@ get_member_function_from_ptrfunc (instan |
| tree function; |
| { |
| if (TREE_CODE (function) == OFFSET_REF) |
| - { |
| - function = TREE_OPERAND (function, 1); |
| - } |
| + function = TREE_OPERAND (function, 1); |
| |
| if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) |
| { |
| - tree fntype, idx, e1, delta, delta2, e2, e3, aref, vtbl; |
| + tree fntype, idx, e1, delta, delta2, e2, e3, vtbl; |
| tree instance, basetype; |
| |
| tree instance_ptr = *instance_ptrptr; |
| @@ -2893,14 +2889,18 @@ get_member_function_from_ptrfunc (instan |
| fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)); |
| basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)); |
| |
| - /* Convert down to the right base, before using the instance. */ |
| - instance = convert_pointer_to_real (basetype, instance_ptr); |
| + /* Convert down to the right base, before using the instance. */ |
| + instance = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype, |
| + ba_check, NULL); |
| + instance = build_base_path (PLUS_EXPR, instance_ptr, instance, 1); |
| if (instance == error_mark_node && instance_ptr != error_mark_node) |
| return instance; |
| |
| e3 = PFN_FROM_PTRMEMFUNC (function); |
| - |
| - vtbl = convert_pointer_to (ptr_type_node, instance); |
| + |
| + vtbl = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), instance); |
| + TREE_CONSTANT (vtbl) = TREE_CONSTANT (instance); |
| + |
| delta = cp_convert (ptrdiff_type_node, |
| build_component_ref (function, delta_identifier, |
| NULL_TREE, 0)); |
| @@ -2950,27 +2950,8 @@ get_member_function_from_ptrfunc (instan |
| build_pointer_type (build_pointer_type (vtable_entry_type)), |
| vtbl, cp_convert (ptrdiff_type_node, delta2)); |
| vtbl = build_indirect_ref (vtbl, NULL_PTR); |
| - aref = build_array_ref (vtbl, idx); |
| - |
| - if (! flag_vtable_thunks) |
| - { |
| - aref = save_expr (aref); |
| - |
| - delta = cp_build_binary_op |
| - (PLUS_EXPR, |
| - build_conditional_expr (e1, |
| - build_component_ref (aref, |
| - delta_identifier, |
| - NULL_TREE, 0), |
| - integer_zero_node), |
| - delta); |
| - } |
| + e2 = build_array_ref (vtbl, idx); |
| |
| - if (flag_vtable_thunks) |
| - e2 = aref; |
| - else |
| - e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0); |
| - |
| /* When using function descriptors, the address of the |
| vtable entry is treated as a function pointer. */ |
| if (TARGET_VTABLE_USES_DESCRIPTORS) |
| @@ -4277,8 +4258,11 @@ build_component_addr (arg, argtype) |
| /* Can't convert directly to ARGTYPE, since that |
| may have the same pointer type as one of our |
| baseclasses. */ |
| - rval = build1 (NOP_EXPR, argtype, |
| - convert_pointer_to (basetype, rval)); |
| + tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)), basetype, |
| + ba_check, NULL); |
| + |
| + rval = build_base_path (PLUS_EXPR, rval, binfo, 1); |
| + rval = build1 (NOP_EXPR, argtype, rval); |
| TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0)); |
| } |
| else |
| @@ -6107,8 +6091,7 @@ build_ptrmemfunc (type, pfn, force) |
| delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0); |
| } |
| |
| - /* Under the new ABI, the conversion is easy. Just adjust |
| - the DELTA field. */ |
| + /* Just adjust the DELTA field. */ |
| delta = cp_convert (ptrdiff_type_node, delta); |
| if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta) |
| n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node); |
| @@ -6173,10 +6156,9 @@ expand_ptrmemfunc_cst (cst, delta, pfn) |
| *delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta), |
| *delta, BINFO_OFFSET (binfo))); |
| |
| - /* Under the new ABI, we set PFN to the vtable offset at |
| - which the function can be found, plus one (unless |
| - ptrmemfunc_vbit_in_delta, in which case delta is shifted |
| - left, and then incremented). */ |
| + /* We set PFN to the vtable offset at which the function can be |
| + found, plus one (unless ptrmemfunc_vbit_in_delta, in which |
| + case delta is shifted left, and then incremented). */ |
| *pfn = DECL_VINDEX (fn); |
| *pfn = fold (build (MULT_EXPR, integer_type_node, *pfn, |
| TYPE_SIZE_UNIT (vtable_entry_type))); |
| Index: gcc/cp/typeck2.c |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v |
| retrieving revision 1.97.2.2 |
| diff -u -p -r1.97.2.2 typeck2.c |
| --- gcc/cp/typeck2.c 2001/04/12 05:26:11 1.97.2.2 |
| +++ gcc/cp/typeck2.c 2002/02/01 22:44:58 |
| @@ -980,12 +980,17 @@ build_scoped_ref (datum, basetype) |
| tree basetype; |
| { |
| tree ref; |
| + tree binfo; |
| |
| if (datum == error_mark_node) |
| return error_mark_node; |
| + binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL); |
| |
| + if (!binfo) |
| + return error_not_base_type (TREE_TYPE (datum), basetype); |
| + |
| ref = build_unary_op (ADDR_EXPR, datum, 0); |
| - ref = convert_pointer_to (basetype, ref); |
| + ref = build_base_path (PLUS_EXPR, ref, binfo, 1); |
| |
| return build_indirect_ref (ref, "(compiler error in build_scoped_ref)"); |
| } |