diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1996-04-12 23:55:07 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1996-04-12 23:55:07 +0000 |
commit | 6b5fbb552b0b8abb9a36ee1a9277b4ca03819b96 (patch) | |
tree | 84ac919a75a7ef9a3abc47f1231f2e6ee3f56ef1 | |
parent | 5ae5999cfe054bd1840277903b2aed4e905c2236 (diff) | |
download | gcc-6b5fbb552b0b8abb9a36ee1a9277b4ca03819b96.zip gcc-6b5fbb552b0b8abb9a36ee1a9277b4ca03819b96.tar.gz gcc-6b5fbb552b0b8abb9a36ee1a9277b4ca03819b96.tar.bz2 |
86th Cygnus<->FSF quick merge
From-SVN: r11710
-rw-r--r-- | gcc/cp/ChangeLog | 187 | ||||
-rw-r--r-- | gcc/cp/call.c | 6 | ||||
-rw-r--r-- | gcc/cp/class.c | 294 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 20 | ||||
-rw-r--r-- | gcc/cp/decl.c | 56 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 79 | ||||
-rw-r--r-- | gcc/cp/init.c | 12 | ||||
-rw-r--r-- | gcc/cp/lex.c | 2 | ||||
-rw-r--r-- | gcc/cp/method.c | 53 | ||||
-rw-r--r-- | gcc/cp/pt.c | 4 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 971 | ||||
-rw-r--r-- | gcc/cp/search.c | 67 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 26 |
13 files changed, 1054 insertions, 723 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 80d94b4..8cfe37d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,190 @@ +Fri Apr 12 09:08:27 1996 Bob Manson <manson@charmed.cygnus.com> + + * search.c (expand_upcast_fixups): Mark the new fixup as + DECL_ARTIFICIAL. + +Thu Apr 11 03:57:09 1996 Jason Merrill <jason@yorick.cygnus.com> + + * init.c (build_new): Use a TARGET_EXPR for alloc_expr. + + * class.c (set_rtti_entry): Fix for thunks. + + * decl2.c (import_export_decl): Still emit typeinfo fns for + cv-variants of builtin types. + + * rtti.c (expand_class_desc): Set up base_info_type_node here. + (init_rtti_processing): Instead of here. + +Wed Apr 10 14:17:13 1996 Jason Merrill <jason@yorick.cygnus.com> + + * rtti.c (init_rtti_processing): Do init regardless of -frtti. + (build_typeid): Only complain about taking dynamic typeid without + -frtti. + + * decl2.c: flag_rtti defaults to 1. + + * rtti.c (get_tinfo_var): The general class case is now smaller. + (init_rtti_processing): Pack the latter three fields of base_info + into 32 bits. + +Wed Apr 10 13:50:14 1996 Mike Stump <mrs@cygnus.com> + + * init.c (expand_member_init): Don't dump if name is NULL_TREE. + +Wed Apr 10 12:56:02 1996 Mike Stump <mrs@cygnus.com> + + * search.c (make_memoized_table_entry): Undefer the pop, if necessary. + (push_memoized_context): Split out code to undefer pop_type_level to + (clear_memoized_cache): here. + (pop_memoized_context): We can only handle one layer of deferral of + pop_type_level so clear the cache, if there was a previous level. + +Tue Apr 9 23:06:09 1996 Jason Merrill <jason@yorick.cygnus.com> + + * rtti.c (init_rtti_processing): Build up base_info_type_node. + (expand_class_desc): Use one pointer to an array of base_info + structs, passed using a CONSTRUCTOR. + +Tue Apr 9 14:20:57 1996 Mike Stump <mrs@cygnus.com> + + * class.c (build_vbase_path): Remove block extern for + flag_assume_nonnull_objects here. + (build_vfn_ref): Split out functionality into build_vtbl_ref. + (build_vtbl_ref): New routine. + (build_vtable): Set up rtti info here. + (add_virtual_function): Note in CLASSTYPE_RTTI the best + place where we can get the rtti pointers from to avoid having to + search around for a place. + (finish_base_struct): Ditto. + (finish_struct_1): Ditto. Never create totally new vtables with totally + new vtable pointers for rtti. Disable code to layout vtable pointers + better until we want to break binary compatibility. + * rtti.c (build_headof_sub): New routine to convert down to a + sub-object that has an rtti pointer in the vtable. + (build_headof): Use it. Also, use build_vtbl_ref now to be more + maintainable. + (build_dynamic_cast): Make sure we have saved it, if we need to. + * search.c (dfs_init_vbase_pointers): Disable code that deals with + a more efficient vtable layout, enable later. + * call.c (flag_assume_nonnull_objects): Moved declaration to + * cp-tree.h: here. Declare build_vtbl_ref. + * pt.c (instantiate_class_template): Use NULL_TREE instead of 0 in + function calls that want a tree. + +Tue Apr 9 12:10:26 1996 Jason Merrill <jason@yorick.cygnus.com> + + * rtti.c (build_dynamic_cast): Handle downcasting to X* given + other X subobjects in the most derived type. Ack. + + * rtti.c (build_dynamic_cast): No need to strip cv-quals here, + get_typeid will do it for us. + (get_typeid_1): Break out call-building for expand_*_desc to use. + (get_typeid): Call it. + (expand_*_desc): Ditto. + * decl.c (init_decl_processing): Don't set TYPE_BUILT_IN on char * + and void *. + (init_decl_processing): Lose builtin_type_tdescs lossage. + * decl2.c (finish_vtable_vardecl): Remove obsolete code. + +Mon Apr 8 17:23:23 1996 Bob Manson <manson@charmed.cygnus.com> + + * pt.c (tsubst): When calling set_nested_typename, use + TYPE_NESTED_NAME (current_class_type) instead of + current_class_name. + + * decl.c (pushdecl): Ditto. + (pushdecl_class_level): Ditto. + (grokdeclarator): Use NULL_TREE instead of 0 in the call to + set_nested_typename. + +Sun Apr 7 10:44:31 1996 Jason Merrill <jason@yorick.cygnus.com> + + * rtti.c (synthesize_tinfo_fn): Handle arrays. + + * cp-tree.h (DECL_REALLY_EXTERN): New macro. + +Sat Apr 6 13:56:27 1996 Jason Merrill <jason@yorick.cygnus.com> + + * rtti.c (throw_bad_cast): Use entry point __throw_bad_cast. + (init_rtti_processing): Lose bad_cast_type. + (build_dynamic_cast): Use throw_bad_cast. + + * rtti.c (synthesize_tinfo_fn): Handle enums and pmfs. + + * decl2.c (finish_file): Don't synthesize artificial functions + that are external and not inline. + + * rtti.c (get_tinfo_fn): If at_eof, call import_export_decl. + + * decl2.c (finish_file): Handle having new inlines added to + saved_inlines by synthesis. + + * rtti.c (get_bad_cast_node): Don't require <typeinfo>. + +Fri Apr 5 17:02:09 1996 Jason Merrill <jason@yorick.cygnus.com> + + RTTI rewrite to initialize nodes as needed, not require that + users #include <typeinfo>, complete functionality and reduce wasted + space. + * rtti.c (init_rtti_processing): New fn. + (build_typeid): The vtable entry is now a function. + (get_tinfo_var): New fn. + (get_tinfo_fn): Ditto. + (get_typeid): Use it. + (build_dynamic_cast): Declare and use entry point __dynamic_cast. + (build_*_desc): Rename to expand_*_desc and rewrite to use entry + points __rtti_*. + (add_uninstantiated_desc, get_def_to_follow, build_t_desc): Lose. + (synthesize_tinfo_fn): New fn. + * method.c (build_t_desc_overload): Lose. + (build_overload_with_type): More generic. + * decl.c (init_decl_processing): Call init_rtti_processing. + * class.c (set_rtti_entry): Use get_tinfo_fn. + * decl2.c (mark_vtable_entries): Mark the rtti function. + (finish_prevtable_vardecl): Don't build_t_desc. + (import_export_decl): Handle tinfo functions. + (finish_file): Ditto. + * typeck.c (inline_conversion): New fn. + (build_function_call_real): Use it. + * cp-tree.h: Add decls. + + * method.c (hack_identifier): Also convert component_refs from + references. + + * lex.c (cons_up_default_function): Use the type, not the name, in + declspecs. + + * decl2.c (import_export_vtable): Fix weak vtables. + +Fri Apr 5 13:30:17 1996 Bob Manson <manson@charmed.cygnus.com> + + * search.c (get_base_distance_recursive): Fix access checks for + protected bases. + +Fri Apr 5 11:02:06 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * call.c (unary_complex_lvalue): Delete unneeded decl, it's in + cp-tree.h. + (convert_harshness): Add prototypes wrapped by PROTO. + * decl2.c (grok_function_init): Likewise. + (do_toplevel_using_decl): Change to void return type. + * class.c (build_vtable_entry): Remove decl of make_thunk. + (merge_overrides): Fix order of arg definitions. + (finish_vtbls): Likewise. + (fixup_vtable_deltas): Likewise. + (modify_all_direct_vtables): Likewise. + (modify_all_indirect_vtables): Likewise. + * search.c (get_base_distance_recursive): Likewise. + (get_abstract_virtuals_1): Likewise. + (fixup_virtual_upcast_offsets): Likewise. + (lookup_fnfields_1): Add prototypes wrapped by PROTO. + * init.c (perform_member_init): Fix order of arg definitions. + (expand_aggr_init_1): Add prototypes wrapped by PROTO. + * cp-tree.h (make_thunk): Add decl. + (overload_template_name, push_template_decl): Add decls. + (do_toplevel_using_decl): Change to void return type. + (vec_binfo_member): Add decl. + Thu Apr 4 13:33:10 1996 Brendan Kehoe <brendan@lisa.cygnus.com> * typeck.c (mark_addressable, convert_for_assignment, diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 55994c6..7afd319 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -38,15 +38,11 @@ Boston, MA 02111-1307, USA. */ extern void sorry (); extern int inhibit_warnings; -extern int flag_assume_nonnull_objects; extern tree ctor_label, dtor_label; -/* From typeck.c: */ -extern tree unary_complex_lvalue (); - /* Compute the ease with which a conversion can be performed between an expected and the given type. */ -static struct harshness_code convert_harshness (); +static struct harshness_code convert_harshness PROTO((register tree, register tree, tree)); #define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG)) #define STD_RETURN(ARG) ((ARG).code = STD_CODE, (ARG)) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 76377e1..bbf259c 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -240,7 +240,6 @@ build_vbase_path (code, type, expr, path, alias_this) if (changed) { - extern int flag_assume_nonnull_objects; tree ind; /* We already check for ambiguous things in the caller, just @@ -377,7 +376,6 @@ build_vtable_entry (delta, pfn) if (flag_vtable_thunks) { HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta); - extern tree make_thunk (); if (idelta) { pfn = build1 (ADDR_EXPR, vtable_entry_type, @@ -425,13 +423,12 @@ build_vtable_entry (delta, pfn) } /* 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 vtable element 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. */ tree -build_vfn_ref (ptr_to_instptr, instance, idx) - tree *ptr_to_instptr, instance; - tree idx; +build_vtbl_ref (instance, idx) + tree instance, idx; { tree vtbl, aref; tree basetype = TREE_TYPE (instance); @@ -487,23 +484,40 @@ build_vfn_ref (ptr_to_instptr, instance, idx) assemble_external (vtbl); aref = build_array_ref (vtbl, idx); - /* 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)); + return aref; +} + +/* 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. */ +tree +build_vfn_ref (ptr_to_instptr, instance, idx) + tree *ptr_to_instptr, 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) return aref; - else + + if (ptr_to_instptr) { - if (ptr_to_instptr) - *ptr_to_instptr - = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), - *ptr_to_instptr, - convert (ptrdiff_type_node, - build_component_ref (aref, delta_identifier, 0, 0))); - return build_component_ref (aref, pfn_identifier, 0, 0); + /* 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, + convert (ptrdiff_type_node, + build_component_ref (aref, delta_identifier, NULL_TREE, 0))); } + + return build_component_ref (aref, pfn_identifier, NULL_TREE, 0); } /* Return the name of the virtual function table (as an IDENTIFIER_NODE) @@ -530,6 +544,70 @@ get_vtable_name (type) return get_identifier (buf); } +/* Return the offset to the main vtable for a given base BINFO. */ +tree +get_vfield_offset (binfo) + tree binfo; +{ + return size_binop (PLUS_EXPR, + size_binop (FLOOR_DIV_EXPR, + DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), + size_int (BITS_PER_UNIT)), + BINFO_OFFSET (binfo)); +} + +/* Get the offset to the start of the original binfo that we derived + this binfo from. If we find TYPE first, return the offset only + that far. The shortened search is useful because the this pointer + on method calling is expected to point to a DECL_CONTEXT (fndecl) + object, and not a baseclass of it. */ +static tree +get_derived_offset (binfo, type) + tree binfo, type; +{ + tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + tree offset2; + int i; + while (BINFO_BASETYPES (binfo) + && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + { + tree binfos = BINFO_BASETYPES (binfo); + if (BINFO_TYPE (binfo) == type) + break; + binfo = TREE_VEC_ELT (binfos, i); + } + offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); + return size_binop (MINUS_EXPR, offset1, offset2); +} + +/* Update the rtti info for this class. */ +static void +set_rtti_entry (virtuals, offset, type) + tree virtuals, offset, type; +{ + tree vfn; + + if (flag_rtti) + vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type)); + else + vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, integer_zero_node); + TREE_CONSTANT (vfn) = 1; + + if (! flag_vtable_thunks) + TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn); + else + { + tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); + TREE_CONSTANT (voff) = 1; + + TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff); + + /* The second slot is for the tdesc pointer when thunks are used. */ + TREE_VALUE (TREE_CHAIN (virtuals)) + = build_vtable_entry (integer_zero_node, vfn); + } +} + /* Build a virtual function for type TYPE. If BINFO is non-NULL, build the vtable starting with the initial approximation that it is the same as the one which is the head of @@ -543,8 +621,15 @@ build_vtable (binfo, type) if (binfo) { + tree offset; + virtuals = copy_list (BINFO_VIRTUALS (binfo)); decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo))); + + /* Now do rtti stuff. */ + offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE); + offset = size_binop (MINUS_EXPR, integer_zero_node, offset); + set_rtti_entry (virtuals, offset, type); } else { @@ -649,36 +734,6 @@ build_type_pathname (format, parent, type) return id; } -/* Update the rtti info for this class. */ -static void -set_rtti_entry (virtuals, offset, type) - tree virtuals, offset, type; -{ - if (! flag_vtable_thunks) - TREE_VALUE (virtuals) - = build_vtable_entry (offset, - (flag_rtti - ? build_t_desc (type, 0) - : integer_zero_node)); - else - { - tree vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); - TREE_CONSTANT (vfn) = 1; - - TREE_VALUE (virtuals) - = build_vtable_entry (integer_zero_node, vfn); - /* The second slot is for the tdesc pointer when thunks are used. */ - vfn = flag_rtti - ? build_t_desc (type, 0) - : integer_zero_node; - vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, vfn); - TREE_CONSTANT (vfn) = 1; - - TREE_VALUE (TREE_CHAIN (virtuals)) - = build_vtable_entry (integer_zero_node, vfn); - } -} - /* Give TYPE 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 @@ -716,8 +771,18 @@ prepare_fresh_vtable (binfo, for_type) BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo)); if (TREE_VIA_VIRTUAL (binfo)) - offset = BINFO_OFFSET (binfo_member (BINFO_TYPE (binfo), - CLASSTYPE_VBASECLASSES (for_type))); + { + tree binfo1 = binfo_member (BINFO_TYPE (binfo), + CLASSTYPE_VBASECLASSES (for_type)); + + /* XXX - This should never happen, if it does, the caller should + ensure that the binfo is from for_type's binfos, not from any + base type's. We can remove all this code after a while. */ + if (binfo1 != binfo) + warning ("internal inconsistency: binfo offset error for rtti"); + + offset = BINFO_OFFSET (binfo1); + } else offset = BINFO_OFFSET (binfo); @@ -844,11 +909,8 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t) { tree entry; - if (flag_rtti && *has_virtual == 0) - { - /* CLASSTYPE_RTTI is only used as a Boolean (NULL or not). */ - CLASSTYPE_RTTI (t) = integer_one_node; - } + /* We remember that this was the base sub-object for rtti. */ + CLASSTYPE_RTTI (t) = t; /* If we are using thunks, use two slots at the front, one for the offset pointer, one for the tdesc pointer. */ @@ -1177,42 +1239,6 @@ alter_access (t, fdecl, access) return 0; } -/* Return the offset to the main vtable for a given base BINFO. */ -tree -get_vfield_offset (binfo) - tree binfo; -{ - return size_binop (PLUS_EXPR, - size_binop (FLOOR_DIV_EXPR, - DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), - size_int (BITS_PER_UNIT)), - BINFO_OFFSET (binfo)); -} - -/* Get the offset to the start of the original binfo that we derived - this binfo from. If we find TYPE first, return the offset only - that far. The shortened search is useful because the this pointer - on method calling is expected to point to a DECL_CONTEXT (fndecl) - object, and not a baseclass of it. */ -static tree -get_derived_offset (binfo, type) - tree binfo, type; -{ - tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); - tree offset2; - int i; - while (BINFO_BASETYPES (binfo) - && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) - { - tree binfos = BINFO_BASETYPES (binfo); - if (BINFO_TYPE (binfo) == type) - break; - binfo = TREE_VEC_ELT (binfos, i); - } - offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); - return size_binop (MINUS_EXPR, offset1, offset2); -} - /* If FOR_TYPE needs to reinitialize virtual function table pointers for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST. Returns BASE_INIT_LIST appropriately modified. */ @@ -1379,6 +1405,7 @@ struct base_info int n_ancestors; tree vfield; tree vfields; + tree rtti; char cant_have_default_ctor; char cant_have_const_ctor; char cant_synth_copy_ctor; @@ -1478,14 +1505,6 @@ finish_base_struct (t, b, t_binfo) TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype); if (! TREE_VIA_VIRTUAL (base_binfo) -#if 0 - /* This cannot be done, as prepare_fresh_vtable wants to modify - binfos associated with vfields anywhere in the hierarchy, not - just immediate base classes. Due to unsharing, the compiler - might consume 3% more memory on a real program. - */ - && ! BINFO_OFFSET_ZEROP (base_binfo) -#endif && BINFO_BASETYPES (base_binfo)) { tree base_binfos = BINFO_BASETYPES (base_binfo); @@ -1523,6 +1542,11 @@ finish_base_struct (t, b, t_binfo) /* Remember that the baseclass has virtual members. */ b->base_has_virtual = 1; + /* Ensure that this is set from at least a virtual base + class. */ + if (b->rtti == NULL_TREE) + b->rtti = CLASSTYPE_RTTI (basetype); + /* Don't borrow virtuals from virtual baseclasses. */ if (TREE_VIA_VIRTUAL (base_binfo)) continue; @@ -1658,6 +1682,11 @@ finish_base_struct (t, b, t_binfo) if (b->vfield == 0) /* If all virtual functions come only from virtual baseclasses. */ return -1; + + /* Update the rtti base if we have a non-virtual base class version + of it. */ + b->rtti = CLASSTYPE_RTTI (BINFO_TYPE (TREE_VEC_ELT (binfos, first_vfn_base_index))); + return first_vfn_base_index; } @@ -2084,8 +2113,9 @@ duplicate_tag_error (t) /* finish up all new vtables. */ static void finish_vtbls (binfo, do_self, t) - tree binfo, t; + tree binfo; int do_self; + tree t; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2346,8 +2376,9 @@ modify_one_vtable (binfo, t, fndecl, pfn) /* These are the ones that are not through virtual base classes. */ static void modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn) - tree binfo, t, fndecl, pfn; + tree binfo; int do_self; + tree t, fndecl, pfn; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2445,8 +2476,9 @@ fixup_vtable_deltas1 (binfo, t) hierarchy, because the layout of the virtual bases has changed. */ static void fixup_vtable_deltas (binfo, init_self, t) - tree binfo, t; + tree binfo; int init_self; + tree t; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2469,8 +2501,9 @@ fixup_vtable_deltas (binfo, init_self, t) /* These are the ones that are through virtual base classes. */ static void modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn) - tree binfo, t, fndecl, pfn; + tree binfo; int do_self, via_virtual; + tree t, fndecl, pfn; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2643,8 +2676,9 @@ override_one_vtable (binfo, old, t) overrides. */ static void merge_overrides (binfo, old, do_self, t) - tree binfo, old, t; + tree binfo, old; int do_self; + tree t; { tree binfos = BINFO_BASETYPES (binfo); tree old_binfos = BINFO_BASETYPES (old); @@ -3070,13 +3104,14 @@ finish_struct_1 (t, attributes, warn_anon) fields = chainon (vf, fields); first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo); - /* Remember where we got our vfield from */ + /* Remember where we got our vfield from. */ CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index; has_virtual = base_info.has_virtual; max_has_virtual = base_info.max_has_virtual; CLASSTYPE_N_SUPERCLASSES (t) += base_info.n_ancestors; vfield = base_info.vfield; vfields = base_info.vfields; + CLASSTYPE_RTTI (t) = base_info.rtti; cant_have_default_ctor = base_info.cant_have_default_ctor; cant_have_const_ctor = base_info.cant_have_const_ctor; cant_synth_copy_ctor = base_info.cant_synth_copy_ctor; @@ -3093,6 +3128,7 @@ finish_struct_1 (t, attributes, warn_anon) max_has_virtual = has_virtual; vfield = NULL_TREE; vfields = NULL_TREE; + CLASSTYPE_RTTI (t) = NULL_TREE; last_x = NULL_TREE; cant_have_default_ctor = 0; cant_have_const_ctor = 0; @@ -3560,9 +3596,6 @@ finish_struct_1 (t, attributes, warn_anon) } TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); - if (flag_rtti && (max_has_virtual > 0 || base_has_virtual) && - has_virtual == 0) - has_virtual = 1; TYPE_HAS_COMPLEX_INIT_REF (t) |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) @@ -3728,13 +3761,15 @@ finish_struct_1 (t, attributes, warn_anon) DECL_SAVED_INSNS (vfield) = NULL_RTX; DECL_FIELD_SIZE (vfield) = 0; DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node); - if (CLASSTYPE_RTTI (t)) - { - /* vfield is always first entry in structure. */ - TREE_CHAIN (vfield) = fields; - fields = vfield; - } - else if (last_x) +#if 0 + /* This is more efficient, but breaks binary compatibility, turn + it on sometime when we don't care. If we turn it on, we also + have to enable the code in dfs_init_vbase_pointers. */ + /* vfield is always first entry in structure. */ + TREE_CHAIN (vfield) = fields; + fields = vfield; +#else + if (last_x) { my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175); TREE_CHAIN (last_x) = vfield; @@ -3742,6 +3777,7 @@ finish_struct_1 (t, attributes, warn_anon) } else fields = vfield; +#endif vfields = chainon (vfields, CLASSTYPE_AS_LIST (t)); } @@ -3843,17 +3879,6 @@ finish_struct_1 (t, attributes, warn_anon) vbases = CLASSTYPE_VBASECLASSES (t); CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases); - /* The rtti code should do this. (mrs) */ -#if 0 - while (vbases) - { - /* Update rtti info with offsets for virtual baseclasses. */ - if (flag_rtti && ! BINFO_NEW_VTABLE_MARKED (vbases)) - prepare_fresh_vtable (vbases, t); - vbases = TREE_CHAIN (vbases); - } -#endif - { /* Now fixup overrides of all functions in vtables from all direct or indirect virtual base classes. */ @@ -3941,34 +3966,29 @@ finish_struct_1 (t, attributes, warn_anon) /* Under our model of GC, every C++ class gets its own virtual function table, at least virtually. */ - if (pending_virtuals || (flag_rtti && TYPE_VIRTUAL_P (t))) + if (pending_virtuals) { pending_virtuals = nreverse (pending_virtuals); /* We must enter these virtuals into the table. */ if (first_vfn_base_index < 0) { - /* The first slot is for the rtti offset. */ - pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); - /* The second slot is for the tdesc pointer when thunks are used. */ if (flag_vtable_thunks) pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); + /* The first slot is for the rtti offset. */ + pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); + set_rtti_entry (pending_virtuals, integer_zero_node, t); build_vtable (NULL_TREE, t); } else { - tree offset; /* Here we know enough to change the type of our virtual function table, but we will wait until later this function. */ if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t))) build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t); - - offset = get_derived_offset (TYPE_BINFO (t), NULL_TREE); - offset = size_binop (MINUS_EXPR, integer_zero_node, offset); - set_rtti_entry (TYPE_BINFO_VIRTUALS (t), offset, t); } /* If this type has basetypes with constructors, then those diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4f3212c..c8c9fd1 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1403,6 +1403,9 @@ extern int flag_new_for_scope; #define DECL_NOT_REALLY_EXTERN(NODE) \ (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern) +#define DECL_REALLY_EXTERN(NODE) \ + (DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE)) + #define DECL_PUBLIC(NODE) \ (TREE_CODE (NODE) == FUNCTION_DECL \ ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE)) @@ -1947,6 +1950,7 @@ extern char *dont_allow_type_definitions; extern tree build_vbase_pointer PROTO((tree, tree)); extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int)); extern tree build_vtable_entry PROTO((tree, tree)); +extern tree build_vtbl_ref PROTO((tree, tree)); extern tree build_vfn_ref PROTO((tree *, tree, tree)); extern void add_method PROTO((tree, tree *, tree)); extern tree get_vfield_offset PROTO((tree)); @@ -2074,6 +2078,8 @@ extern void pop_cp_function_context PROTO((tree)); extern void grok_op_properties PROTO((tree, int, int)); /* in decl2.c */ +extern int flag_assume_nonnull_objects; + extern int lang_decode_option PROTO((char *)); extern tree grok_method_quals PROTO((tree, tree, tree)); extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree)); @@ -2112,7 +2118,7 @@ extern tree reparse_decl_as_expr PROTO((tree, tree)); extern tree finish_decl_parsing PROTO((tree)); extern tree lookup_name_nonclass PROTO((tree)); extern tree check_cp_case_value PROTO((tree)); -extern tree do_toplevel_using_decl PROTO((tree)); +extern void do_toplevel_using_decl PROTO((tree)); extern tree do_class_using_decl PROTO((tree)); extern tree current_namespace_id PROTO((tree)); extern tree get_namespace_id PROTO((void)); @@ -2152,10 +2158,7 @@ extern void init_repo PROTO((char*)); extern void finish_repo PROTO((void)); /* in rtti.c */ -extern tree build_classof PROTO((tree)); -extern tree build_t_desc PROTO((tree, int)); -extern tree build_i_desc PROTO((tree)); -extern tree build_m_desc PROTO((tree)); +extern tree get_tinfo_fn PROTO((tree)); extern tree build_typeid PROTO((tree)); extern tree get_typeid PROTO((tree)); extern tree build_dynamic_cast PROTO((tree, tree)); @@ -2269,7 +2272,7 @@ extern tree build_static_name PROTO((tree, tree)); extern tree cplus_exception_name PROTO((tree)); extern tree build_decl_overload PROTO((tree, tree, int)); extern tree build_typename_overload PROTO((tree)); -extern tree build_t_desc_overload PROTO((tree)); +extern tree build_overload_with_type PROTO((tree, tree)); extern void declare_overloaded PROTO((tree)); #ifdef NO_AUTO_OVERLOAD extern int is_overloaded PROTO((tree)); @@ -2277,6 +2280,7 @@ extern int is_overloaded PROTO((tree)); extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree)); extern tree hack_identifier PROTO((tree, tree)); extern tree build_component_type_expr PROTO((tree, tree, tree, int)); +extern tree make_thunk PROTO((tree, int)); extern void synthesize_method PROTO((tree)); /* in pt.c */ @@ -2288,10 +2292,12 @@ extern void begin_template_parm_list PROTO((void)); extern tree process_template_parm PROTO((tree, tree)); extern tree end_template_parm_list PROTO((tree)); extern void end_template_decl PROTO((void)); +extern void push_template_decl PROTO((tree)); extern tree lookup_template_class PROTO((tree, tree, tree)); extern int uses_template_parms PROTO((tree)); extern tree instantiate_class_template PROTO((tree)); extern tree instantiate_template PROTO((tree, tree *)); +extern void overload_template_name PROTO((tree)); extern int type_unification PROTO((tree, tree *, tree, tree, int *, int)); struct tinst_level *tinst_for_decl PROTO((void)); extern void mark_decl_instantiated PROTO((tree, int)); @@ -2402,6 +2408,7 @@ extern tree build_unsave_expr PROTO((tree)); extern tree unsave_expr PROTO((tree)); extern int cp_expand_decl_cleanup PROTO((tree, tree)); extern tree get_type_decl PROTO((tree)); +extern tree vec_binfo_member PROTO((tree, tree)); extern tree hack_decl_function_context PROTO((tree)); /* in typeck.c */ @@ -2428,6 +2435,7 @@ extern tree expr_sizeof PROTO((tree)); extern tree c_sizeof PROTO((tree)); extern tree c_sizeof_nowarn PROTO((tree)); extern tree c_alignof PROTO((tree)); +extern tree inline_conversion PROTO((tree)); extern tree decay_conversion PROTO((tree)); extern tree default_conversion PROTO((tree)); extern tree build_object_ref PROTO((tree, tree, tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c5274b4..d32431b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3164,7 +3164,7 @@ pushdecl (x) Any artificial decls that need DECL_NESTED_TYPENAME will have it set in pushtag. */ if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) - set_nested_typename (x, current_class_name, DECL_NAME (x), type); + set_nested_typename (x, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, DECL_NAME (x), type); if (type != error_mark_node && TYPE_NAME (type) @@ -3491,7 +3491,7 @@ pushdecl_class_level (x) Any artificial decls that need DECL_NESTED_TYPENAME will have it set in pushtag. */ if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x)) - set_nested_typename (x, current_class_name, name, TREE_TYPE (x)); + set_nested_typename (x, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, name, TREE_TYPE (x)); } } return x; @@ -4655,32 +4655,6 @@ record_builtin_type (rid_index, name, type) set_identifier_type_value (rname, NULL_TREE); } } - - if (flag_rtti) - { - if (builtin_type_tdescs_len+5 >= builtin_type_tdescs_max) - { - builtin_type_tdescs_max *= 2; - builtin_type_tdescs_arr - = (tree *)xrealloc (builtin_type_tdescs_arr, - builtin_type_tdescs_max * sizeof (tree)); - } - builtin_type_tdescs_arr[builtin_type_tdescs_len++] = type; - if (TREE_CODE (type) != POINTER_TYPE) - { - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_pointer_type (type); - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_pointer_type (build_type_variant (type, 1, 0)); - } - if (TREE_CODE (type) != VOID_TYPE) - { - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_reference_type (type); - builtin_type_tdescs_arr[builtin_type_tdescs_len++] - = build_reference_type (build_type_variant (type, 1, 0)); - } - } } /* Push overloaded decl, in global scope, with one argument so it @@ -4695,7 +4669,8 @@ push_overloaded_decl_1 (x) #ifdef __GNUC__ __inline #endif -tree auto_function (name, type, code) +tree +auto_function (name, type, code) tree name, type; enum built_in_function code; { @@ -4772,11 +4747,6 @@ init_decl_processing () #endif gcc_obstack_init (&decl_obstack); - if (flag_rtti) - { - builtin_type_tdescs_max = 100; - builtin_type_tdescs_arr = (tree *)xmalloc (100 * sizeof (tree)); - } /* Must lay these out before anything else gets laid out. */ error_mark_node = make_node (ERROR_MARK); @@ -4944,7 +4914,9 @@ init_decl_processing () string_type_node = build_pointer_type (char_type_node); const_string_type_node = build_pointer_type (build_type_variant (char_type_node, 1, 0)); +#if 0 record_builtin_type (RID_MAX, NULL_PTR, string_type_node); +#endif /* Make a type to be the domain of a few array types whose domains don't really matter. @@ -4972,7 +4944,9 @@ init_decl_processing () ptr_type_node = build_pointer_type (void_type_node); const_ptr_type_node = build_pointer_type (build_type_variant (void_type_node, 1, 0)); +#if 0 record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node); +#endif endlink = void_list_node; int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink); double_endlink = tree_cons (NULL_TREE, double_type_node, endlink); @@ -5471,17 +5445,6 @@ init_decl_processing () finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, integer_type_node); } - - if (flag_rtti) - { - int i = builtin_type_tdescs_len; - while (i > 0) - { - tree tdesc = build_t_desc (builtin_type_tdescs_arr[--i], 0); - TREE_ASM_WRITTEN (tdesc) = 1; - TREE_PUBLIC (TREE_OPERAND (tdesc, 0)) = 1; - } - } #endif /*flag_rtti*/ /* Now, C++. */ @@ -5517,6 +5480,7 @@ init_decl_processing () init_class_processing (); init_init_processing (); init_search_processing (); + init_rtti_processing (); if (flag_handle_exceptions) init_exception_processing (); @@ -9029,7 +8993,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli tree d = TYPE_NAME (type), c = DECL_CONTEXT (d); if (!c) - set_nested_typename (d, 0, declarator, type); + set_nested_typename (d, NULL_TREE, declarator, type); else if (TREE_CODE (c) == FUNCTION_DECL) set_nested_typename (d, DECL_ASSEMBLER_NAME (c), declarator, type); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 8077b5b..039b427 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA. */ extern tree get_file_function_name (); extern tree cleanups_this_call; -static void grok_function_init (); +static void grok_function_init PROTO((tree, tree)); void import_export_decl (); extern int current_class_depth; @@ -318,7 +318,7 @@ int flag_int_enum_equivalence; /* Controls whether compiler generates 'type descriptor' that give run-time type information. */ -int flag_rtti; +int flag_rtti = 1; /* Nonzero if we wish to output cross-referencing information for the GNU class browser. */ @@ -2430,6 +2430,14 @@ mark_vtable_entries (decl) { tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl)); + if (flag_rtti) + { + tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (TREE_CHAIN (entries)) + : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries))); + tree fn = TREE_OPERAND (fnaddr, 0); + TREE_ADDRESSABLE (fn) = 1; + mark_used (fn); + } skip_rtti_stuff (&entries); for (; entries; entries = TREE_CHAIN (entries)) @@ -2500,7 +2508,10 @@ import_export_vtable (decl, type, final) cp_error ("all virtual functions redeclared inline"); #endif if (flag_weak) - DECL_WEAK (decl) = 1; + { + TREE_PUBLIC (decl) = 1; + DECL_WEAK (decl) = 1; + } else TREE_PUBLIC (decl) = 0; DECL_EXTERNAL (decl) = 0; @@ -2557,21 +2568,6 @@ finish_prevtable_vardecl (prev, vars) } import_export_vtable (vars, ctype, 1); - - /* We cannot use TREE_USED here, as it may be set by the expanding of a - ctor that is used to build a global object. The long term plan is to - make the TD entries statically initialized and move this to - finish_vtable_vardecl time. */ - if (flag_rtti && write_virtuals >= 0 - && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || 1 || TREE_USED (vars))) - { - /* Kick out the type descriptor before we dump out global - initializers, as they are initialized at run time and - we have to find them when we scan for things that need initialized - at the top level. */ - build_t_desc (ctype, 1); - } - return 1; } @@ -2583,15 +2579,6 @@ finish_vtable_vardecl (prev, vars) && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)) && ! TREE_ASM_WRITTEN (vars)) { -#if 0 - /* The long term plan it to make the TD entries statically initialized, - have the entries built and emitted here. When that happens, this - can be enabled, and the other call to build_t_desc removed. */ - /* Kick out the type descriptor before writing out the vtable. */ - if (flag_rtti) - build_t_desc (DECL_CONTEXT (vars), 1); -#endif - /* Write it out. */ mark_vtable_entries (vars); if (TREE_TYPE (DECL_INITIAL (vars)) == 0) @@ -2763,6 +2750,23 @@ import_export_decl (decl) else TREE_PUBLIC (decl) = 0; } + /* tinfo function */ + else if (DECL_ARTIFICIAL (decl) && DECL_MUTABLE_P (decl)) + { + tree ctype = TREE_TYPE (DECL_NAME (decl)); + if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype)) + { + DECL_NOT_REALLY_EXTERN (decl) + = ! (CLASSTYPE_INTERFACE_ONLY (ctype) + || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines)); + } + else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype)) + DECL_NOT_REALLY_EXTERN (decl) = 0; + else if (flag_weak) + DECL_WEAK (decl) = 1; + else + TREE_PUBLIC (decl) = 0; + } else if (DECL_C_STATIC (decl)) TREE_PUBLIC (decl) = 0; else if (flag_weak) @@ -3095,10 +3099,6 @@ finish_file () { tree decl = TREE_VALUE (fnname); import_export_decl (decl); - if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) - && TREE_PUBLIC (decl) && ! DECL_WEAK (decl) - && DECL_NOT_REALLY_EXTERN (decl)) - synthesize_method (decl); } /* Now write out inline functions which had their addresses taken and @@ -3126,14 +3126,21 @@ finish_file () tree decl = TREE_VALUE (*p); if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) - && TREE_USED (decl)) + && TREE_USED (decl) + && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl))) { - synthesize_method (decl); + if (DECL_MUTABLE_P (decl)) + synthesize_tinfo_fn (decl); + else + synthesize_method (decl); reconsider = 1; } - if (TREE_ASM_WRITTEN (decl) - || (DECL_SAVED_INSNS (decl) == 0 && ! DECL_ARTIFICIAL (decl))) + if (decl != TREE_VALUE (*p)) + ; + else if (TREE_ASM_WRITTEN (decl) + || (DECL_SAVED_INSNS (decl) == 0 + && ! DECL_ARTIFICIAL (decl))) *p = TREE_CHAIN (*p); else p = &TREE_CHAIN (*p); @@ -3619,7 +3626,7 @@ do_namespace_alias (alias, namespace) sorry ("namespace alias"); } -tree +void do_toplevel_using_decl (decl) tree decl; { diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b8d0dad..e5e186e 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -51,7 +51,7 @@ static void expand_aggr_vbase_init (); void expand_member_init (); void expand_aggr_init (); -static void expand_aggr_init_1 (); +static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int, int)); static void expand_virtual_init PROTO((tree, tree)); tree expand_vec_init (); @@ -152,8 +152,9 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) /* Subroutine of emit_base_init. */ static void perform_member_init (member, name, init, explicit, protect_list) - tree member, name, init, *protect_list; + tree member, name, init; int explicit; + tree *protect_list; { tree decl; tree type = TREE_TYPE (member); @@ -941,7 +942,7 @@ expand_member_init (exp, name, init) type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); - if (TREE_CODE (name) == TYPE_DECL) + if (name && TREE_CODE (name) == TYPE_DECL) { basetype = TREE_TYPE (name); name = DECL_NAME (name); @@ -2827,8 +2828,9 @@ build_new (placement, decl, init, use_global_new) not expanded as part of the RTL_EXPR for the initialization, so we can't just use save_expr here. */ - alloc_temp = get_temp_name (TREE_TYPE (rval), 0); - alloc_expr = build (MODIFY_EXPR, TREE_TYPE (rval), alloc_temp, rval); + alloc_temp = build (VAR_DECL, TREE_TYPE (rval)); + layout_decl (alloc_temp, 0); + alloc_expr = build (TARGET_EXPR, TREE_TYPE (rval), alloc_temp, rval, 0); TREE_SIDE_EFFECTS (alloc_expr) = 1; rval = alloc_temp; } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index a1b841b..bbc8b04 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1650,7 +1650,7 @@ cons_up_default_function (type, full_name, kind) /* Fall through... */ case 6: retref = 1; - declspecs = build_decl_list (NULL_TREE, full_name); + declspecs = build_decl_list (NULL_TREE, type); name = ansi_opname [(int) MODIFY_EXPR]; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index a417e1c..8d1bba7 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1073,49 +1073,14 @@ build_typename_overload (type) return id; } -#ifndef NO_DOLLAR_IN_LABEL -#define T_DESC_FORMAT "TD$" -#define I_DESC_FORMAT "ID$" -#define M_DESC_FORMAT "MD$" -#else -#if !defined(NO_DOT_IN_LABEL) -#define T_DESC_FORMAT "TD." -#define I_DESC_FORMAT "ID." -#define M_DESC_FORMAT "MD." -#else -#define T_DESC_FORMAT "__t_desc_" -#define I_DESC_FORMAT "__i_desc_" -#define M_DESC_FORMAT "__m_desc_" -#endif -#endif - -/* Build an overload name for the type expression TYPE. */ tree -build_t_desc_overload (type) - tree type; +build_overload_with_type (name, type) + tree name, type; { OB_INIT (); - OB_PUTS (T_DESC_FORMAT); + OB_PUTID (name); nofold = 1; -#if 0 - /* Use a different format if the type isn't defined yet. */ - if (TYPE_SIZE (type) == NULL_TREE) - { - char *p; - int changed; - - for (p = tname; *p; p++) - if (isupper (*p)) - { - changed = 1; - *p = tolower (*p); - } - /* If there's no change, we have an inappropriate T_DESC_FORMAT. */ - my_friendly_assert (changed != 0, 249); - } -#endif - build_overload_name (type, 0, 1); return get_identifier (obstack_base (&scratch_obstack)); } @@ -1580,10 +1545,9 @@ hack_identifier (value, name) this field was initialized by a base initializer, we can emit an error message. */ TREE_USED (value) = 1; - return build_component_ref (C_C_D, name, 0, 1); + value = build_component_ref (C_C_D, name, 0, 1); } - - if (really_overloaded_fn (value)) + else if (really_overloaded_fn (value)) { #if 0 tree t = get_first_fn (value); @@ -1668,12 +1632,7 @@ hack_identifier (value, name) } if (TREE_CODE (type) == REFERENCE_TYPE && ! current_template_parms) - { - my_friendly_assert (TREE_CODE (value) == VAR_DECL - || TREE_CODE (value) == PARM_DECL - || TREE_CODE (value) == RESULT_DECL, 252); - return convert_from_reference (value); - } + value = convert_from_reference (value); return value; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c4b58a4..c1e422b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1185,7 +1185,7 @@ instantiate_class_template (type) require_complete_type (tmp); /* XXX handle attributes */ - type = finish_struct_1 (type, 0, 0); + type = finish_struct_1 (type, NULL_TREE, 0); } else { @@ -1578,7 +1578,7 @@ tsubst (t, args, nargs, in_decl) tree r = copy_node (t); TREE_TYPE (r) = type; DECL_CONTEXT (r) = current_class_type; - set_nested_typename (r, current_class_name, DECL_NAME (r), type); + set_nested_typename (r, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, DECL_NAME (r), type); TREE_CHAIN (r) = NULL_TREE; return r; } diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index bd6a0ac..75eff1d 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -1,5 +1,6 @@ /* RunTime Type Identification Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Mostly written by Jason Merrill (jason@cygnus.com). This file is part of GNU CC. @@ -32,16 +33,50 @@ extern tree define_function (); extern tree build_t_desc_overload (); extern struct obstack *permanent_obstack; +tree type_info_type_node; +tree tinfo_fn_id; +tree tinfo_fn_type; + /* in c-common.c */ extern tree combine_strings PROTO((tree)); -/* Given the expression EXP of type `class *', return the head - of the object pointed to by EXP. */ +void +init_rtti_processing () +{ + type_info_type_node = xref_tag + (class_type_node, get_identifier ("type_info"), NULL_TREE, 1); + tinfo_fn_id = get_identifier ("__tf"); + tinfo_fn_type = build_function_type + (build_reference_type (build_type_variant (type_info_type_node, 1, 0)), + void_list_node); +} + +/* 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_VIRTUAL_P), else just return the + expression. */ static tree build_headof (exp) tree exp; { tree type = TREE_TYPE (exp); + tree aref; tree vptr, offset; if (TREE_CODE (type) != POINTER_TYPE) @@ -51,22 +86,22 @@ build_headof (exp) } type = TREE_TYPE (type); - if (!TYPE_VIRTUAL_P (type) || CLASSTYPE_VFIELD (type) == NULL_TREE) + if (!TYPE_VIRTUAL_P (type)) return exp; - vptr = fold (size_binop (PLUS_EXPR, - size_binop (FLOOR_DIV_EXPR, - DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (type)), - size_int (BITS_PER_UNIT)), - exp)); - vptr = build1 (INDIRECT_REF, build_pointer_type (vtable_entry_type), vptr); + /* 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); + + aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node); if (flag_vtable_thunks) - offset = build_array_ref (vptr, integer_zero_node); + offset = aref; else - offset = build_component_ref (build_array_ref (vptr, integer_zero_node), - delta_identifier, - NULL_TREE, 0); + offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0); type = build_type_variant (ptr_type_node, TREE_READONLY (exp), TREE_THIS_VOLATILE (exp)); @@ -83,9 +118,6 @@ build_typeid (exp) { tree type; - if (!flag_rtti) - cp_error ("cannot take typeid of object when -frtti is not specified"); - if (exp == error_mark_node) return error_mark_node; @@ -116,62 +148,181 @@ build_typeid (exp) /* build reference to type_info from vtable. */ tree t; + if (! flag_rtti) + warning ("taking dynamic typeid of object without -frtti"); + + /* If we don't have rtti stuff, get to a sub-object that does. */ + if (!CLASSTYPE_VFIELDS (TREE_TYPE (type))) + { + exp = build_unary_op (ADDR_EXPR, exp, 0); + exp = build_headof_sub (exp); + exp = build_indirect_ref (exp, NULL_PTR); + } + if (flag_vtable_thunks) - t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_one_node); + t = build_vfn_ref ((tree *) 0, exp, integer_one_node); else - t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_zero_node); + t = build_vfn_ref ((tree *) 0, exp, integer_zero_node); + TREE_TYPE (t) = build_pointer_type (tinfo_fn_type); - TREE_TYPE (t) = build_pointer_type (__class_desc_type_node); - t = build_indirect_ref (t, NULL); - return t; + t = build (CALL_EXPR, TREE_TYPE (tinfo_fn_type), t, NULL_TREE, 0); + TREE_SIDE_EFFECTS (t) = 1; + return convert_from_reference (t); } /* otherwise return the type_info for the static type of the expr. */ return get_typeid (type); } +tree +get_tinfo_var (type) + tree type; +{ + tree tname = build_overload_with_type (get_identifier ("__ti"), type); + tree tdecl, arrtype; + int size; + + if (IDENTIFIER_GLOBAL_VALUE (tname)) + return IDENTIFIER_GLOBAL_VALUE (tname); + + /* Figure out how much space we need to allocate for the type_info object. + If our struct layout or the type_info classes are changed, this will + need to be modified. */ + if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) + size = 4 * POINTER_SIZE; + else if (TREE_CODE (type) == POINTER_TYPE + && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE + || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)) + size = 3 * POINTER_SIZE; + else if (IS_AGGR_TYPE (type)) + { + if (CLASSTYPE_N_BASECLASSES (type) == 0) + size = 2 * POINTER_SIZE; + else if (! TYPE_USES_COMPLEX_INHERITANCE (type) + && (TREE_VIA_PUBLIC + (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)))) + size = 3 * POINTER_SIZE; + else + size = 4 * POINTER_SIZE; + } + else + size = 2 * POINTER_SIZE; + + push_obstacks (&permanent_obstack, &permanent_obstack); + + /* The type for a character array of the appropriate size. */ + arrtype = build_cplus_array_type + (unsigned_char_type_node, + build_index_type (size_int (size / BITS_PER_UNIT - 1))); + + tdecl = build_decl (VAR_DECL, tname, arrtype); + TREE_PUBLIC (tdecl) = 1; + DECL_EXTERNAL (tdecl) = 1; + DECL_ARTIFICIAL (tdecl) = 1; + pushdecl_top_level (tdecl); + cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); + + pop_obstacks (); + + return tdecl; +} + +tree +get_tinfo_fn (type) + tree type; +{ + tree name = build_overload_with_type (tinfo_fn_id, type); + tree d; + + if (IDENTIFIER_GLOBAL_VALUE (name)) + return IDENTIFIER_GLOBAL_VALUE (name); + + push_obstacks (&permanent_obstack, &permanent_obstack); + + d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type); + DECL_EXTERNAL (d) = 1; + TREE_PUBLIC (d) = 1; + DECL_ARTIFICIAL (d) = 1; + DECL_NOT_REALLY_EXTERN (d) = 1; + DECL_MUTABLE_P (d) = 1; + TREE_TYPE (name) = type; + pushdecl_top_level (d); + make_function_rtl (d); + mark_inline_for_output (d); + if (at_eof) + import_export_decl (d); + + pop_obstacks (); + + return d; +} + +tree +get_typeid_1 (type) + tree type; +{ + tree t = build (CALL_EXPR, TREE_TYPE (tinfo_fn_type), + default_conversion (get_tinfo_fn (type)), NULL_TREE, 0); + TREE_SIDE_EFFECTS (t) = 1; + return convert_from_reference (t); +} + /* Return the type_info object for TYPE, creating it if necessary. */ tree get_typeid (type) tree type; { - tree t, td; + tree t; if (type == error_mark_node) return error_mark_node; - /* Is it useful (and/or correct) to have different typeids for `T &' - and `T'? */ + /* If the type of the type-id is a reference type, the result of the + typeid expression refers to a type_info object representing the + referenced type. */ if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); - td = build_t_desc (type, 1); - if (td == error_mark_node) - return error_mark_node; + /* The top-level cv-qualifiers of the lvalue expression or the type-id + that is the operand of typeid are always ignored. */ + type = TYPE_MAIN_VARIANT (type); - t = TREE_OPERAND (td, 0); - return t; + return get_typeid_1 (type); } /* Get a bad_cast node for the program to throw... - See libstdc++::exception{,.cc} for __bad_cast_object */ + See libstdc++/exception.cc for __throw_bad_cast */ + static tree -get_bad_cast_node () +throw_bad_cast () { - static tree t; - if (t == NULL_TREE - && (t = lookup_name (get_identifier ("__bad_cast_object"), 0)) - == NULL_TREE) - { - error ("you must #include <typeinfo>"); - return error_mark_node; - } - return t; + tree d = get_identifier ("__throw_bad_cast"); + tree type; + + if (IDENTIFIER_GLOBAL_VALUE (d)) + return IDENTIFIER_GLOBAL_VALUE (d); + + push_obstacks (&permanent_obstack, &permanent_obstack); + + type = build_function_type (void_type_node, void_list_node); + d = build_lang_decl (FUNCTION_DECL, d, type); + DECL_EXTERNAL (d) = 1; + TREE_PUBLIC (d) = 1; + DECL_ARTIFICIAL (d) = 1; + pushdecl_top_level (d); + make_function_rtl (d); + + pop_obstacks (); + + d = build (CALL_EXPR, void_type_node, default_conversion (d), NULL_TREE, 0); + TREE_SIDE_EFFECTS (d) = 1; + return d; } /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working paper. */ + tree build_dynamic_cast (type, expr) tree type, expr; @@ -179,6 +330,7 @@ build_dynamic_cast (type, expr) enum tree_code tc = TREE_CODE (type); tree exprtype = TREE_TYPE (expr); enum tree_code ec = TREE_CODE (exprtype); + tree dcast_fn; if (type == error_mark_node || expr == error_mark_node) return error_mark_node; @@ -264,12 +416,15 @@ build_dynamic_cast (type, expr) && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) return build1 (NOP_EXPR, type, expr); - return build_headof (expr); + expr = build_headof (expr); + if (TREE_TYPE (expr) != type) + expr = build1 (NOP_EXPR, type, expr); + return expr; } else { tree retval; - tree result, td1, td2, elems, expr1; + tree result, td1, td2, td3, elems, expr1, expr2; /* If we got here, we can't convert statically. Therefore, dynamic_cast<D&>(b) (b an object) cannot succeed. */ @@ -280,7 +435,7 @@ build_dynamic_cast (type, expr) { cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", expr, type); - return build_throw (get_bad_cast_node ()); + return throw_bad_cast (); } } /* Ditto for dynamic_cast<D*>(&b). */ @@ -298,29 +453,66 @@ build_dynamic_cast (type, expr) } } + /* Since expr is used twice below, save it. */ + expr = save_expr (expr); + expr1 = expr; if (tc == REFERENCE_TYPE) expr1 = build_unary_op (ADDR_EXPR, expr1, 0); /* Build run-time conversion. */ - expr1 = build_headof (expr1); + expr2 = build_headof (expr1); if (ec == POINTER_TYPE) td1 = build_typeid (build_indirect_ref (expr, NULL_PTR)); else td1 = build_typeid (expr); - td2 = get_typeid (TYPE_MAIN_VARIANT (TREE_TYPE (type))); - - elems = tree_cons (NULL_TREE, td2, - tree_cons (NULL_TREE, build_int_2 (1, 0), - tree_cons (NULL_TREE, expr1, NULL_TREE))); - result = build_method_call (td1, - get_identifier ("__rtti_match"), elems, NULL_TREE, LOOKUP_NORMAL); + td2 = get_typeid (TREE_TYPE (type)); + td3 = get_typeid (TREE_TYPE (exprtype)); + + elems = tree_cons + (NULL_TREE, TREE_OPERAND (td1, 0), tree_cons + (NULL_TREE, TREE_OPERAND (td2, 0), tree_cons + (NULL_TREE, build_int_2 (1, 0), tree_cons + (NULL_TREE, expr2, tree_cons + (NULL_TREE, TREE_OPERAND (td3, 0), tree_cons + (NULL_TREE, expr1, NULL_TREE)))))); + + dcast_fn = get_identifier ("__dynamic_cast"); + if (IDENTIFIER_GLOBAL_VALUE (dcast_fn)) + dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn); + else + { + tree tmp; + + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = build_reference_type + (build_type_variant (type_info_type_node, 1, 0)); + tmp = tree_cons + (NULL_TREE, tmp, tree_cons + (NULL_TREE, tmp, tree_cons + (NULL_TREE, integer_type_node, tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, tmp, tree_cons + (NULL_TREE, ptr_type_node, void_list_node)))))); + tmp = build_function_type (ptr_type_node, tmp); + dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp); + DECL_EXTERNAL (dcast_fn) = 1; + TREE_PUBLIC (dcast_fn) = 1; + DECL_ARTIFICIAL (dcast_fn) = 1; + pushdecl_top_level (dcast_fn); + make_function_rtl (dcast_fn); + pop_obstacks (); + } + + result = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (dcast_fn)), + decay_conversion (dcast_fn), elems, 0); + TREE_SIDE_EFFECTS (result) = 1; if (tc == REFERENCE_TYPE) { - expr1 = build_throw (get_bad_cast_node ()); + expr1 = throw_bad_cast (); expr1 = build_compound_expr (tree_cons (NULL_TREE, expr1, build_tree_list (NULL_TREE, convert (type, integer_zero_node)))); TREE_TYPE (expr1) = type; @@ -354,129 +546,67 @@ build_dynamic_cast (type, expr) Note: these constructors always return the address of the descriptor info, since that is simplest for their mutual interaction. */ -static tree -build_generic_desc (tdecl, type, elems) - tree tdecl; - tree type; - tree elems; -{ - tree init = elems; - int toplev = global_bindings_p (); +extern tree const_string_type_node; - TREE_CONSTANT (init) = 1; - TREE_STATIC (init) = 1; - TREE_READONLY (init) = 1; +/* Build an initializer for a __si_type_info node. */ - TREE_TYPE (tdecl) = type; - DECL_INITIAL (tdecl) = init; - TREE_STATIC (tdecl) = 1; - DECL_SIZE (tdecl) = NULL_TREE; - layout_decl (tdecl, 0); - if (! toplev) - push_to_top_level (); - cp_finish_decl (tdecl, init, NULL_TREE, 0, 0); - if (! toplev) - pop_from_top_level (); - - if (! TREE_USED (tdecl)) - { - assemble_external (tdecl); - TREE_USED (tdecl) = 1; - } - - return IDENTIFIER_AS_DESC (DECL_NAME (tdecl)); -} - -/* Build an initializer for a __bltn_desc node. */ -static tree -build_bltn_desc (tdecl, type) +static void +expand_si_desc (tdecl, type) tree tdecl; tree type; { - tree elems, t; - - if (type == boolean_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_BOOL"), - 0, 0); - else if (type == char_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_CHAR"), - 0, 0); - else if (type == short_integer_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SHORT"), - 0, 0); - else if (type == integer_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_INT"), - 0, 0); - else if (type == long_integer_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_LONG"), - 0, 0); - else if (type == long_long_integer_type_node) - t = lookup_field (__bltn_desc_type_node, - get_identifier("_RTTI_BI_LONGLONG"), 0, 0); - else if (type == float_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_FLOAT"), - 0, 0); - else if (type == double_type_node) - t = lookup_field (__bltn_desc_type_node, - get_identifier("_RTTI_BI_DOUBLE"), 0, 0); - else if (type == long_double_type_node) - t = lookup_field (__bltn_desc_type_node, - get_identifier("_RTTI_BI_LDOUBLE"), 0, 0); - else if (type == unsigned_char_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UCHAR"), - 0, 0); - else if (type == short_unsigned_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_USHORT"), - 0, 0); - else if (type == unsigned_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UINT"), - 0, 0); - else if (type == long_unsigned_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_ULONG"), - 0, 0); - else if (type == long_long_unsigned_type_node) - t = lookup_field (__bltn_desc_type_node, - get_identifier("_RTTI_BI_ULONGLONG"), 0, 0); - else if (type == signed_char_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SCHAR"), - 0, 0); - else if (type == wchar_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_WCHAR"), - 0, 0); - else if (type == void_type_node) - t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_VOID"), - 0, 0); + tree t, elems, fn; + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name), name)); + + type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)); + expand_expr_stmt (get_typeid_1 (type)); + t = decay_conversion (get_tinfo_var (type)); + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, t, NULL_TREE))); + + fn = get_identifier ("__rtti_si"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); else { - cp_compiler_error ("type `%T' not handled as a built-in type"); + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, build_pointer_type (type_info_type_node), + void_list_node))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + pop_obstacks (); } - elems = tree_cons (NULL_TREE, t, NULL_TREE); - return build_generic_desc (tdecl, __bltn_desc_type_node, elems); -} - -/* Build an initializer for a __user_desc node. */ -static tree -build_user_desc (tdecl) - tree tdecl; -{ - tree elems, name_string; - tree tname = DECL_NAME (tdecl); - - name_string = combine_strings (build_string - (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); - elems = name_string; - return build_generic_desc (tdecl, __user_desc_type_node, elems); + fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + decay_conversion (fn), elems, 0); + TREE_SIDE_EFFECTS (fn) = 1; + expand_expr_stmt (fn); } /* Build an initializer for a __class_type_info node. */ -static tree -build_class_desc (tdecl, type) + +static void +expand_class_desc (tdecl, type) tree tdecl; tree type; { - tree tname = DECL_NAME (tdecl); + tree tname = TYPE_NESTED_NAME (type); tree name_string; + tree fn, tmp; + char *name; int i = CLASSTYPE_N_BASECLASSES (type); int base_cnt = 0; @@ -487,30 +617,50 @@ build_class_desc (tdecl, type) int n_base = i; #endif tree base, elems, access, offset, isvir; - tree base_list, off_list, acc_list, isvir_list; - static tree acc_pub = NULL_TREE; - static tree acc_pro = NULL_TREE; - static tree acc_pri = NULL_TREE; + tree elt, elts = NULL_TREE; + static tree base_info_type_node; - if (acc_pub == NULL_TREE) + if (base_info_type_node == NULL_TREE) { - acc_pub = lookup_field (__class_desc_type_node, - get_identifier("_RTTI_ACCESS_PUBLIC"), 0, 0); - acc_pro = lookup_field (__class_desc_type_node, - get_identifier("_RTTI_ACCESS_PROTECTED"), 0, 0); - acc_pri = lookup_field (__class_desc_type_node, - get_identifier("_RTTI_ACCESS_PRIVATE"), 0, 0); + tree fields [4]; + + /* A reasonably close approximation of __class_type_info::base_info */ + + push_obstacks (&permanent_obstack, &permanent_obstack); + base_info_type_node = make_lang_type (RECORD_TYPE); + + /* Actually const __user_type_info * */ + fields [0] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, + build_pointer_type (build_type_variant (type_info_type_node, 1, 0))); + fields [1] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, sizetype); + DECL_BIT_FIELD (fields[1]) = 1; + DECL_FIELD_SIZE (fields[1]) = 29; + + fields [2] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, boolean_type_node); + DECL_BIT_FIELD (fields[2]) = 1; + DECL_FIELD_SIZE (fields[2]) = 1; + + /* Actually enum access */ + fields [3] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, integer_type_node); + DECL_BIT_FIELD (fields[3]) = 1; + DECL_FIELD_SIZE (fields[3]) = 2; + + finish_builtin_type (base_info_type_node, "__base_info", fields, + 3, ptr_type_node); + pop_obstacks (); } - base_list = build_tree_list (NULL_TREE, integer_zero_node); - off_list = build_tree_list (NULL_TREE, integer_zero_node); - acc_list = build_tree_list (NULL_TREE, integer_zero_node); - isvir_list = build_tree_list (NULL_TREE, integer_zero_node); while (--i >= 0) { tree binfo = TREE_VEC_ELT (binfos, i); - base = build_t_desc (BINFO_TYPE (binfo), 1); + expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo))); + base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo))); + if (TREE_VIA_VIRTUAL (binfo)) { tree t = BINFO_TYPE (binfo); @@ -527,20 +677,24 @@ build_class_desc (tdecl, type) offset = BINFO_OFFSET (binfo); if (TREE_VIA_PUBLIC (binfo)) - access = acc_pub; + access = access_public_node; else if (TREE_VIA_PROTECTED (binfo)) - access = acc_pro; + access = access_protected_node; else - access = acc_pri; + access = access_private_node; if (TREE_VIA_VIRTUAL (binfo)) - isvir = build_int_2 (1, 0); + isvir = boolean_true_node; else - isvir = build_int_2 (0, 0); - - base_list = tree_cons (NULL_TREE, base, base_list); - isvir_list = tree_cons (NULL_TREE, isvir, isvir_list); - acc_list = tree_cons (NULL_TREE, access, acc_list); - off_list = tree_cons (NULL_TREE, offset, off_list); + isvir = boolean_false_node; + + elt = build + (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons + (NULL_TREE, base, tree_cons + (NULL_TREE, offset, tree_cons + (NULL_TREE, isvir, tree_cons + (NULL_TREE, access, NULL_TREE))))); + TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1; + elts = tree_cons (NULL_TREE, elt, elts); base_cnt++; } #if 0 @@ -548,18 +702,18 @@ build_class_desc (tdecl, type) while (vb) { tree b; - access = acc_pub; + access = access_public_node; while (--i >= 0) { b = TREE_VEC_ELT (binfos, i); if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b)) { if (TREE_VIA_PUBLIC (b)) - access = acc_pub; + access = access_public_node; else if (TREE_VIA_PROTECTED (b)) - access = acc_pro; + access = access_protected_node; else - access = acc_pri; + access = access_private_node; break; } } @@ -576,278 +730,271 @@ build_class_desc (tdecl, type) vb = TREE_CHAIN (vb); } #endif - base_list = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), - base_list, 0); - off_list = finish_table (NULL_TREE, integer_type_node, - off_list, 0); - isvir_list = finish_table (NULL_TREE, integer_type_node, - isvir_list, 0); - acc_list = finish_table (NULL_TREE, __access_mode_type_node, - acc_list, 0); - - name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); + name = build_overload_name (type, 1, 1); + name_string = combine_strings (build_string (strlen (name), name)); - elems = tree_cons (NULL_TREE, name_string, - tree_cons (NULL_TREE, default_conversion (base_list), - tree_cons (NULL_TREE, default_conversion (off_list), - tree_cons (NULL_TREE, default_conversion (isvir_list), - tree_cons (NULL_TREE, default_conversion (acc_list), - tree_cons (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE)))))); + { + tree arrtype = build_array_type (base_info_type_node, NULL_TREE); + elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts); + TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts) = + TREE_STATIC (elts) = 1; + complete_array_type (arrtype, elts, 1); + } - return build_generic_desc (tdecl, __class_desc_type_node, elems); -} + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, decay_conversion (elts), tree_cons + (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE)))); -/* Build an initializer for a __pointer_type_info node. */ -static tree -build_ptr_desc (tdecl, type) - tree tdecl; - tree type; -{ - tree t, elems; + fn = get_identifier ("__rtti_class"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons + (NULL_TREE, sizetype, void_list_node)))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + pop_obstacks (); + } - t = TREE_TYPE (type); - t = build_t_desc (t, 1); - t = build_indirect_ref (t, NULL); - elems = tree_cons (NULL_TREE, t, NULL_TREE); - return build_generic_desc (tdecl, __ptr_desc_type_node, elems); + fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + decay_conversion (fn), elems, 0); + TREE_SIDE_EFFECTS (fn) = 1; + expand_expr_stmt (fn); } -/* Build an initializer for a __attr_type_info node. */ -static tree -build_attr_desc (tdecl, type) +/* Build an initializer for a __pointer_type_info node. */ +static void +expand_ptr_desc (tdecl, type) tree tdecl; tree type; { - tree elems, t, attrval; + tree t, elems, fn; + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name), name)); - if (TYPE_READONLY (type)) - { - if (TYPE_VOLATILE (type)) - attrval = lookup_field (__attr_desc_type_node, - get_identifier("_RTTI_ATTR_CONSTVOL"), 0, 0); - else - attrval = lookup_field (__attr_desc_type_node, - get_identifier("_RTTI_ATTR_CONST"), 0, 0); - } + type = TREE_TYPE (type); + expand_expr_stmt (get_typeid_1 (type)); + t = decay_conversion (get_tinfo_var (type)); + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, t, NULL_TREE))); + + fn = get_identifier ("__rtti_ptr"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); else { - if (TYPE_VOLATILE (type)) - attrval = lookup_field (__attr_desc_type_node, - get_identifier("_RTTI_ATTR_VOLATILE"), 0, 0); + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, build_pointer_type (type_info_type_node), + void_list_node))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + pop_obstacks (); } - t = build_t_desc (TYPE_MAIN_VARIANT (type), 1); - t = build_indirect_ref (t , NULL); - elems = tree_cons (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE)); - return build_generic_desc (tdecl, __attr_desc_type_node, elems); -} - -/* Build an initializer for a __func_type_info node. */ -static tree -build_func_desc (tdecl) - tree tdecl; -{ - tree elems, name_string; - tree tname = DECL_NAME (tdecl); - name_string = combine_strings (build_string - (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); - elems = name_string; - return build_generic_desc (tdecl, __func_desc_type_node, elems); + fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + decay_conversion (fn), elems, 0); + TREE_SIDE_EFFECTS (fn) = 1; + expand_expr_stmt (fn); } -/* Build an initializer for a __ptmf_type_info node. */ -static tree -build_ptmf_desc (tdecl) - tree tdecl; -{ - tree elems, name_string; - tree tname = DECL_NAME (tdecl); - - name_string = combine_strings (build_string - (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); - elems = name_string; - return build_generic_desc (tdecl, __ptmf_desc_type_node, elems); -} - -/* Build an initializer for a __ptmd_type_info node. */ -static tree -build_ptmd_desc (tdecl, type) - tree tdecl; - tree type; -{ - tree tc, t, elems; - tc = build_t_desc (TYPE_OFFSET_BASETYPE (type), 1); - tc = build_indirect_ref (tc , NULL); - t = build_t_desc (TREE_TYPE (type), 1); - t = build_indirect_ref (t , NULL); - elems = tree_cons (NULL_TREE, tc, - tree_cons (NULL_TREE, t, NULL_TREE)); - return build_generic_desc (tdecl, __ptmd_desc_type_node, elems); -} - -struct uninst_st { - tree type; - struct uninst_st *next; -}; -typedef struct uninst_st uninst_node; -static uninst_node * uninst_desc = (uninst_node *)NULL; +/* Build an initializer for a __attr_type_info node. */ static void -add_uninstantiated_desc (type) +expand_attr_desc (tdecl, type) + tree tdecl; tree type; { - uninst_node *t; + tree elems, t, fn; + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name), name)); + tree attrval = build_int_2 + (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0); + + expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type))); + t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type))); + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE)))); + + fn = get_identifier ("__rtti_attr"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, integer_type_node, tree_cons + (NULL_TREE, build_pointer_type (type_info_type_node), + void_list_node)))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + pop_obstacks (); + } - t = (uninst_node *) xmalloc (sizeof (struct uninst_st)); - t->type = type; - t->next = uninst_desc; - uninst_desc = t; + fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + decay_conversion (fn), elems, 0); + TREE_SIDE_EFFECTS (fn) = 1; + expand_expr_stmt (fn); } -/* We may choose to link the emitting of certain high use TDs for certain - objects, we do that here. Return the type to link against if such a - link exists, otherwise just return TYPE. */ +/* Build an initializer for a type_info node that just has a name. */ -static tree -get_def_to_follow (type) - tree type; -{ -#if 0 - /* For now we don't lay out T&, T* TDs with the main TD for the object. */ - /* Let T* and T& be written only when T is written (if T is an aggr). - We do this for const, but not for volatile, since volatile - is rare and const is not. */ - if (!TYPE_VOLATILE (taggr) - && (TREE_CODE (taggr) == POINTER_TYPE - || TREE_CODE (taggr) == REFERENCE_TYPE) - && IS_AGGR_TYPE (TREE_TYPE (taggr))) - taggr = TREE_TYPE (taggr); -#endif - return type; -} - -/* build a general type_info node. */ -tree -build_t_desc (type, definition) +static void +expand_generic_desc (tdecl, type, fnname) + tree tdecl; tree type; - int definition; + char *fnname; { - tree tdecl, tname; - tree t, taggr; - - if (__ptmd_desc_type_node == NULL_TREE) - { - init_type_desc(); - if (__ptmd_desc_type_node) - { - for ( ; uninst_desc; uninst_desc = uninst_desc->next ) - build_t_desc (uninst_desc->type, 1); - } - } - if (__t_desc_type_node == NULL_TREE) - { - static int warned = 0; - if (! warned) - { - cp_error ("failed to build type descriptor node of '%T', maybe <typeinfo> not included", type); - } - warned = 1; - return error_mark_node; - } - if (__ptmd_desc_type_node == NULL_TREE) - { - add_uninstantiated_desc (type); - definition = 0; - } - - push_obstacks (&permanent_obstack, &permanent_obstack); - tname = build_t_desc_overload (type); - - if (!IDENTIFIER_AS_DESC (tname)) + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name), name)); + tree elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), NULL_TREE)); + + tree fn = get_identifier (fnname); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else { - tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); - DECL_EXTERNAL (tdecl) = 1; - TREE_PUBLIC (tdecl) = 1; - tdecl = pushdecl_top_level (tdecl); - SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); - if (!definition) - cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, void_list_node)); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + pop_obstacks (); } - else - tdecl = TREE_OPERAND (IDENTIFIER_AS_DESC (tname), 0); - /* If it's not a definition, don't do anything more. */ - if (!definition) - return IDENTIFIER_AS_DESC (tname); + fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)), + decay_conversion (fn), elems, 0); + TREE_SIDE_EFFECTS (fn) = 1; + expand_expr_stmt (fn); +} - /* If it has already been written, don't to anything more. */ - /* Should this be on tdecl? */ - if (TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))) - return IDENTIFIER_AS_DESC (tname); +/* Generate the code for a type_info initialization function. + Note that we take advantage of the passage - /* If we previously defined it, return the defined result. */ - if (DECL_INITIAL (tdecl)) - return IDENTIFIER_AS_DESC (tname); - - taggr = get_def_to_follow (type); + 5.2.7 Type identification [expr.typeid] + + Whether or not the destructor is called for the type_info object at the + end of the program is unspecified. - /* If we know that we don't need to write out this type's - vtable, then don't write out it's type_info. Somebody - else will take care of that. */ - if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr)) - { - /* Let's play follow the vtable. */ - TREE_PUBLIC (tdecl) = CLASSTYPE_INTERFACE_KNOWN (taggr); - DECL_EXTERNAL (tdecl) = CLASSTYPE_INTERFACE_ONLY (taggr); - } - else - { - DECL_EXTERNAL (tdecl) = 0; - TREE_PUBLIC (tdecl) = (definition > 1); - } + and don't bother to arrange for these objects to be destroyed. It + doesn't matter, anyway, since the destructors don't do anything. + + This must only be called from toplevel (i.e. from finish_file)! */ - if (DECL_EXTERNAL (tdecl)) - return IDENTIFIER_AS_DESC (tname); +void +synthesize_tinfo_fn (fndecl) + tree fndecl; +{ + tree type = TREE_TYPE (DECL_NAME (fndecl)); + tree tmp, addr; - /* Show that we are defining the t_desc for this type. */ - DECL_INITIAL (tdecl) = error_mark_node; - t = DECL_CONTEXT (tdecl); - if ( t && TREE_CODE_CLASS (TREE_CODE (t)) == 't') - pushclass (t, 2); + tree tdecl = get_tinfo_var (type); + DECL_EXTERNAL (tdecl) = 0; + TREE_STATIC (tdecl) = 1; + DECL_COMMON (tdecl) = 1; + TREE_USED (tdecl) = 1; + DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node); + cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); + + start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1); + store_parm_decls (); + clear_last_expr (); + push_momentary (); + + /* If the first word of the array (the vtable) is non-zero, we've already + initialized the object, so don't do it again. */ + addr = decay_conversion (tdecl); + tmp = convert (build_pointer_type (ptr_type_node), addr); + tmp = build_indirect_ref (tmp, 0); + tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1); + expand_start_cond (tmp, 0); if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) - t = build_attr_desc (tdecl, type); + expand_attr_desc (tdecl, type); else if (TREE_CODE (type) == ARRAY_TYPE) - t = build_ptr_desc (tdecl, type); + expand_generic_desc (tdecl, type, "__rtti_array"); else if (TREE_CODE (type) == POINTER_TYPE) { if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) - { - type = TREE_TYPE (type); - t = build_ptmd_desc (tdecl, type); - } + expand_generic_desc (tdecl, type, "__rtti_ptmd"); + else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE) + expand_generic_desc (tdecl, type, "__rtti_ptmf"); else - { - t = build_ptr_desc (tdecl, type); - } + expand_ptr_desc (tdecl, type); } - else if (TYPE_BUILT_IN (type)) - t = build_bltn_desc (tdecl, type); + else if (TYPE_PTRMEMFUNC_P (type)) + expand_generic_desc (tdecl, type, "__rtti_ptmf"); else if (IS_AGGR_TYPE (type)) { - if (TYPE_PTRMEMFUNC_P (type)) - t = build_ptmf_desc (tdecl); + if (CLASSTYPE_N_BASECLASSES (type) == 0) + expand_generic_desc (tdecl, type, "__rtti_user"); + else if (! TYPE_USES_COMPLEX_INHERITANCE (type) + && (TREE_VIA_PUBLIC + (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)))) + expand_si_desc (tdecl, type); else - t = build_class_desc (tdecl, type); + expand_class_desc (tdecl, type); } + else if (TREE_CODE (type) == ENUMERAL_TYPE) + expand_generic_desc (tdecl, type, "__rtti_user"); else if (TREE_CODE (type) == FUNCTION_TYPE) - t = build_func_desc (tdecl); - else - t = build_user_desc (tdecl); + expand_generic_desc (tdecl, type, "__rtti_func"); + else + my_friendly_abort (252); - pop_obstacks (); - return t; + expand_end_cond (); + + /* OK, now return the type_info object. */ + tmp = convert (build_pointer_type (type_info_type_node), addr); + tmp = build_indirect_ref (tmp, 0); + c_expand_return (tmp); + finish_function (lineno, 0, 0); } #if 0 diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 588d823..ed97fc3 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -74,7 +74,7 @@ pop_stack_level (stack) static struct search_level *search_stack; static tree lookup_field_1 (); -static int lookup_fnfields_1 (); +static int lookup_fnfields_1 PROTO((tree, tree)); static void dfs_walk (); static int markedp (); static void dfs_unmark (); @@ -246,6 +246,18 @@ my_new_memoized_entry (chain) return p; } +/* Clears the deferred pop from pop_memoized_context, if any. */ +static void +clear_memoized_cache () +{ + if (prev_type_stack) + { + type_stack = pop_type_level (prev_type_stack); + prev_type_memoized = 0; + prev_type_stack = 0; + } +} + /* Make an entry in the memoized table for type TYPE that the entry for NAME is FIELD. */ @@ -257,6 +269,10 @@ make_memoized_table_entry (type, name, function_p) int index = MEMOIZED_HASH_FN (name); tree entry, *prev_entry; + /* Since we allocate from the type_obstack, we must pop any deferred + levels. */ + clear_memoized_cache (); + memoized_adds[function_p] += 1; if (CLASSTYPE_MTABLE_ENTRY (type) == 0) { @@ -334,9 +350,7 @@ push_memoized_context (type, use_old) return; } /* Otherwise, need to pop old stack here. */ - type_stack = pop_type_level (prev_type_stack); - prev_type_memoized = 0; - prev_type_stack = 0; + clear_memoized_cache (); } type_stack = push_type_level ((struct stack_level *)type_stack, @@ -364,6 +378,9 @@ pop_memoized_context (use_old) while (len--) tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]); + /* If there was a deferred pop, we need to pop it now. */ + clear_memoized_cache (); + prev_type_stack = type_stack; prev_type_memoized = type_stack->type; } @@ -494,14 +511,23 @@ get_binfo (parent, binfo, protect) static int get_base_distance_recursive (binfo, depth, is_private, rval, rval_private_ptr, new_binfo_ptr, parent, path_ptr, - protect, via_virtual_ptr, via_virtual) - tree binfo, *new_binfo_ptr, parent, *path_ptr; - int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr, - via_virtual; + protect, via_virtual_ptr, via_virtual, + current_scope_in_chain) + tree binfo; + int depth, is_private, rval; + int *rval_private_ptr; + tree *new_binfo_ptr, parent, *path_ptr; + int protect, *via_virtual_ptr, via_virtual; + int current_scope_in_chain; { tree binfos; int i, n_baselinks; + if (protect + && !current_scope_in_chain + && is_friend (BINFO_TYPE (binfo), current_scope ())) + current_scope_in_chain = 1; + if (BINFO_TYPE (binfo) == parent || binfo == parent) { if (rval == -1) @@ -556,6 +582,8 @@ get_base_distance_recursive (binfo, depth, is_private, rval, = (protect && (is_private || (!TREE_VIA_PUBLIC (base_binfo) + && !(TREE_VIA_PROTECTED (base_binfo) + && current_scope_in_chain) && !is_friend (BINFO_TYPE (binfo), current_scope ())))); int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo); int was; @@ -572,7 +600,8 @@ get_base_distance_recursive (binfo, depth, is_private, rval, rval, rval_private_ptr, new_binfo_ptr, parent, path_ptr, protect, via_virtual_ptr, - this_virtual); + this_virtual, + current_scope_in_chain); /* watch for updates; only update if path is good. */ if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was) BINFO_INHERITANCE_CHAIN (base_binfo) = binfo; @@ -652,7 +681,8 @@ get_base_distance (parent, binfo, protect, path_ptr) rval = get_base_distance_recursive (binfo, 0, 0, -1, &rval_private, &new_binfo, parent, - path_ptr, watch_access, &via_virtual, 0); + path_ptr, watch_access, &via_virtual, 0, + 0); dfs_walk (binfo, dfs_unmark, markedp); @@ -2106,8 +2136,9 @@ get_matching_virtual (binfo, fndecl, dtorp) expand_direct_vtbls_init for the style of search we do. */ static tree get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals) - tree binfo, abstract_virtuals; + tree binfo; int do_self; + tree abstract_virtuals; { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; @@ -2559,12 +2590,12 @@ dfs_init_vbase_pointers (binfo) CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); - /* If there is a rtti, it is the first field, though perhaps from - the base class. Otherwise, the first fields are virtual base class - pointer fields. */ - if (CLASSTYPE_RTTI (type) && VFIELD_NAME_P (DECL_NAME (fields))) - /* Get past vtable for the object. */ +#if 0 + /* See finish_struct_1 for when we can enable this. */ + /* If we have a vtable pointer first, skip it. */ + if (VFIELD_NAME_P (DECL_NAME (fields))) fields = TREE_CHAIN (fields); +#endif if (fields == NULL_TREE || DECL_NAME (fields) == NULL_TREE @@ -2736,6 +2767,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, 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, 0, LOOKUP_ONLYCONVERTING); @@ -2796,8 +2828,9 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, 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, 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); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 762a0aa..a2c79b4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1572,6 +1572,22 @@ default_conversion (exp) return exp; } + +/* Take the address of an inline function without setting TREE_ADDRESSABLE + or TREE_USED. */ + +tree +inline_conversion (exp) + tree exp; +{ + if (TREE_CODE (exp) == FUNCTION_DECL) + { + tree type = build_type_variant + (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp)); + exp = build1 (ADDR_EXPR, build_pointer_type (type), exp); + } + return exp; +} tree build_object_ref (datum, basetype, field) @@ -2489,11 +2505,6 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) { aref = save_expr (aref); - /* 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)); - delta = build_binary_op (PLUS_EXPR, build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node), delta, 1); @@ -2575,10 +2586,7 @@ build_function_call_real (function, params, require_complete, flags) && current_function_decl) synthesize_method (function); - fntype = build_type_variant (TREE_TYPE (function), - TREE_READONLY (function), - TREE_THIS_VOLATILE (function)); - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); + function = inline_conversion (function); } else function = default_conversion (function); |