From d28742934453813f3e98c255ccc4ae638c253ee6 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 17 Jan 2000 04:08:01 +0000 Subject: * cp-tree.h (flag_new_abi): Move. (flag_use_cxa_atexit): Likewise. (flag_honor_std): Likewise. (flag_rtti): Likewise. (vbase_offsets_in_vtable_p): Define. (vptrs_present_everywhere_p): Likewise. (TYPE_CONTAINS_VPTR_P): Likewise. (dfs_walk_real): Declare. * class.c (build_vbase_pointer_fields): Check vbase_offsets_in_vtable_p. (dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in BINFO_VPTR_FIELD. (build_vbase_offset_vtbl_entries): Simplify. (build_vbase_offset_vtbl_entries): Adjust. (build_vbase_pointer): Add ability to look up vbase offsets in vtable. (start_vtable): New function. (add_virtual_function): Use it. (determine_primary_base): Use TYPE_CONTAINS_VPTR_P. (num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p. (build_vtbl_initializer): Take the type of the complete object as input. Use it to correctly calculate vbase offsets. (dfs_finish_vtbls): Pass the complete type to build_vtbl_initializer. (check_bases_and_members): Use TYPE_CONTAINS_VPTR_P. (create_vtable_ptr): Create a vtable even if there are no new virtual functions, under the new ABI. (finish_struct_1): Likewise. (get_vfield_name): Use TYPE_CONTAINS_VPTR_P. * decl.c (exapnd_static_init): Remove call to preserve_initializer. * decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in vtables. * init.c (initialize_vtbl_ptrs): Initialize them in pre-order. (expand_virtual_init): Use vbase_offsets_in_vtable_p. (construct_virtual_bases): Don't initialize virtual base pointers under the new ABI. (build_aggr_init): Clean up comment. (expand_aggr_init_1): Likewise. * rtti.c (expand_class_desc): Store the virtual function table index where the vbase offset lives in the offset field. * search.c (dfs_walk_real): Make it global. (dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P. * tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD. * tinfo.h (USItype): Make it signed under the new ABI. * tinfo.cc (convert_to_base): New function. Encapsulate base conversion logic here. (__class_type_info::do_upcast): Use it. (__class_type_info::do_dyncast): Likewise. (__class_type_info::do_find_public_subobj): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@31452 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 52 ++++++++++++++ gcc/cp/class.c | 213 ++++++++++++++++++++++++++++++++++--------------------- gcc/cp/cp-tree.h | 65 ++++++++++++----- gcc/cp/decl.c | 10 +-- gcc/cp/decl2.c | 5 +- gcc/cp/init.c | 41 +++++------ gcc/cp/rtti.c | 34 ++++++--- gcc/cp/search.c | 13 ++-- gcc/cp/tinfo.cc | 67 +++++++++++------ gcc/cp/tinfo.h | 6 +- gcc/cp/tree.c | 1 - 11 files changed, 335 insertions(+), 172 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a8d7922bc6c..f8f2bdf285d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,57 @@ 2000-01-16 Mark Mitchell + * cp-tree.h (flag_new_abi): Move. + (flag_use_cxa_atexit): Likewise. + (flag_honor_std): Likewise. + (flag_rtti): Likewise. + (vbase_offsets_in_vtable_p): Define. + (vptrs_present_everywhere_p): Likewise. + (TYPE_CONTAINS_VPTR_P): Likewise. + (dfs_walk_real): Declare. + * class.c (build_vbase_pointer_fields): Check + vbase_offsets_in_vtable_p. + (dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in + BINFO_VPTR_FIELD. + (build_vbase_offset_vtbl_entries): Simplify. + (build_vbase_offset_vtbl_entries): Adjust. + (build_vbase_pointer): Add ability to look up vbase offsets in + vtable. + (start_vtable): New function. + (add_virtual_function): Use it. + (determine_primary_base): Use TYPE_CONTAINS_VPTR_P. + (num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p. + (build_vtbl_initializer): Take the type of the complete object as + input. Use it to correctly calculate vbase offsets. + (dfs_finish_vtbls): Pass the complete type to + build_vtbl_initializer. + (check_bases_and_members): Use TYPE_CONTAINS_VPTR_P. + (create_vtable_ptr): Create a vtable even if there are no + new virtual functions, under the new ABI. + (finish_struct_1): Likewise. + (get_vfield_name): Use TYPE_CONTAINS_VPTR_P. + * decl.c (exapnd_static_init): Remove call to + preserve_initializer. + * decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in + vtables. + * init.c (initialize_vtbl_ptrs): Initialize them in pre-order. + (expand_virtual_init): Use vbase_offsets_in_vtable_p. + (construct_virtual_bases): Don't initialize virtual base pointers + under the new ABI. + (build_aggr_init): Clean up comment. + (expand_aggr_init_1): Likewise. + * rtti.c (expand_class_desc): Store the virtual function table + index where the vbase offset lives in the offset field. + * search.c (dfs_walk_real): Make it global. + (dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P. + * tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD. + + * tinfo.h (USItype): Make it signed under the new ABI. + * tinfo.cc (convert_to_base): New function. Encapsulate base + conversion logic here. + (__class_type_info::do_upcast): Use it. + (__class_type_info::do_dyncast): Likewise. + (__class_type_info::do_find_public_subobj): Likewise. + * init.c (construct_virtual_bases): Don't look up the addresses of virtual bases at run-time. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a557292757d..8c1073e64bf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -115,7 +115,7 @@ static tree resolve_address_of_overloaded_function PROTO((tree, tree, int, int, tree)); static void build_vtable_entry_ref PROTO((tree, tree, tree)); static tree build_vtable_entry_for_fn PROTO((tree, tree)); -static tree build_vtbl_initializer PROTO((tree)); +static tree build_vtbl_initializer PROTO((tree, tree)); static int count_fields PROTO((tree)); static int add_fields_to_vec PROTO((tree, tree, int)); static void check_bitfield_decl PROTO((tree)); @@ -145,7 +145,8 @@ static void remove_base_fields PROTO((tree)); static tree dfs_set_offset_for_shared_vbases PROTO((tree, void *)); static tree dfs_set_offset_for_unshared_vbases PROTO((tree, void *)); static tree dfs_build_vbase_offset_vtbl_entries PROTO((tree, void *)); -static tree build_vbase_offset_vtbl_entries PROTO((tree)); +static tree build_vbase_offset_vtbl_entries PROTO((tree, tree)); +static void start_vtable PROTO((tree, int *)); /* Variables shared between class.c and call.c. */ @@ -178,9 +179,12 @@ build_vbase_pointer_fields (rec, empty_p) tree decl; int i; - /* Handle basetypes almost like fields, but record their - offsets differently. */ + /* 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); @@ -251,10 +255,27 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data) else if (TREE_VIA_VIRTUAL (binfo)) { tree init; + tree vbase; + + /* Remember the index to the vbase offset for this virtual + base. */ + vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list)); + if (!TREE_VALUE (list)) + BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0); + else + { + BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list)); + BINFO_VPTR_FIELD (vbase) = ssize_binop (MINUS_EXPR, + BINFO_VPTR_FIELD (vbase), + integer_one_node); + } + /* And record the offset at which this virtual base lies in the + vtable. */ init = BINFO_OFFSET (binfo); - init = build1 (NOP_EXPR, vtable_entry_type, init); - TREE_VALUE (list) = tree_cons (NULL_TREE, init, TREE_VALUE (list)); + TREE_VALUE (list) = tree_cons (BINFO_VPTR_FIELD (vbase), + init, + TREE_VALUE (list)); } SET_BINFO_VTABLE_PATH_MARKED (binfo); @@ -262,69 +283,46 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data) return NULL_TREE; } -/* Returns the initializers for the vbase offset entries in the - vtable, in reverse order. */ +/* Returns the initializers for the vbase offset entries in the vtable + for BINFO (which is part of the class hierarchy dominated by T), in + reverse order. */ static tree -build_vbase_offset_vtbl_entries (binfo) +build_vbase_offset_vtbl_entries (binfo, t) tree binfo; + tree t; { - tree type; tree inits; tree init; + tree list; /* Under the old ABI, pointers to virtual bases are stored in each object. */ - if (!flag_new_abi) + if (!vbase_offsets_in_vtable_p ()) return NULL_TREE; /* If there are no virtual baseclasses, then there is nothing to do. */ - type = BINFO_TYPE (binfo); - if (!TYPE_USES_VIRTUAL_BASECLASSES (type)) + if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) return NULL_TREE; inits = NULL_TREE; - /* Under the new ABI, the vtable contains offsets to all virtual - bases. The ABI specifies different layouts depending on whether - or not *all* of the bases of this type are virtual. */ - if (CLASSTYPE_N_BASECLASSES (type) - == list_length (CLASSTYPE_VBASECLASSES (type))) - { - /* In this case, the offsets are allocated from right to left of - the declaration order in which the virtual bases appear. */ - int i; - - for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i) - { - tree vbase = BINFO_BASETYPE (binfo, i); - init = BINFO_OFFSET (vbase); - init = build1 (NOP_EXPR, vtable_entry_type, init); - inits = tree_cons (NULL_TREE, init, inits); - } - } - else - { - tree list; - - /* While in this case, the offsets are allocated in the reverse - order of a depth-first left-to-right traversal of the - hierarchy. We use BINFO_VTABLE_PATH_MARKED because we are - ourselves during a dfs_walk, and so BINFO_MARKED is already - in use. */ - list = build_tree_list (type, NULL_TREE); - TREE_TYPE (list) = binfo; - dfs_walk (binfo, - dfs_build_vbase_offset_vtbl_entries, - dfs_vtable_path_unmarked_real_bases_queue_p, - list); - dfs_walk (binfo, - dfs_vtable_path_unmark, - dfs_vtable_path_marked_real_bases_queue_p, - list); - inits = nreverse (TREE_VALUE (list)); - } + /* The offsets are allocated in the reverse order of a + depth-first left-to-right traversal of the hierarchy. We use + BINFO_VTABLE_PATH_MARKED because we are ourselves during a + dfs_walk, and so BINFO_MARKED is already in use. */ + list = build_tree_list (t, NULL_TREE); + TREE_TYPE (list) = binfo; + dfs_walk (binfo, + dfs_build_vbase_offset_vtbl_entries, + dfs_vtable_path_unmarked_real_bases_queue_p, + list); + dfs_walk (binfo, + dfs_vtable_path_unmark, + dfs_vtable_path_marked_real_bases_queue_p, + list); + inits = nreverse (TREE_VALUE (list)); /* We've now got offsets in the right oder. However, the offsets we've stored are offsets from the beginning of the complete @@ -334,9 +332,13 @@ build_vbase_offset_vtbl_entries (binfo) tree exp = TREE_VALUE (init); exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo)); - exp = build1 (NOP_EXPR, vtable_entry_type, TREE_VALUE (init)); + exp = build1 (NOP_EXPR, vtable_entry_type, exp); exp = fold (exp); TREE_CONSTANT (exp) = 1; + /* The dfs_build_vbase_offset_vtbl_entries routine uses the + TREE_PURPOSE to scribble in. But, we need to clear it now so + that the values are not perceived as labeled initializers. */ + TREE_PURPOSE (init) = NULL_TREE; TREE_VALUE (init) = exp; } @@ -344,16 +346,41 @@ build_vbase_offset_vtbl_entries (binfo) } /* Returns a pointer to the virtual base class of EXP that has the - indicated TYPE. */ + indicated TYPE. EXP is of class type, not a pointer type. */ static tree build_vbase_pointer (exp, type) tree exp, type; { - char *name; - FORMAT_VBASE_NAME (name, type); - - return build_component_ref (exp, get_identifier (name), NULL_TREE, 0); + 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_binary_op (PLUS_EXPR, + 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. @@ -1100,6 +1127,25 @@ get_vtable_entry_n (virtuals, n) return virtuals; } +/* Call this function whenever its known that a vtable for T is going + to be needed. It's safe to call it more than once. *HAS_VIRTUAL_P + is initialized to the number of slots that are reserved at the + beginning of the vtable for RTTI information. */ + +static void +start_vtable (t, has_virtual_p) + tree t; + int *has_virtual_p; +{ + if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t)) + { + if (flag_vtable_thunks) + *has_virtual_p = 2; + else + *has_virtual_p = 1; + } +} + /* Add a virtual function to all the appropriate vtables for the class T. DECL_VINDEX(X) should be error_mark_node, if we want to allocate a new slot in our table. If it is error_mark_node, we @@ -1139,13 +1185,7 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t) /* If we are using thunks, use two slots at the front, one for the offset pointer, one for the tdesc pointer. For ARM-style vtables, use the same slot for both. */ - if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t)) - { - if (flag_vtable_thunks) - *has_virtual = 2; - else - *has_virtual = 1; - } + start_vtable (t, has_virtual); /* Build a new INT_CST for this DECL_VINDEX. */ { @@ -1767,7 +1807,7 @@ determine_primary_base (t, has_virtual_p) tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i); tree basetype = BINFO_TYPE (base_binfo); - if (TYPE_POLYMORPHIC_P (basetype)) + if (TYPE_CONTAINS_VPTR_P (basetype)) { /* Even a virtual baseclass can contain our RTTI information. But, we prefer a non-virtual polymorphic @@ -2287,9 +2327,8 @@ num_extra_vtbl_entries (binfo) tree type; int entries; - /* Under the old ABI, there are no entries at negative offsets. */ - if (!flag_new_abi) + if (!vbase_offsets_in_vtable_p ()) return size_zero_node; type = BINFO_TYPE (binfo); @@ -2317,18 +2356,20 @@ size_extra_vtbl_entries (binfo) return fold (offset); } -/* Construct the initializer for BINFOs virtual function table. */ +/* Construct the initializer for BINFOs virtual function table. BINFO + is part of the hierarchy dominated by T. */ static tree -build_vtbl_initializer (binfo) +build_vtbl_initializer (binfo, t) tree binfo; + tree t; { tree v = BINFO_VIRTUALS (binfo); tree inits = NULL_TREE; tree type = BINFO_TYPE (binfo); /* Add entries to the vtable for offsets to our virtual bases. */ - inits = build_vbase_offset_vtbl_entries (binfo); + inits = build_vbase_offset_vtbl_entries (binfo, t); /* Process the RTTI stuff at the head of the list. If we're not using vtable thunks, then the RTTI entry is just an ordinary @@ -2397,7 +2438,7 @@ build_vtbl_initializer (binfo) static tree dfs_finish_vtbls (binfo, data) tree binfo; - void *data ATTRIBUTE_UNUSED; + void *data; { if (!BINFO_PRIMARY_MARKED_P (binfo) && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)) @@ -2409,7 +2450,7 @@ dfs_finish_vtbls (binfo, data) decl = BINFO_VTABLE (binfo); context = DECL_CONTEXT (decl); DECL_CONTEXT (decl) = 0; - DECL_INITIAL (decl) = build_vtbl_initializer (binfo); + DECL_INITIAL (decl) = build_vtbl_initializer (binfo, (tree) data); cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0); DECL_CONTEXT (decl) = context; } @@ -4112,9 +4153,9 @@ check_bases_and_members (t, empty_p) /* Check all the method declarations. */ check_methods (t); - /* A nearly-empty class has to be polymorphic; a nearly empty class - contains a vptr. */ - if (!TYPE_POLYMORPHIC_P (t)) + /* A nearly-empty class has to be vptr-containing; a nearly empty + class contains just a vptr. */ + if (!TYPE_CONTAINS_VPTR_P (t)) CLASSTYPE_NEARLY_EMPTY_P (t) = 0; /* Do some bookkeeping that will guide the generation of implicitly @@ -4177,6 +4218,12 @@ create_vtable_ptr (t, empty_p, has_virtual_p, add_virtual_function (pending_virtuals_p, pending_hard_virtuals_p, has_virtual_p, fn, t); + /* 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_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()) + start_vtable (t, has_virtual_p); + /* If we couldn't find an appropriate base class, create a new field here. */ if (*has_virtual_p && !TYPE_VFIELD (t)) @@ -4771,7 +4818,7 @@ finish_struct_1 (t) TYPE_VFIELD (t) = vfield; } - if (flag_rtti && TYPE_POLYMORPHIC_P (t) && !pending_hard_virtuals) + if (flag_rtti && TYPE_CONTAINS_VPTR_P (t) && !pending_hard_virtuals) modify_all_vtables (t, NULL_TREE); for (pending_hard_virtuals = nreverse (pending_hard_virtuals); @@ -4802,9 +4849,9 @@ finish_struct_1 (t) } } - /* Under our model of GC, every C++ class gets its own virtual - function table, at least virtually. */ - if (pending_virtuals) + /* If necessary, create the vtable for this class. */ + if (pending_virtuals + || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())) { pending_virtuals = nreverse (pending_virtuals); /* We must enter these virtuals into the table. */ @@ -4836,6 +4883,8 @@ finish_struct_1 (t) CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; } + /* If we didn't need a new vtable, see if we should copy one from + the base. */ else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t)) { tree binfo = CLASSTYPE_PRIMARY_BINFO (t); @@ -4855,7 +4904,7 @@ finish_struct_1 (t) CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; } - if (TYPE_POLYMORPHIC_P (t)) + if (TYPE_CONTAINS_VPTR_P (t)) { CLASSTYPE_VSIZE (t) = has_virtual; if (CLASSTYPE_HAS_PRIMARY_BASE_P (t)) @@ -6004,7 +6053,7 @@ get_vfield_name (type) char *buf; while (BINFO_BASETYPES (binfo) - && TYPE_POLYMORPHIC_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0))) + && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0))) && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0))) binfo = BINFO_BASETYPE (binfo, 0); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2101cae0a5f..b171b1fdf57 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -177,7 +177,44 @@ Boston, MA 02111-1307, USA. */ #define RECORD_OR_UNION_TYPE_CHECK(NODE) NODE #endif + +/* ABI control. */ + +/* Nonzero to enable experimental ABI changes. */ + +extern int flag_new_abi; + +/* Nonzero to use __cxa_atexit, rather than atexit, to register + destructors for local statics and global objects. */ + +extern int flag_use_cxa_atexit; + +/* Nonzero to not ignore namespace std. */ +extern int flag_honor_std; + +/* Nonzero means generate 'rtti' that give run-time type information. */ + +extern int flag_rtti; + +/* 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() (flag_new_abi) + +/* 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() (flag_new_abi) + + /* Language-dependent contents of an identifier. */ struct lang_identifier @@ -2156,6 +2193,12 @@ struct lang_decl polymorphic class. */ #define TYPE_POLYMORPHIC_P(NODE) (TREE_LANG_FLAG_2 (NODE)) +/* 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))) + extern int flag_new_for_scope; /* This flag is true of a local VAR_DECL if it was declared in a for @@ -3160,10 +3203,6 @@ extern struct pending_inline *pending_inlines; extern int flag_this_is_variable; -/* Nonzero means generate 'rtti' that give run-time type information. */ - -extern int flag_rtti; - /* Nonzero means do emit exported implementations of functions even if they can be inlined. */ @@ -3187,19 +3226,6 @@ extern int flag_implicit_templates; extern int flag_weak; -/* Nonzero to enable experimental ABI changes. */ - -extern int flag_new_abi; - -/* Nonzero to use __cxa_atexit, rather than atexit, to register - destructors for local statics and global objects. */ - -extern int flag_use_cxa_atexit; - -/* Nonzero to not ignore namespace std. */ - -extern int flag_honor_std; - /* Nonzero if we should expand functions calls inline at the tree level, rather than at the RTL level. */ @@ -3961,6 +3987,11 @@ extern tree dfs_walk PROTO((tree, tree (*)(tree, void *), tree (*) (tree, void *), void *)); +extern tree dfs_walk_real PROTO ((tree, + tree (*) (tree, void *), + tree (*) (tree, void *), + tree (*) (tree, void *), + void *)); extern tree dfs_unmark PROTO((tree, void *)); extern tree dfs_vbase_unmark PROTO((tree, void *)); extern tree dfs_vtable_path_unmark PROTO((tree, void *)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d8a57e56f2b..0a5dc568f48 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8201,15 +8201,7 @@ expand_static_init (decl, init) finish_if_stmt (); } else - { - /* This code takes into account memory allocation policy of - `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING does not - hold for this object, then we must make permanent the storage - currently in the temporary obstack. */ - if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) - preserve_initializer (); - static_aggregates = tree_cons (init, decl, static_aggregates); - } + static_aggregates = tree_cons (init, decl, static_aggregates); } /* Finish the declaration of a catch-parameter. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 40b656ff73d..10d071e4ec3 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2296,8 +2296,9 @@ mark_vtable_entries (decl) fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries))); - if (TREE_CODE (fnaddr) == NOP_EXPR) - /* RTTI offset. */ + if (TREE_CODE (fnaddr) != ADDR_EXPR) + /* This entry is an offset: a virtual base class offset, a + virtual call offset, and RTTI offset, etc. */ continue; fn = TREE_OPERAND (fnaddr, 0); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3828ddf499b..b5a1ac43bf8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -119,8 +119,12 @@ initialize_vtbl_ptrs (type, addr) { tree list = build_tree_list (type, addr); - dfs_walk (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, - dfs_unmarked_real_bases_queue_p, list); + /* 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. */ + 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 (TYPE_USES_VIRTUAL_BASECLASSES (type)) @@ -657,7 +661,7 @@ expand_virtual_init (binfo, decl) vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl); /* Under the new ABI, we need to point into the middle of the vtable. */ - if (flag_new_abi) + if (vbase_offsets_in_vtable_p ()) vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, size_extra_vtbl_entries (binfo)); @@ -720,7 +724,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) /* Construct the virtual base-classes of THIS_REF (whose address is THIS_PTR). The object has the indicated TYPE. The construction actually takes place only if FLAG is non-zero. INIT_LIST is list - of initialization for constructor to perform. */ + of initializations for constructors to perform. */ static void construct_virtual_bases (type, this_ref, this_ptr, init_list, flag) @@ -731,21 +735,25 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag) tree flag; { tree vbases; - tree result; - tree if_stmt; /* 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_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 (); + 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; @@ -1019,11 +1027,6 @@ finish_init_stmts (stmt_expr, compound_stmt) If `init' is a CONSTRUCTOR, then we emit a warning message, explaining that such initializations are invalid. - ALIAS_THIS is nonzero iff we are initializing something which is - essentially an alias for current_class_ref. In this case, the base - constructor may move it on us, and we must keep track of such - deviations. - If INIT resolves to a CALL_EXPR which happens to return something of the type we are looking for, then we know that we can safely use that call to perform the @@ -1217,8 +1220,6 @@ expand_default_init (binfo, true_exp, exp, init, flags) from TRUE_EXP. In constructors, we don't know anything about the value being initialized. - ALIAS_THIS serves the same purpose it serves for expand_aggr_init. - FLAGS is just passes to `build_method_call'. See that function for its description. */ diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 74113aba2c6..cddefe7dae2 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -1,5 +1,5 @@ /* RunTime Type Identification - Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1995, 96-97, 1998, 1999, 2000 Free Software Foundation, Inc. Mostly written by Jason Merrill (jason@cygnus.com). This file is part of GNU CC. @@ -811,7 +811,8 @@ expand_class_desc (tdecl, type) (type_info_type_node, TYPE_QUAL_CONST))); fields [1] = build_lang_decl - (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node); + (FIELD_DECL, NULL_TREE, + flag_new_abi ? intSI_type_node : unsigned_intSI_type_node); DECL_BIT_FIELD (fields[1]) = 1; DECL_FIELD_SIZE (fields[1]) = 29; @@ -839,15 +840,26 @@ expand_class_desc (tdecl, type) if (TREE_VIA_VIRTUAL (binfo)) { - tree t = BINFO_TYPE (binfo); - const char *name; - tree field; - - FORMAT_VBASE_NAME (name, t); - field = lookup_field (type, get_identifier (name), 0, 0); - offset = size_binop (FLOOR_DIV_EXPR, - DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT)); - offset = convert (sizetype, offset); + if (!vbase_offsets_in_vtable_p ()) + { + tree t = BINFO_TYPE (binfo); + const char *name; + tree field; + + FORMAT_VBASE_NAME (name, t); + field = lookup_field (type, get_identifier (name), 0, 0); + offset = size_binop (FLOOR_DIV_EXPR, + DECL_FIELD_BITPOS (field), + size_int (BITS_PER_UNIT)); + offset = convert (sizetype, offset); + } + else + { + /* Under the new ABI, we store the vtable offset at which + the virtual base offset can be found. */ + tree vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type); + offset = convert (sizetype, BINFO_VPTR_FIELD (vbase)); + } } else offset = BINFO_OFFSET (binfo); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 697bf8b214e..d29cdb57705 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -126,11 +126,6 @@ static tree bfs_walk void *)); static tree lookup_field_queue_p PROTO((tree, void *)); static tree lookup_field_r PROTO((tree, void *)); -static tree dfs_walk_real PROTO ((tree, - tree (*) (tree, void *), - tree (*) (tree, void *), - tree (*) (tree, void *), - void *)); static tree get_virtuals_named_this_r PROTO ((tree, void *)); static tree context_for_name_lookup PROTO ((tree)); static tree canonical_binfo PROTO ((tree)); @@ -1773,7 +1768,7 @@ bfs_walk (binfo, fn, qfn, data) performed, and PREFN is called in preorder, while POSTFN is called in postorder. */ -static tree +tree dfs_walk_real (binfo, prefn, postfn, qfn, data) tree binfo; tree (*prefn) PROTO((tree, void *)); @@ -3200,9 +3195,9 @@ maybe_suppress_debug_info (t) TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; else if (CLASSTYPE_INTERFACE_KNOWN (t)) /* Don't set it. */; - /* If the class has virtual functions, write out the debug info - along with the vtable. */ - else if (TYPE_POLYMORPHIC_P (t)) + /* If the class has a vtable, write out the debug info along with + the vtable. */ + else if (TYPE_CONTAINS_VPTR_P (t)) TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1; /* Otherwise, just emit the debug info normally. */ diff --git a/gcc/cp/tinfo.cc b/gcc/cp/tinfo.cc index 1d4885c9264..18a00b0b19a 100644 --- a/gcc/cp/tinfo.cc +++ b/gcc/cp/tinfo.cc @@ -1,5 +1,5 @@ // Methods for type_info for -*- C++ -*- Run Time Type Identification. -// Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation +// Copyright (C) 1994, 1996, 1998, 1999, 2000 Free Software Foundation // This file is part of GNU CC. @@ -31,6 +31,34 @@ #include "tinfo.h" #include "new" // for placement new +namespace +{ +// ADDR is a pointer to an object. Convert it to a pointer to a base, +// using OFFSET. +inline void* +convert_to_base (void *addr, bool is_virtual, USItype offset) +{ + if (!addr) + return NULL; + + if (!is_virtual) + return (char *) addr + offset; + +#ifdef __GXX_ABI_VERSION + // Under the new ABI, the offset gives us an index into the vtable, + // which contains an offset to the virtual base. The vptr is always + // the first thing in the object. + std::ptrdiff_t *vtable = *((std::ptrdiff_t **) addr); + return ((char *) addr) + vtable[offset]; +#else + // Under the old ABI, the offset gives us the address of a pointer + // to the virtual base. + return *((void **) ((char *) addr + offset)); +#endif +} + +} + // This file contains the minimal working set necessary to link with code // that uses virtual functions and -frtti but does not actually use RTTI // functionality. @@ -254,14 +282,11 @@ do_upcast (sub_kind access_path, upcast_result result2; void *p = objptr; sub_kind sub_access = access_path; - if (p) - p = (char *)p + base_list[i].offset; + p = convert_to_base (p, + base_list[i].is_virtual, + base_list[i].offset); if (base_list[i].is_virtual) - { - if (p) - p = *(void **)p; - sub_access = sub_kind (sub_access | contained_virtual_mask); - } + sub_access = sub_kind (sub_access | contained_virtual_mask); if (base_list[i].access != PUBLIC) sub_access = sub_kind (sub_access & ~contained_public_mask); if (base_list[i].base->do_upcast (sub_access, target, p, result2)) @@ -344,13 +369,13 @@ do_dyncast (int boff, sub_kind access_path, for (size_t i = n_bases; i--;) { dyncast_result result2; - void *p = (char *)objptr + base_list[i].offset; + void *p; sub_kind sub_access = access_path; + p = convert_to_base (objptr, + base_list[i].is_virtual, + base_list[i].offset); if (base_list[i].is_virtual) - { - p = *(void **)p; - sub_access = sub_kind (sub_access | contained_virtual_mask); - } + sub_access = sub_kind (sub_access | contained_virtual_mask); if (base_list[i].access != PUBLIC) sub_access = sub_kind (sub_access & ~contained_public_mask); @@ -492,13 +517,15 @@ do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *s { if (base_list[i].access != PUBLIC) continue; // Not public, can't be here. - void *p = (char *)objptr + base_list[i].offset; - if (base_list[i].is_virtual) - { - if (boff == -1) - continue; // Not a virtual base, so can't be here. - p = *(void **)p; - } + void *p; + + if (base_list[i].is_virtual && boff == -1) + // Not a virtual base, so can't be here. + continue; + + p = convert_to_base (objptr, + base_list[i].is_virtual, + base_list[i].offset); sub_kind base_kind = base_list[i].base->do_find_public_subobj (boff, subtype, p, subptr); diff --git a/gcc/cp/tinfo.h b/gcc/cp/tinfo.h index 39be84edde5..116c7a8dd0f 100644 --- a/gcc/cp/tinfo.h +++ b/gcc/cp/tinfo.h @@ -1,5 +1,5 @@ // RTTI support internals for -*- C++ -*- -// Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation +// Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000 Free Software Foundation #include "typeinfo" @@ -167,7 +167,11 @@ public: // type_info for a general class. +#ifdef __GXX_ABI_VERSION +typedef int USItype __attribute__ ((mode (SI))); +#else typedef unsigned int USItype __attribute__ ((mode (SI))); +#endif struct __class_type_info : public __user_type_info { enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 }; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index a951b5f7197..3c342d5f877 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -860,7 +860,6 @@ make_binfo (offset, binfo, vtable, virtuals) BINFO_OFFSET (new_binfo) = offset; BINFO_VTABLE (new_binfo) = vtable; BINFO_VIRTUALS (new_binfo) = virtuals; - BINFO_VPTR_FIELD (new_binfo) = NULL_TREE; if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE) BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo)); -- cgit v1.2.3