diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/ChangeLog gcc-2.95.3/gcc/cp/ChangeLog *** gcc-2.95.2/gcc/cp/ChangeLog Mon Oct 25 07:59:12 1999 --- gcc-2.95.3/gcc/cp/ChangeLog Fri Mar 16 12:52:13 2001 *************** *** 1,3 **** --- 1,146 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + + Fri Jun 9 17:55:08 2000 Jeffrey A Law (law@cygnus.com) + + 2000-02-07 + * decl2.c (import_export_decl): vlist ctor wrappers follow virtual + methods in their interface. + (vlist_ctor_wrapper_p): new function. + (finish_vlist_ctor_wrapper): likewise. + + 2000-02-06 + * decl2.c (maybe_retrofit_in_chrg): Move call to + make_vlist_ctor_wrapper from here ... + * decl.c (grok_ctor_properties): ... to here. + * decl.c (grokfndecl): ... and here. + * init.c (no_vlist_base_init): Declare unseen Vlist ctor weak. + * decl2.c (maybe_retrofit_in_chrg): Be sorry about varargs ctors. + + 2000-03-08 Nathan Sidwell + + * exception.cc (__cp_pop_exception): Cleanup the original object. + + 1999-11-13 Jason Merrill + + * rtti.c (get_tinfo_fn_unused): Split out from get_tinfo_fn. + * class.c (set_rtti_entry): Use it. + + Wed Apr 12 00:45:49 2000 Jeffrey A Law (law@cygnus.com) + + 2000-02-03 + * call.c (add_function_candidate): Do not add vlist ctor into + candidates in compatibility mode. + (build_user_type_conversion_1): Add LOOKUP_HAS_VLIST when adding + vlist. + (convert_like): Likewise. + (build_over_call): Skip vlist only if it is mentioned in flags. + (build_new_method_call): Do not add vlist in compatibility mode, + except for dtors. + * cp-tree.h (flag_vtable_thunks): Has now four possible values. + (DECL_VLIST_CTOR_WRAPPER_P, DECL_VLIST_CTOR_WRAPPED): New macros. + (in_charge_identifier): Declare external. + * decl.c (xref_basetypes): Check for vtable_thunks >=2. + (finish_dtor): Use bit 2 of in_chrg. + (finish_function): Do not finish vlist ctor wrappers. + * decl2.c (flag_vtable_thunks_compat): New variable. + (lang_decode_option): Set it accordingly. + (maybe_retrofit_in_chrg): Call make_vlist_ctor_wrapper. + * init.c (build_base_dtor_call): Pass 4 in in_chrg. + (no_vlist_base_init): New function. + (expand_default_init): Do not pass vlist in compatibility mode. + Try to call old base ctor if new one was not generated. + (build_new_1): Do not pass vlist in compatibility mode. + * method.c (get_id_2): Do not put _Vlist into dtor name in + compatibility mode. + (make_vlist_ctor_wrapper, emit_vlist_ctor_wrapper): New functions. + (synthesize_method): Call emit_vlist_ctor_wrapper. + * pt.c (instantiate_class_template): Check for vtable_thunks >=2. + + Sat Nov 13 15:48:59 1999 H.J. Lu + * init.c (finish_dtor): Call mark_all_temps_used () before + declaring vlist. + + Tue Nov 9 15:01:57 1999 H.J. Lu + * init.c (construct_virtual_bases): Update. + (expand_cleanup_for_base): Update. + + Tue Nov 9 08:25:04 1999 H.J. Lu + * init.c (construct_virtual_bases): Update. + (expand_cleanup_for_base): Take vlist parameter. + (emit_base_init): Pass vlist to expand_cleanup_for_base. + (construct_virtual_bases): Likewise. + + 1999-05-02 Martin von Löwis + * class.c (prepare_ctor_vtable, finish_one_ctor_vtable, + prepend_ctor_vfields_for_vbase, finish_ctor_vtables_for_vbases, + finish_ctor_vtables_1, prepend_vbase_vfields, + finish_ctor_vtables): New functions. + (finish_struct_1): Call finish_ctor_vtables. + * cp-tree.h (TYPE_USES_PVBASES): New macro. + (constructor_for_vbase_attr): Widen to two bits. + (CONSTRUCTOR_FOR_VBASE, CONSTRUCTOR_FOR_PVBASE, + DESTRUCTOR_FOR_PVBASE): New macros. + (DECL_CONSTRUCTOR_FOR_VBASE_P): Adopt to new enumeration. + (DECL_CONSTRUCTOR_FOR_VBASE): New macro. + (DECL_CONSTRUCTOR_FOR_PVBASE_P, DECL_DESTRUCTOR_FOR_PVBASE_P): New + macros. + (vlist_identifier, vlist_type_node, vlist_zero_node): Declare. + (VCTABLE_NAME, VLIST_NAME_FORMAT, VLIST_NAME, VLIST1_NAME, + VLIST_TYPE_NAME): New macros. + (LOOKUP_HAS_VLIST): New macro. + (build_base_dtor_call, init_vlist): Declare. + (build_destructor_name): Add int argument. + * decl.c (vlist_identifier, vlist_type_node, vlist_zero_node): + Define. + (init_decl_processing): Initialize them. + (grokdeclarator): Handle vlist argument. + (copy_args_p): Likewise. + (grok_ctor_properties): Don't try to skip initial int for + templates. Skip vlist if available. + (xref_basetypes): Set TYPE_USES_PVBASES. + (finish_dtor, finish_ctor): New functions, moved out of ... + (finish_function): ... here. + * decl2.c (lang_decode_option): Set flag_vtable_thunks explicitly. + (maybe_retrofit_in_chrg): Retrofit __vlist parameter. + (grokclassfn): Pass pvbase flag into mangled name. + * init.c (build_base_dtor_call): New function. + (build_partial_cleanup_for): Call it. + (pvbasecount, init_vlist, ): New functions. + (emit_base_init): Process vlist argument. + (expand_aggr_vbase_init_1): Likewise. + (expand_aggr_vbase_init): Likewise. + (expand_default_init): Likewise. + (build_new_1): Pass null vlist argument. + (build_delete): Likewise. Call build_base_dtor_call. + * method.c (process_overload_item): Mangle _Vlist specially. + (build_base_path, get_vlist_vtable_id): New functions. + (build_destructor_name): Potentially mangle _Vlist into it. + (do_build_copy_constructor): Skip vlist argument. + (synthesize_method): Likewise. + * pt.c (has_pvbases_p): New function. + (instantiate_class_template): Call it. + (tsubst_decl): Retrofit before mangling. Pass pvbase_p to + destructor mangling. + * search.c (expand_direct_vtbls_init_thunks): New function. + (expand_indirect_vtbls_init_thunks): New function. + (expand_indirect_vtbls_init): Call it. + * call.c (add_function_candidate): Process vlist argument. + (build_user_type_conversion_1): Add vlist argument. + (convert_like): Likewise. + (build_over_call): Likewise. + (build_new_method_call): Likewise. + + 2000-02-18 Martin von Loewis + + * typeck2.c (my_friendly_abort): Use GCCBUGURL. + + 1999-11-01 Jason Merrill + + * decl2.c (maybe_make_one_only): Always make things comdat on + ELF targets, too. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/call.c gcc-2.95.3/gcc/cp/call.c *** gcc-2.95.2/gcc/cp/call.c Wed Jun 16 12:26:24 1999 --- gcc-2.95.3/gcc/cp/call.c Wed Apr 12 07:53:29 2000 *************** add_function_candidate (candidates, fn, *** 1065,1072 **** tree parmnode, argnode; int viable = 1; ! /* The `this' and `in_chrg' arguments to constructors are not considered ! in overload resolution. */ if (DECL_CONSTRUCTOR_P (fn)) { parmlist = TREE_CHAIN (parmlist); --- 1065,1072 ---- tree parmnode, argnode; int viable = 1; ! /* The `this', `in_chrg', and `vlist' arguments to constructors are ! not considered in overload resolution. */ if (DECL_CONSTRUCTOR_P (fn)) { parmlist = TREE_CHAIN (parmlist); *************** add_function_candidate (candidates, fn, *** 1076,1081 **** --- 1076,1097 ---- parmlist = TREE_CHAIN (parmlist); arglist = TREE_CHAIN (arglist); } + if ((flags & LOOKUP_HAS_VLIST) + && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + { + parmlist = TREE_CHAIN (parmlist); + arglist = TREE_CHAIN (arglist); + } + else if (!(flags & LOOKUP_HAS_VLIST) + && !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + /* Ok */; + else + { + /* The ctor expects a vlist and the arguments don't have + one, or vice versa, so fn is not even a candidate, since + the corresponding ctor would be the candidate. */ + return candidates; + } } len = list_length (arglist); *************** build_user_type_conversion_1 (totype, ex *** 2071,2076 **** --- 2087,2097 ---- tree t = build_int_2 (0, 0); TREE_TYPE (t) = build_pointer_type (totype); args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_PVBASES (totype) && !flag_vtable_thunks_compat) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags |= LOOKUP_HAS_VLIST; + } if (TYPE_USES_VIRTUAL_BASECLASSES (totype)) args = scratch_tree_cons (NULL_TREE, integer_one_node, args); args = scratch_tree_cons (NULL_TREE, t, args); *************** convert_like (convs, expr) *** 3038,3043 **** --- 3059,3065 ---- = WRAPPER_PTR (TREE_OPERAND (convs, 1)); tree fn = cand->fn; tree args; + int flags = LOOKUP_NORMAL; if (DECL_CONSTRUCTOR_P (fn)) { *************** convert_like (convs, expr) *** 3045,3057 **** TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn)); args = build_scratch_list (NULL_TREE, expr); if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) args = scratch_tree_cons (NULL_TREE, integer_one_node, args); args = scratch_tree_cons (NULL_TREE, t, args); } else args = build_this (expr); ! expr = build_over_call (cand, args, LOOKUP_NORMAL); /* If this is a constructor or a function returning an aggr type, we need to build up a TARGET_EXPR. */ --- 3067,3085 ---- TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn)); args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_PVBASES (DECL_CONTEXT (fn)) + && !flag_vtable_thunks_compat) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags != LOOKUP_HAS_VLIST; + } if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) args = scratch_tree_cons (NULL_TREE, integer_one_node, args); args = scratch_tree_cons (NULL_TREE, t, args); } else args = build_this (expr); ! expr = build_over_call (cand, args, flags); /* If this is a constructor or a function returning an aggr type, we need to build up a TARGET_EXPR. */ *************** build_over_call (cand, args, flags) *** 3260,3265 **** --- 3288,3300 ---- arg = TREE_CHAIN (arg); parm = TREE_CHAIN (parm); } + if (flags & LOOKUP_HAS_VLIST) + { + converted_args = expr_tree_cons + (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + } } /* Bypass access control for 'this' parameter. */ else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) *************** build_over_call (cand, args, flags) *** 3369,3374 **** --- 3404,3411 ---- arg = TREE_CHAIN (converted_args); if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) arg = TREE_CHAIN (arg); + if (flags & LOOKUP_HAS_VLIST) + arg = TREE_CHAIN (arg); arg = TREE_VALUE (arg); /* Pull out the real argument, disregarding const-correctness. */ *************** build_new_method_call (instance, name, a *** 3544,3549 **** --- 3581,3588 ---- remove it for error reporting. */ if (flags & LOOKUP_HAS_IN_CHARGE) user_args = TREE_CHAIN (args); + if (flags & LOOKUP_HAS_VLIST) + user_args = TREE_CHAIN (user_args); args = resolve_args (args); *************** build_new_method_call (instance, name, a *** 3616,3621 **** --- 3655,3666 ---- if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype) && ! (flags & LOOKUP_HAS_IN_CHARGE)) { + if (TYPE_USES_PVBASES(basetype) + && (!flag_vtable_thunks_compat || (name == dtor_identifier))) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags |= LOOKUP_HAS_VLIST; + } flags |= LOOKUP_HAS_IN_CHARGE; args = scratch_tree_cons (NULL_TREE, integer_one_node, args); } diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/class.c gcc-2.95.3/gcc/cp/class.c *** gcc-2.95.2/gcc/cp/class.c Sat Aug 7 02:31:51 1999 --- gcc-2.95.3/gcc/cp/class.c Thu Apr 20 06:13:24 2000 *************** static tree get_basefndecls PROTO((tree, *** 102,109 **** --- 102,116 ---- static void set_rtti_entry PROTO((tree, tree, tree)); static tree build_vtable PROTO((tree, tree)); static void prepare_fresh_vtable PROTO((tree, tree)); + static tree prepare_ctor_vtable PROTO((tree, tree, tree)); static void fixup_vtable_deltas1 PROTO((tree, tree)); static void fixup_vtable_deltas PROTO((tree, int, tree)); + static tree finish_one_ctor_vtable PROTO((tree, tree, tree, tree)); + static tree prepend_ctor_vfields_for_vbase PROTO((tree, tree, tree, tree, int, tree)); + static tree finish_ctor_vtables_for_vbases PROTO((tree, tree, tree)); + static tree finish_ctor_vtables_1 PROTO((tree, tree)); + static tree prepend_vbase_vfields PROTO((tree, int, tree)); + static void finish_ctor_vtables PROTO((tree)); static void finish_vtbls PROTO((tree, int, tree)); static void modify_vtable_entry PROTO((tree, tree, tree)); static tree get_vtable_entry_n PROTO((tree, unsigned HOST_WIDE_INT)); *************** set_rtti_entry (virtuals, offset, type) *** 673,679 **** return; if (flag_rtti) ! vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type)); else vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node); TREE_CONSTANT (vfn) = 1; --- 680,686 ---- return; if (flag_rtti) ! vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn_unused (type)); else vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node); TREE_CONSTANT (vfn) = 1; *************** prepare_fresh_vtable (binfo, for_type) *** 922,927 **** --- 929,971 ---- SET_BINFO_NEW_VTABLE_MARKED (binfo); } + /* Return a new vtable for use in initialization of the BASE subobject + of COMPLETE_TYPE. The vtable there goes into the vfield of the + VBASEBASE virtual subobject. */ + + static tree + prepare_ctor_vtable (complete_type, base, vbasebase) + tree complete_type, base, vbasebase; + { + tree orig_decl = BINFO_VTABLE (vbasebase); + tree name = get_vlist_vtable_id (base, vbasebase); + tree new_decl; + + new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); + /* Remember which class this vtable is really for. */ + DECL_CONTEXT (new_decl) = complete_type; + + DECL_ARTIFICIAL (new_decl) = 1; + TREE_STATIC (new_decl) = 1; + new_decl = pushdecl_top_level (new_decl); + DECL_VIRTUAL_P (new_decl) = 1; + #ifndef WRITABLE_VTABLES + /* Make them READONLY by default. (mrs) */ + TREE_READONLY (new_decl) = 1; + #endif + DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl); + + #ifdef GATHER_STATISTICS + n_vtables += 1; + n_vtable_elems += list_length (BINFO_VIRTUALS (binfo)); + #endif + + /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ + import_export_vtable (new_decl, complete_type, 0); + + return new_decl; + } + #if 0 /* Access the virtual function table entry that logically contains BASE_FNDECL. VIRTUALS is the virtual function table's *************** finish_struct_bits (t, max_has_virtual) *** 1798,1803 **** --- 1842,1848 ---- TYPE_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t); TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t); TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t); + TYPE_USES_PVBASES (variants) = TYPE_USES_PVBASES (t); /* Copy whatever these are holding today. */ TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t); TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t); *************** warn_hidden (t) *** 2933,2938 **** --- 2978,3286 ---- } } + /* Generate one vtable for use in constructors or destructors of BASE + subobjects of COMPLETE_TYPE objects. The vtable belongs to the + vfield of the VBASEVASE subobject of the VBASE virtual base of + COMPLETE_TYPE (and BASE). */ + + static tree + finish_one_ctor_vtable (complete_type, base, vbase, vbasebase) + tree complete_type, base, vbase, vbasebase; + { + tree virtuals; + tree newtable; + tree newvirtuals; + tree offset; + tree newvbase = binfo_member (BINFO_TYPE (vbase), + CLASSTYPE_VBASECLASSES (complete_type)); + + newtable = prepare_ctor_vtable (complete_type, base, vbasebase); + newvirtuals = copy_list (BINFO_VIRTUALS (vbasebase)); + + virtuals = newvirtuals; + /* Change the offset entry. First, delta between base an vbase. */ + offset = ssize_binop (MINUS_EXPR, BINFO_OFFSET (newvbase), + BINFO_OFFSET (base)); + /* Add delta between vbase and vbasebase. */ + offset = ssize_binop (PLUS_EXPR, offset, BINFO_OFFSET (vbasebase)); + offset = ssize_binop (MINUS_EXPR, offset, BINFO_OFFSET (vbase)); + /* Finally, negate. */ + offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset); + offset = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); + TREE_CONSTANT (offset) = 1; + TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, offset); + virtuals = TREE_CHAIN (virtuals); + + /* Skip the typeinfo function. */ + virtuals = TREE_CHAIN (virtuals); + + /* Iterate over all methods of this virtual base. */ + for (; virtuals; virtuals = TREE_CHAIN (virtuals)) + { + tree fndecl = TREE_VALUE (virtuals); + tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl); + fndecl = TREE_OPERAND (pfn, 0); + if (fndecl) + { + tree delta, newdelta, binfo_context; + tree context = DECL_CLASS_CONTEXT (fndecl); + + /* If this method is implemented in a base of the vbase, the + thunk we have is correct. */ + if (DERIVED_FROM_P (context, vbase)) + continue; + + binfo_context = binfo_value (context, base); + if (TREE_VIA_VIRTUAL (binfo_context)) + binfo_context = binfo_member + (context, CLASSTYPE_VBASECLASSES (complete_type)); + /* This is the delta from a complete C to a B subobject, or + more generally to the base subobject that implements the + virtual function for B. BASE already has the offset to + the complete type. */ + delta = BINFO_OFFSET (binfo_context); + /* This is the delta from the A to the complete C. */ + newdelta = BINFO_OFFSET (newvbase); + /* This is the delta from the A to the B subobject. */ + newdelta = size_binop (MINUS_EXPR, newdelta, delta); + newdelta = ssize_binop (MINUS_EXPR, integer_zero_node, + newdelta); + + modify_vtable_entry (virtuals, + build_vtable_entry (newdelta, pfn), + fndecl); + } + } + DECL_INITIAL (newtable) = build_nt (CONSTRUCTOR, NULL_TREE, + newvirtuals); + DECL_CONTEXT (newtable) = NULL_TREE; + cp_finish_decl (newtable, DECL_INITIAL (newtable), NULL_TREE, 0, 0); + DECL_CONTEXT (newtable) = complete_type; + return newtable; + } + + /* Add all vtables into LIST for the VBASEBASE subobject and its bases + of VBASE virtual BASE of COMPLETE_TYPE for use in BASE + constructors. DO_SELF indicates whether this is the VBASEBASE that + has 'primary' vfield. Return the new LIST. */ + + static tree + prepend_ctor_vfields_for_vbase (complete_type, base, vbase, vbasebase, + do_self, list) + tree complete_type, base, vbase, vbasebase; + int do_self; + tree list; + { + int i; + tree vtbl; + tree bases = BINFO_BASETYPES (vbasebase); + int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (vbasebase)); + + if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (vbasebase))) + { + vtbl = finish_one_ctor_vtable (complete_type, base, vbase, vbasebase); + vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl); + TREE_READONLY (vtbl) = 1; + TREE_CONSTANT (vtbl) = 1; + list = tree_cons (NULL_TREE, vtbl, list); + } + + if (!bases) + return list; + + for (i = 0; i < TREE_VEC_LENGTH (bases); i++) + { + tree vbasebase = TREE_VEC_ELT (bases, i); + if (TREE_VIA_VIRTUAL (vbasebase)) + continue; + list = prepend_ctor_vfields_for_vbase + (complete_type, base, vbase, vbasebase, (i != vfp), list); + } + + return list; + } + + /* Iterate over all virtual bases of the BASE subobject of + COMPLETE_TYPE. This list is given in VBASES. Return the list of + vtables generated in the process. */ + + static tree + finish_ctor_vtables_for_vbases (vbases, base, complete_type) + tree vbases, base, complete_type; + { + tree result = NULL_TREE; + + for (; vbases; vbases = TREE_CHAIN (vbases)) + result = prepend_ctor_vfields_for_vbase + (complete_type, base, vbases, vbases, 1, result); + return result; + } + + /* Generate special vtables for virtual bases for use inside base + class ctors and dtors. Inside this function, we assume the + following scenario: + class A{virtual void foo();}; + class B:virtual A{int member1;} + class C:B{int member2;} + + BINFO is a base subject (e.g. B) of COMPLETE_TYPE. Returns the list + of virtual tables. */ + + static tree + finish_ctor_vtables_1 (binfo, complete_type) + tree binfo; + tree complete_type; + { + int i; + tree binfos; + tree result = NULL_TREE; + + binfos = BINFO_BASETYPES (binfo); + if (!binfos) + return result; + + /* Iterate over all bases (i.e. B). */ + for (i = 0; i < TREE_VEC_LENGTH (binfos); i++) + { + tree base = TREE_VEC_ELT (binfos, i); + tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (base)); + if (!vbases) + /* This base class does not have virtual bases. */ + continue; + if (TREE_VIA_VIRTUAL (base)) + /* A virtual base class is initialized on in the most-derived + constructor. */ + continue; + if (!TYPE_USES_PVBASES (BINFO_TYPE (base))) + /* Class has no polymorphic vbases. */ + continue; + /* Prepend vtable list for base class. */ + result = chainon (finish_ctor_vtables_1 (base, complete_type), + result); + /* Prepend our own vtable list. */ + result = chainon + (finish_ctor_vtables_for_vbases (vbases, base, complete_type), + result); + } + return result; + } + + /* Add the vtables of a virtual base BINFO in front of LIST, returning + the new list. DO_SELF indicates whether we have to return the + vtable of a vfield borrowed in a derived class. */ + + static tree + prepend_vbase_vfields (binfo, do_self, list) + tree binfo; + int do_self; + tree list; + { + int i; + tree vtbl; + tree bases = BINFO_BASETYPES (binfo); + int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + + if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + vtbl = BINFO_VTABLE (binfo); + vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl); + TREE_READONLY (vtbl) = 1; + TREE_CONSTANT (vtbl) = 1; + list = tree_cons (NULL_TREE, vtbl, list); + } + + if (!bases) + return list; + + for (i = 0; i < TREE_VEC_LENGTH (bases); i++) + { + tree base = TREE_VEC_ELT (bases, i); + if (TREE_VIA_VIRTUAL (base)) + continue; + list = prepend_vbase_vfields (base, (i != vfp), list); + } + + return list; + } + + /* Wrapper around finish_ctor_vtables_1. Compute the vtable list for + type T. */ + + static void + finish_ctor_vtables (t) + tree t; + { + tree veclist = NULL_TREE; + tree decl, type; + char *name; + tree vbase; + int len; + + /* This is only good for vtable thunks. */ + my_friendly_assert (flag_vtable_thunks, 990307); + + /* Start with the list of most-derived vtables. */ + + for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; + vbase = TREE_CHAIN (vbase)) + veclist = prepend_vbase_vfields (vbase, 1, veclist); + + /* Compute the list of vtables for the bases. */ + veclist = chainon (veclist, finish_ctor_vtables_1 (TYPE_BINFO (t), t)); + + /* Finally, we initialize the virtual bases first. */ + for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; + vbase = TREE_CHAIN (vbase)) + { + tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbase)); + if (!vbases) + continue; + veclist = chainon (veclist, + finish_ctor_vtables_for_vbases (vbases, vbase, t)); + veclist = chainon (veclist, + finish_ctor_vtables_1 (vbase, t)); + } + + veclist = nreverse (veclist); + + /* Generate the name for the vtable list. */ + name = alloca (strlen (VLIST_NAME_FORMAT) + + TYPE_ASSEMBLER_NAME_LENGTH (t) + 2); + sprintf (name, VLIST_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (t)); + + /* Build the type of the list. */ + len = list_length (veclist) - 1; + if (len < 0) + /* If this class has virtual bases without virtual methods, make a + single zero-entry in the array. This avoids zero-sized objects. */ + len++; + type = build_cplus_array_type (vtbl_ptr_type_node, + build_index_type (size_int (len))); + + + /* Produce a new decl holding the list. */ + decl = build_lang_decl (VAR_DECL, get_identifier (name), type); + TREE_STATIC (decl) = 1; + TREE_READONLY (decl) = 1; + decl = pushdecl_top_level (decl); + import_export_vtable (decl, t, 0); + DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, veclist); + + DECL_ARTIFICIAL (decl) = 1; + /* This tells finish_file et.al. that this is related to virtual + tables. There is currently no way to distinguish between vtables + and vlists, other than the name of the decl. */ + DECL_VIRTUAL_P (decl) = 1; + + /* Output the array. */ + cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); + + /* Set the class context after finishing, so that finish thinks this + is an unrelated global, and then finish_vtable_vardecl knows what + class this is related to. */ + DECL_CONTEXT (decl) = t; + } + /* Check for things that are invalid. There are probably plenty of other things we should check for also. */ *************** finish_struct_1 (t, warn_anon) *** 4069,4074 **** --- 4417,4426 ---- /* Make the rtl for any new vtables we have created, and unmark the base types we marked. */ finish_vtbls (TYPE_BINFO (t), 1, t); + /* If we use thunks, and have virtual bases, we might need to emit + additional vtables. */ + if (flag_vtable_thunks && TYPE_USES_PVBASES (t)) + finish_ctor_vtables (t); hack_incomplete_structures (t); #if 0 diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/cp-tree.h gcc-2.95.3/gcc/cp/cp-tree.h *** gcc-2.95.2/gcc/cp/cp-tree.h Fri Aug 20 00:29:44 1999 --- gcc-2.95.3/gcc/cp/cp-tree.h Thu Apr 20 06:13:25 2000 *************** Boston, MA 02111-1307, USA. */ *** 52,58 **** 4: BINFO_NEW_VTABLE_MARKED. TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). ! 5: Not used. 6: Not used. Usage of TYPE_LANG_FLAG_?: --- 52,58 ---- 4: BINFO_NEW_VTABLE_MARKED. TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). ! 5: TYPE_USES_PVBASES (in a class TYPE). 6: Not used. Usage of TYPE_LANG_FLAG_?: *************** extern int write_virtuals; *** 503,510 **** /* True for more efficient but incompatible (not fully tested) vtable implementation (using thunks). ! 0 is old behavior; 1 is new behavior. */ ! extern int flag_vtable_thunks; /* INTERFACE_ONLY nonzero means that we are in an "interface" section of the compiler. INTERFACE_UNKNOWN nonzero means --- 503,511 ---- /* True for more efficient but incompatible (not fully tested) vtable implementation (using thunks). ! 0 is old behavior; 1 is new behavior; 3 adds vlist arguments; ! 2 is 3 plus backwards-compatibility to 1. */ ! extern int flag_vtable_thunks, flag_vtable_thunks_compat; /* INTERFACE_ONLY nonzero means that we are in an "interface" section of the compiler. INTERFACE_UNKNOWN nonzero means *************** struct lang_type *** 889,894 **** --- 890,899 ---- hierarchy, then we can use more efficient search techniques. */ #define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE)) + /* Nonzero means that this _CLASSTYPE uses polymorphic virtual bases. + This flag is set only when we use vtable thunks. */ + #define TYPE_USES_PVBASES(NODE) (TREE_LANG_FLAG_5(NODE)) + /* Vector member functions defined in this class. Each element is either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All functions with the same name end up in the same slot. The first *************** struct lang_type *** 965,971 **** /* The number of virtual functions defined for this _CLASSTYPE node. */ #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize) ! /* The virtual base classes that this type uses. */ #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases) /* The virtual function pointer fields that this type contains. */ #define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields) --- 970,976 ---- /* The number of virtual functions defined for this _CLASSTYPE node. */ #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize) ! /* The list of binfos of virtual base classes that this type uses. */ #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases) /* The virtual function pointer fields that this type contains. */ #define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields) *************** struct lang_decl_flags *** 1165,1186 **** unsigned static_function : 1; unsigned const_memfunc : 1; unsigned volatile_memfunc : 1; - unsigned abstract_virtual : 1; unsigned permanent_attr : 1 ; ! unsigned constructor_for_vbase_attr : 1; unsigned mutable_flag : 1; unsigned is_default_implementation : 1; unsigned saved_inline : 1; unsigned use_template : 2; - unsigned nonconverting : 1; unsigned declared_inline : 1; unsigned not_really_extern : 1; unsigned needs_final_overrider : 1; unsigned bitfield : 1; unsigned defined_in_class : 1; ! unsigned dummy : 4; tree access; tree context; --- 1170,1190 ---- unsigned static_function : 1; unsigned const_memfunc : 1; unsigned volatile_memfunc : 1; unsigned abstract_virtual : 1; unsigned permanent_attr : 1 ; ! unsigned mutable_flag : 1; unsigned is_default_implementation : 1; unsigned saved_inline : 1; unsigned use_template : 2; unsigned nonconverting : 1; unsigned declared_inline : 1; unsigned not_really_extern : 1; unsigned needs_final_overrider : 1; unsigned bitfield : 1; unsigned defined_in_class : 1; ! unsigned constructor_for_vbase_attr : 2; ! unsigned dummy : 3; tree access; tree context; *************** struct lang_decl *** 1226,1234 **** #define DECL_CONV_FN_P(NODE) \ (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE))) ! /* For FUNCTION_DECLs: nonzero means that this function is a constructor for an object with virtual baseclasses. */ ! #define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr) /* Non-zero for a FUNCTION_DECL that declares a type-info function. */ #define DECL_TINFO_FN_P(NODE) \ --- 1230,1264 ---- #define DECL_CONV_FN_P(NODE) \ (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE))) ! #define CONSTRUCTOR_FOR_VBASE 1 ! #define CONSTRUCTOR_FOR_PVBASE 2 ! #define DESTRUCTOR_FOR_PVBASE 3 ! ! /* For FUNCTION_DECLs: nonzero means that this function is a con/destructor for an object with virtual baseclasses. */ ! #define DECL_CONSTRUCTOR_FOR_VBASE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr) ! ! /* Nonzero means that this function is a constructor for an object ! with virtual baseclasses. */ ! #define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) \ ! (DECL_CONSTRUCTOR_FOR_VBASE (NODE) == CONSTRUCTOR_FOR_VBASE) ! ! /* Nonzero means that this function is a constructor for an object ! with virtual baseclasses which have virtual functions. */ ! #define DECL_CONSTRUCTOR_FOR_PVBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr == CONSTRUCTOR_FOR_PVBASE) ! ! /* Nonzero means that this function is a destructor for an object ! with virtual baseclasses which have virtual functions. */ ! #define DECL_DESTRUCTOR_FOR_PVBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr == DESTRUCTOR_FOR_PVBASE) ! ! /* Nonzero means that this function is a wrapper around a PVBASE ctor. */ ! #define DECL_VLIST_CTOR_WRAPPER_P(NODE) \ ! (DECL_CONSTRUCTOR_FOR_VBASE_P (NODE) && DECL_VLIST_CTOR_WRAPPED (NODE)\ ! && TREE_CODE (DECL_VLIST_CTOR_WRAPPED (NODE)) == FUNCTION_DECL \ ! && DECL_CONSTRUCTOR_FOR_PVBASE_P (DECL_VLIST_CTOR_WRAPPED (NODE))) ! ! /* Refers to original function that NODE wraps. */ ! #define DECL_VLIST_CTOR_WRAPPED(NODE) DECL_MEMFUNC_POINTER_TO (NODE) /* Non-zero for a FUNCTION_DECL that declares a type-info function. */ #define DECL_TINFO_FN_P(NODE) \ *************** extern tree delta2_identifier; *** 2168,2173 **** --- 2198,2204 ---- extern tree pfn_or_delta2_identifier; extern tree tag_identifier; extern tree vt_off_identifier; + extern tree in_charge_identifier; /* A node that is a list (length 1) of error_mark_nodes. */ extern tree error_mark_list; *************** extern tree class_type_node, record_type *** 2177,2182 **** --- 2208,2215 ---- extern tree unknown_type_node; extern tree opaque_type_node, signature_type_node; + extern tree vlist_identifier, vlist_type_node, vlist_zero_node; + /* Node for "pointer to (virtual) function". This may be distinct from ptr_type_node so gdb can distinguish them. */ #define vfunc_ptr_type_node \ *************** extern int current_function_parms_stored *** 2292,2297 **** --- 2325,2332 ---- #define AUTO_TEMP_FORMAT "_$tmp_%d" #define VTABLE_BASE "$vb" #define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt$%s") + #define VCTABLE_NAME "__vc$" + #define VLIST_NAME_FORMAT "__vl$%s" #define VFIELD_BASE "$vf" #define VFIELD_NAME "_vptr$" #define VFIELD_NAME_FORMAT "_vptr$%s" *************** extern int current_function_parms_stored *** 2314,2319 **** --- 2349,2356 ---- #define AUTO_TEMP_FORMAT "_.tmp_%d" #define VTABLE_BASE ".vb" #define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt.%s") + #define VCTABLE_NAME "__vc." + #define VLIST_NAME_FORMAT "__vl.%s" #define VFIELD_BASE ".vf" #define VFIELD_NAME "_vptr." #define VFIELD_NAME_FORMAT "_vptr.%s" *************** extern int current_function_parms_stored *** 2346,2351 **** --- 2383,2390 ---- #define VTABLE_NAME_P(ID_NODE) \ (!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \ sizeof (VTABLE_NAME) - 1)) + #define VCTABLE_NAME "__vc_" + #define VLIST_NAME_FORMAT "__vl_%s" #define VFIELD_BASE "__vfb" #define VFIELD_NAME "__vptr_" #define VFIELD_NAME_P(ID_NODE) \ *************** extern int current_function_parms_stored *** 2379,2384 **** --- 2418,2426 ---- #define DTOR_NAME "__dt" #define IN_CHARGE_NAME "__in_chrg" + #define VLIST_NAME "__vlist" + #define VLIST1_NAME "__vlist1" + #define VLIST_TYPE_NAME "6_Vlist" #define VTBL_PTR_TYPE "__vtbl_ptr_type" #define VTABLE_DELTA_NAME "__delta" *************** extern tree current_class_name; /* IDENT *** 2556,2561 **** --- 2598,2605 ---- as well as the space of member functions. LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already in the parameter list. + LOOKUP_HAS_VLIST means that the "vlist" variable is already in + the parameter list. LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried. DIRECT_BIND means that if a temporary is created, it should be created so that it lives as long as the current variable bindings; otherwise it *************** extern tree current_class_name; /* IDENT *** 2594,2599 **** --- 2638,2644 ---- #define LOOKUP_PREFER_NAMESPACES (4096) #define LOOKUP_PREFER_BOTH (6144) #define LOOKUP_TEMPLATES_EXPECTED (8192) + #define LOOKUP_HAS_VLIST (16384) #define LOOKUP_NAMESPACES_ONLY(f) \ (((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES)) *************** extern tree build_x_delete PROTO((tree *** 3051,3056 **** --- 3096,3103 ---- extern tree build_delete PROTO((tree, tree, tree, int, int)); extern tree build_vbase_delete PROTO((tree, tree)); extern tree build_vec_delete PROTO((tree, tree, tree, tree, int)); + extern tree build_base_dtor_call PROTO((tree, tree, tree)); + extern void init_vlist PROTO((tree)); /* in input.c */ *************** extern tree build_decl_overload_real *** 3117,3129 **** extern void set_mangled_name_for_decl PROTO((tree)); extern tree build_typename_overload PROTO((tree)); extern tree build_overload_with_type PROTO((tree, tree)); ! extern tree build_destructor_name PROTO((tree)); extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree)); extern tree hack_identifier PROTO((tree, tree)); extern tree make_thunk PROTO((tree, int)); extern void emit_thunk PROTO((tree)); extern void synthesize_method PROTO((tree)); extern tree get_id_2 PROTO((char *, tree)); /* in pt.c */ extern void check_template_shadow PROTO ((tree)); --- 3164,3178 ---- extern void set_mangled_name_for_decl PROTO((tree)); extern tree build_typename_overload PROTO((tree)); extern tree build_overload_with_type PROTO((tree, tree)); ! extern tree build_destructor_name PROTO((tree, int)); extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree)); extern tree hack_identifier PROTO((tree, tree)); extern tree make_thunk PROTO((tree, int)); extern void emit_thunk PROTO((tree)); extern void synthesize_method PROTO((tree)); extern tree get_id_2 PROTO((char *, tree)); + extern tree get_vlist_vtable_id PROTO((tree, tree)); + /* in pt.c */ extern void check_template_shadow PROTO ((tree)); *************** extern tree get_tinfo_fn_dynamic PROTO( *** 3200,3205 **** --- 3249,3255 ---- extern tree build_typeid PROTO((tree)); extern tree build_x_typeid PROTO((tree)); extern tree get_tinfo_fn PROTO((tree)); + extern tree get_tinfo_fn_unused PROTO((tree)); extern tree get_typeid PROTO((tree)); extern tree get_typeid_1 PROTO((tree)); extern tree build_dynamic_cast PROTO((tree, tree)); diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/decl.c gcc-2.95.3/gcc/cp/decl.c *** gcc-2.95.2/gcc/cp/decl.c Mon Aug 9 01:28:33 1999 --- gcc-2.95.3/gcc/cp/decl.c Sat Jun 10 01:06:42 2000 *************** static tree record_builtin_java_type PRO *** 188,193 **** --- 188,195 ---- static const char *tag_name PROTO((enum tag_types code)); static void find_class_binding_level PROTO((void)); static struct binding_level *innermost_nonclass_level PROTO((void)); + static void finish_dtor PROTO((void)); + static void finish_ctor PROTO((int)); static tree poplevel_class PROTO((void)); static void warn_about_implicit_typename_lookup PROTO((tree, tree)); static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *)); *************** tree __ptr_desc_array_type, __attr_dec_a *** 335,340 **** --- 337,351 ---- tree __ptmf_desc_array_type, __ptmd_desc_array_type; #endif + /* This is the identifier __vlist. */ + tree vlist_identifier; + + /* This is the type _Vlist = vtable_entry_type**. */ + tree vlist_type_node; + + /* A null pointer of type _Vlist. */ + tree vlist_zero_node; + /* Indicates that there is a type value in some namespace, although that is not necessarily in scope at the moment. */ *************** init_decl_processing () *** 6283,6288 **** --- 6294,6300 ---- this_identifier = get_identifier (THIS_NAME); in_charge_identifier = get_identifier (IN_CHARGE_NAME); + vlist_identifier = get_identifier (VLIST_NAME); ctor_identifier = get_identifier (CTOR_NAME); dtor_identifier = get_identifier (DTOR_NAME); pfn_identifier = get_identifier (VTABLE_PFN_NAME); *************** init_decl_processing () *** 6510,6515 **** --- 6522,6528 ---- #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); *************** init_decl_processing () *** 6849,6854 **** --- 6862,6877 ---- layout_type (vtbl_ptr_type_node); record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node); + if (flag_vtable_thunks) + { + /* We need vlists only when using thunks; otherwise leave them + as NULL_TREE. That way, it doesn't get into the way of the + mangling. */ + vlist_type_node = build_pointer_type (vtbl_ptr_type_node); + vlist_zero_node = build_int_2 (0, 0); + TREE_TYPE (vlist_zero_node) = vlist_type_node; + } + /* Simplify life by making a "sigtable_entry_type". Give its fields names so that the debugger can use them. */ *************** grokfndecl (ctype, type, declarator, ori *** 8944,8952 **** --- 8967,8978 ---- template_count, 2 * (funcdef_flag != 0) + 4 * (friendp != 0)); + if (decl == error_mark_node) return NULL_TREE; + maybe_vlist_ctor_wrapper (decl, funcdef_flag); + if ((! TYPE_FOR_JAVA (ctype) || check_java_method (decl)) && check) { *************** grokdeclarator (declarator, declspecs, d *** 11386,11391 **** --- 11412,11421 ---- if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (decl))) arg_types = TREE_CHAIN (arg_types); + /* And the `vlist' argument. */ + if (TYPE_USES_PVBASES (DECL_CONTEXT (decl))) + arg_types = TREE_CHAIN (arg_types); + if (arg_types == void_list_node || (arg_types && TREE_CHAIN (arg_types) *************** replace_defarg (arg, init) *** 12080,12085 **** --- 12110,12118 ---- TREE_PURPOSE (arg) = init; } + /* Return 1 if D copies its arguments. This is used to test for copy + constructors and copy assignment operators. */ + int copy_args_p (d) tree d; *************** copy_args_p (d) *** 12087,12093 **** tree t = FUNCTION_ARG_CHAIN (d); if (DECL_CONSTRUCTOR_P (d) && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d))) ! t = TREE_CHAIN (t); if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t))) == DECL_CLASS_CONTEXT (d)) --- 12120,12131 ---- tree t = FUNCTION_ARG_CHAIN (d); if (DECL_CONSTRUCTOR_P (d) && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d))) ! { ! t = TREE_CHAIN (t); ! if (TYPE_USES_PVBASES (DECL_CONTEXT (d))) ! t = TREE_CHAIN (t); ! } ! if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t))) == DECL_CLASS_CONTEXT (d)) *************** grok_ctor_properties (ctype, decl) *** 12117,12123 **** added to any ctor so we can tell if the class has been initialized yet. This could screw things up in this function, so we deliberately ignore the leading int if we're in that situation. */ ! if (TYPE_USES_VIRTUAL_BASECLASSES (ctype)) { my_friendly_assert (parmtypes && TREE_VALUE (parmtypes) == integer_type_node, --- 12155,12162 ---- added to any ctor so we can tell if the class has been initialized yet. This could screw things up in this function, so we deliberately ignore the leading int if we're in that situation. */ ! if (TYPE_USES_VIRTUAL_BASECLASSES (ctype) ! && !CLASSTYPE_IS_TEMPLATE (ctype)) { my_friendly_assert (parmtypes && TREE_VALUE (parmtypes) == integer_type_node, *************** grok_ctor_properties (ctype, decl) *** 12126,12131 **** --- 12165,12181 ---- parmtype = TREE_VALUE (parmtypes); } + if (TYPE_USES_PVBASES (ctype)) + { + my_friendly_assert (parmtypes + && TREE_VALUE (parmtypes) == vlist_type_node, + 980529); + parmtypes = TREE_CHAIN (parmtypes); + parmtype = TREE_VALUE (parmtypes); + } + + maybe_vlist_ctor_wrapper (decl, 0); + /* [class.copy] A non-template constructor for class X is a copy constructor if *************** xref_basetypes (code_type_node, name, re *** 12923,12928 **** --- 12973,12988 ---- { TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; TYPE_USES_COMPLEX_INHERITANCE (ref) = 1; + /* The PVBASES flag is never set for templates; we know + only for instantiations whether the virtual bases are + polymorphic. */ + if (flag_vtable_thunks >= 2 && !CLASSTYPE_IS_TEMPLATE (ref)) + { + if (via_virtual && TYPE_VIRTUAL_P (basetype)) + TYPE_USES_PVBASES (ref) = 1; + else if (TYPE_USES_PVBASES (basetype)) + TYPE_USES_PVBASES (ref) = 1; + } } if (CLASS_TYPE_P (basetype)) *************** store_return_init (return_id, init) *** 13928,13933 **** --- 13988,14300 ---- } + /* Emit implicit code for a destructor. This is a subroutine of + finish_function. */ + + static void + finish_dtor () + { + tree binfo = TYPE_BINFO (current_class_type); + tree cond = integer_one_node; + tree exprstmt; + tree in_charge_node = lookup_name (in_charge_identifier, 0); + tree virtual_size; + int ok_to_optimize_dtor = 0; + int empty_dtor = get_last_insn () == last_dtor_insn; + rtx insns, last_parm_insn; + + if (current_function_assigns_this) + cond = build (NE_EXPR, boolean_type_node, + current_class_ptr, integer_zero_node); + else + { + int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type); + + /* If this destructor is empty, then we don't need to check + whether `this' is NULL in some cases. */ + if ((flag_this_is_variable & 1) == 0) + ok_to_optimize_dtor = 1; + else if (empty_dtor) + ok_to_optimize_dtor + = (n_baseclasses == 0 + || (n_baseclasses == 1 + && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0)))); + } + + /* If this has a vlist1 parameter, allocate the corresponding vlist + parameter. */ + if (DECL_DESTRUCTOR_FOR_PVBASE_P (current_function_decl)) + { + /* _Vlist __vlist; */ + tree vlist; + + mark_all_temps_used(); + vlist = pushdecl (build_decl (VAR_DECL, vlist_identifier, + vlist_type_node)); + TREE_USED (vlist) = 1; + DECL_ARTIFICIAL (vlist) = 1; + expand_decl (vlist); + expand_decl_init (vlist); + } + + /* These initializations might go inline. Protect + the binding level of the parms. */ + pushlevel (0); + expand_start_bindings (0); + + if (current_function_assigns_this) + { + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + } + + /* Generate the code to call destructor on base class. + If this destructor belongs to a class with virtual + functions, then set the virtual function table + pointer to represent the type of our base class. */ + + /* This side-effect makes call to `build_delete' generate the + code we have to have at the end of this destructor. + `build_delete' will set the flag again. */ + TYPE_HAS_DESTRUCTOR (current_class_type) = 0; + + /* These are two cases where we cannot delegate deletion. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) + || TYPE_GETS_REG_DELETE (current_class_type)) + exprstmt = build_delete + (current_class_type, current_class_ref, integer_zero_node, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); + else + exprstmt = build_delete + (current_class_type, current_class_ref, in_charge_node, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); + + /* If we did not assign to this, then `this' is non-zero at + the end of a destructor. As a special optimization, don't + emit test if this is an empty destructor. If it does nothing, + it does nothing. If it calls a base destructor, the base + destructor will perform the test. */ + + if (exprstmt != error_mark_node + && (TREE_CODE (exprstmt) != NOP_EXPR + || TREE_OPERAND (exprstmt, 0) != integer_zero_node + || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))) + { + expand_label (dtor_label); + if (cond != integer_one_node) + expand_start_cond (cond, 0); + if (exprstmt != void_zero_node) + /* Don't call `expand_expr_stmt' if we're not going to do + anything, since -Wall will give a diagnostic. */ + expand_expr_stmt (exprstmt); + + /* Run destructor on all virtual baseclasses. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + { + tree vbases = nreverse + (copy_list (CLASSTYPE_VBASECLASSES (current_class_type))); + expand_start_cond (build (BIT_AND_EXPR, integer_type_node, + in_charge_node, integer_two_node), 0); + while (vbases) + { + if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) + { + tree vb = get_vbase + (BINFO_TYPE (vbases), + TYPE_BINFO (current_class_type)); + + expand_expr_stmt + (build_base_dtor_call (current_class_ref, + vb, integer_zero_node)); + } + vbases = TREE_CHAIN (vbases); + } + expand_end_cond (); + } + + do_pending_stack_adjust (); + if (cond != integer_one_node) + expand_end_cond (); + } + + virtual_size = c_sizeof (current_class_type); + + /* At the end, call delete if that's what's requested. */ + + /* FDIS sez: At the point of definition of a virtual destructor + (including an implicit definition), non-placement operator + delete shall be looked up in the scope of the destructor's + class and if found shall be accessible and unambiguous. + + This is somewhat unclear, but I take it to mean that if the + class only defines placement deletes we don't do anything here. + So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain + for us if they ever try to delete one of these. */ + + if (TYPE_GETS_REG_DELETE (current_class_type) + || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + exprstmt = build_op_delete_call + (DELETE_EXPR, current_class_ptr, virtual_size, + LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); + else + exprstmt = NULL_TREE; + + if (exprstmt) + { + cond = build (BIT_AND_EXPR, integer_type_node, + in_charge_node, integer_one_node); + expand_start_cond (cond, 0); + expand_expr_stmt (exprstmt); + expand_end_cond (); + } + + /* End of destructor. */ + expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0); + poplevel (getdecls () != NULL_TREE, 0, 0); + + /* Back to the top of destructor. */ + /* Don't execute destructor code if `this' is NULL. */ + + start_sequence (); + + /* If we need thunk-style vlists, initialize them if the caller did + not pass them. This requires a new temporary. The generated code + looks like + if (!(__in_charge & 4)) + __vlist = __vl. + sizeof(__vl.); + else + __vlist = __vlist1; + */ + if (TYPE_USES_PVBASES (current_class_type)) + { + tree vlist = lookup_name (vlist_identifier, 0); + tree vlist1 = lookup_name (get_identifier (VLIST1_NAME), 0); + cond = build (BIT_AND_EXPR, integer_type_node, + in_charge_node, build_int_2 (4, 0)); + cond = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond); + expand_start_cond (cond, 0); + init_vlist (current_class_type); + expand_start_else (); + expand_expr_stmt (build_modify_expr (vlist, NOP_EXPR, vlist1)); + expand_end_cond (); + } + + /* If the dtor is empty, and we know there is not possible way we + could use any vtable entries, before they are possibly set by + a base class dtor, we don't have to setup the vtables, as we + know that any base class dtoring will set up any vtables it + needs. We avoid MI, because one base class dtor can do a + virtual dispatch to an overridden function that would need to + have a non-related vtable set up, we cannot avoid setting up + vtables in that case. We could change this to see if there is + just one vtable. */ + if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type)) + { + /* Make all virtual function table pointers in non-virtual base + classes point to CURRENT_CLASS_TYPE's virtual function + tables. */ + expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr); + + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr); + } + + if (! ok_to_optimize_dtor) + { + cond = build_binary_op (NE_EXPR, + current_class_ptr, integer_zero_node); + expand_start_cond (cond, 0); + } + + insns = get_insns (); + end_sequence (); + + last_parm_insn = get_first_nonparm_insn (); + if (last_parm_insn == NULL_RTX) + last_parm_insn = get_last_insn (); + else + last_parm_insn = previous_insn (last_parm_insn); + + emit_insns_after (insns, last_parm_insn); + + if (! ok_to_optimize_dtor) + expand_end_cond (); + } + + /* Emit implicit code for a constructor. This is a subroutine of + finish_function. CALL_POPLEVEL is the same variable in + finish_function. */ + + static void + finish_ctor (call_poplevel) + int call_poplevel; + { + register tree fndecl = current_function_decl; + tree cond = NULL_TREE, thenclause = NULL_TREE; + rtx insns; + tree decls; + + /* Allow constructor for a type to get a new instance of the object + using `build_new'. */ + tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type); + CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE; + + if (flag_this_is_variable > 0) + { + cond = build_binary_op (EQ_EXPR, current_class_ptr, integer_zero_node); + thenclause = + build_modify_expr (current_class_ptr, NOP_EXPR, + build_new (NULL_TREE, current_class_type, + void_type_node, 0)); + } + + CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals; + + start_sequence (); + + if (flag_this_is_variable > 0) + { + expand_start_cond (cond, 0); + expand_expr_stmt (thenclause); + expand_end_cond (); + } + + /* Emit insns from `emit_base_init' which sets up virtual + function table pointer(s). */ + if (base_init_expr) + { + expand_expr_stmt (base_init_expr); + base_init_expr = NULL_TREE; + } + + insns = get_insns (); + end_sequence (); + + /* This is where the body of the constructor begins. */ + + emit_insns_after (insns, last_parm_cleanup_insn); + + end_protect_partials (); + + /* This is where the body of the constructor ends. */ + expand_label (ctor_label); + ctor_label = NULL_TREE; + + if (call_poplevel) + { + decls = getdecls (); + expand_end_bindings (decls, decls != NULL_TREE, 0); + poplevel (decls != NULL_TREE, 1, 0); + } + + /* c_expand_return knows to return 'this' from a constructor. */ + c_expand_return (NULL_TREE); + + current_function_assigns_this = 0; + current_function_just_assigned_this = 0; + } + + /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage for the function definition. *************** finish_function (lineno, flags, nested) *** 13956,13962 **** { register tree fndecl = current_function_decl; tree fntype, ctype = NULL_TREE; - rtx last_parm_insn, insns; /* Label to use if this function is supposed to return a value. */ tree no_return_label = NULL_TREE; tree decls = NULL_TREE; --- 14323,14328 ---- *************** finish_function (lineno, flags, nested) *** 14018,14208 **** do_pending_stack_adjust (); if (dtor_label) ! { ! tree binfo = TYPE_BINFO (current_class_type); ! tree cond = integer_one_node; ! tree exprstmt; ! tree in_charge_node = lookup_name (in_charge_identifier, 0); ! tree virtual_size; ! int ok_to_optimize_dtor = 0; ! int empty_dtor = get_last_insn () == last_dtor_insn; ! ! if (current_function_assigns_this) ! cond = build (NE_EXPR, boolean_type_node, ! current_class_ptr, integer_zero_node); ! else ! { ! int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type); ! ! /* If this destructor is empty, then we don't need to check ! whether `this' is NULL in some cases. */ ! if ((flag_this_is_variable & 1) == 0) ! ok_to_optimize_dtor = 1; ! else if (empty_dtor) ! ok_to_optimize_dtor ! = (n_baseclasses == 0 ! || (n_baseclasses == 1 ! && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0)))); ! } ! ! /* These initializations might go inline. Protect ! the binding level of the parms. */ ! pushlevel (0); ! expand_start_bindings (0); ! ! if (current_function_assigns_this) ! { ! current_function_assigns_this = 0; ! current_function_just_assigned_this = 0; ! } ! ! /* Generate the code to call destructor on base class. ! If this destructor belongs to a class with virtual ! functions, then set the virtual function table ! pointer to represent the type of our base class. */ ! ! /* This side-effect makes call to `build_delete' generate the ! code we have to have at the end of this destructor. ! `build_delete' will set the flag again. */ ! TYPE_HAS_DESTRUCTOR (current_class_type) = 0; ! ! /* These are two cases where we cannot delegate deletion. */ ! if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) ! || TYPE_GETS_REG_DELETE (current_class_type)) ! exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node, ! LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); ! else ! exprstmt = build_delete (current_class_type, current_class_ref, in_charge_node, ! LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0); ! ! /* If we did not assign to this, then `this' is non-zero at ! the end of a destructor. As a special optimization, don't ! emit test if this is an empty destructor. If it does nothing, ! it does nothing. If it calls a base destructor, the base ! destructor will perform the test. */ ! ! if (exprstmt != error_mark_node ! && (TREE_CODE (exprstmt) != NOP_EXPR ! || TREE_OPERAND (exprstmt, 0) != integer_zero_node ! || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))) ! { ! expand_label (dtor_label); ! if (cond != integer_one_node) ! expand_start_cond (cond, 0); ! if (exprstmt != void_zero_node) ! /* Don't call `expand_expr_stmt' if we're not going to do ! anything, since -Wall will give a diagnostic. */ ! expand_expr_stmt (exprstmt); ! ! /* Run destructor on all virtual baseclasses. */ ! if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) ! { ! tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type))); ! expand_start_cond (build (BIT_AND_EXPR, integer_type_node, ! in_charge_node, integer_two_node), 0); ! while (vbases) ! { ! if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) ! { ! tree vb = get_vbase ! (BINFO_TYPE (vbases), ! TYPE_BINFO (current_class_type)); ! expand_expr_stmt ! (build_scoped_method_call ! (current_class_ref, vb, dtor_identifier, ! build_expr_list (NULL_TREE, integer_zero_node))); ! } ! vbases = TREE_CHAIN (vbases); ! } ! expand_end_cond (); ! } ! ! do_pending_stack_adjust (); ! if (cond != integer_one_node) ! expand_end_cond (); ! } ! ! virtual_size = c_sizeof (current_class_type); ! ! /* At the end, call delete if that's what's requested. */ ! ! /* FDIS sez: At the point of definition of a virtual destructor ! (including an implicit definition), non-placement operator ! delete shall be looked up in the scope of the destructor's ! class and if found shall be accessible and unambiguous. ! ! This is somewhat unclear, but I take it to mean that if the ! class only defines placement deletes we don't do anything here. ! So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain ! for us if they ever try to delete one of these. */ ! ! if (TYPE_GETS_REG_DELETE (current_class_type) ! || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) ! exprstmt = build_op_delete_call ! (DELETE_EXPR, current_class_ptr, virtual_size, ! LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); ! else ! exprstmt = NULL_TREE; ! ! if (exprstmt) ! { ! cond = build (BIT_AND_EXPR, integer_type_node, ! in_charge_node, integer_one_node); ! expand_start_cond (cond, 0); ! expand_expr_stmt (exprstmt); ! expand_end_cond (); ! } ! ! /* End of destructor. */ ! expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0); ! poplevel (getdecls () != NULL_TREE, 0, 0); ! ! /* Back to the top of destructor. */ ! /* Don't execute destructor code if `this' is NULL. */ ! ! start_sequence (); ! ! /* If the dtor is empty, and we know there is not possible way we ! could use any vtable entries, before they are possibly set by ! a base class dtor, we don't have to setup the vtables, as we ! know that any base class dtoring will set up any vtables it ! needs. We avoid MI, because one base class dtor can do a ! virtual dispatch to an overridden function that would need to ! have a non-related vtable set up, we cannot avoid setting up ! vtables in that case. We could change this to see if there is ! just one vtable. */ ! if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type)) ! { ! /* Make all virtual function table pointers in non-virtual base ! classes point to CURRENT_CLASS_TYPE's virtual function ! tables. */ ! expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr); ! ! if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) ! expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr); ! } ! ! if (! ok_to_optimize_dtor) ! { ! cond = build_binary_op (NE_EXPR, ! current_class_ptr, integer_zero_node); ! expand_start_cond (cond, 0); ! } ! ! insns = get_insns (); ! end_sequence (); ! ! last_parm_insn = get_first_nonparm_insn (); ! if (last_parm_insn == NULL_RTX) ! last_parm_insn = get_last_insn (); ! else ! last_parm_insn = previous_insn (last_parm_insn); ! ! emit_insns_after (insns, last_parm_insn); ! ! if (! ok_to_optimize_dtor) ! expand_end_cond (); ! } else if (current_function_assigns_this) { /* Does not need to call emit_base_init, because --- 14384,14390 ---- do_pending_stack_adjust (); if (dtor_label) ! finish_dtor (); else if (current_function_assigns_this) { /* Does not need to call emit_base_init, because *************** finish_function (lineno, flags, nested) *** 14232,14298 **** current_function_just_assigned_this = 0; base_init_expr = NULL_TREE; } ! else if (DECL_CONSTRUCTOR_P (fndecl)) ! { ! tree cond = NULL_TREE, thenclause = NULL_TREE; ! /* Allow constructor for a type to get a new instance of the object ! using `build_new'. */ ! tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type); ! CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE; ! ! if (flag_this_is_variable > 0) ! { ! cond = build_binary_op (EQ_EXPR, ! current_class_ptr, integer_zero_node); ! thenclause = build_modify_expr (current_class_ptr, NOP_EXPR, ! build_new (NULL_TREE, current_class_type, void_type_node, 0)); ! } ! ! CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals; ! ! start_sequence (); ! ! if (flag_this_is_variable > 0) ! { ! expand_start_cond (cond, 0); ! expand_expr_stmt (thenclause); ! expand_end_cond (); ! } ! ! /* Emit insns from `emit_base_init' which sets up virtual ! function table pointer(s). */ ! if (base_init_expr) ! { ! expand_expr_stmt (base_init_expr); ! base_init_expr = NULL_TREE; ! } ! ! insns = get_insns (); ! end_sequence (); ! ! /* This is where the body of the constructor begins. */ ! ! emit_insns_after (insns, last_parm_cleanup_insn); ! ! end_protect_partials (); ! ! /* This is where the body of the constructor ends. */ ! expand_label (ctor_label); ! ctor_label = NULL_TREE; ! ! if (call_poplevel) ! { ! decls = getdecls (); ! expand_end_bindings (decls, decls != NULL_TREE, 0); ! poplevel (decls != NULL_TREE, 1, 0); ! } ! ! /* c_expand_return knows to return 'this' from a constructor. */ ! c_expand_return (NULL_TREE); ! ! current_function_assigns_this = 0; ! current_function_just_assigned_this = 0; ! } else if (DECL_MAIN_P (fndecl)) { /* Make it so that `main' always returns 0 by default. */ --- 14414,14422 ---- current_function_just_assigned_this = 0; base_init_expr = NULL_TREE; } ! else if (DECL_CONSTRUCTOR_P (fndecl) ! && !DECL_VLIST_CTOR_WRAPPER_P (fndecl)) ! finish_ctor (call_poplevel); else if (DECL_MAIN_P (fndecl)) { /* Make it so that `main' always returns 0 by default. */ diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/decl2.c gcc-2.95.3/gcc/cp/decl2.c *** gcc-2.95.2/gcc/cp/decl2.c Fri Aug 20 00:29:45 1999 --- gcc-2.95.3/gcc/cp/decl2.c Sat Jun 10 01:06:44 2000 *************** int warn_long_long = 1; *** 224,237 **** int warn_ctor_dtor_privacy = 1; ! /* True if we want to implement vtables using "thunks". ! The default is off. */ #ifndef DEFAULT_VTABLE_THUNKS #define DEFAULT_VTABLE_THUNKS 0 #endif int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS; /* True if we want to deal with repository information. */ int flag_use_repository; --- 224,244 ---- int warn_ctor_dtor_privacy = 1; ! /* 1 or 2 if we want to implement vtables using "thunks". ! The default is off. Version 1 indicates "old" implementation; ! Version 2 passes the __vlist argument in pvbase cases. */ #ifndef DEFAULT_VTABLE_THUNKS #define DEFAULT_VTABLE_THUNKS 0 #endif int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS; + #if DEFAULT_VTABLE_THUNKS == 2 + int flag_vtable_thunks_compat = 1; + #else + int flag_vtable_thunks_compat = 0; + #endif + /* True if we want to deal with repository information. */ int flag_use_repository; *************** lang_decode_option (argc, argv) *** 633,638 **** --- 640,670 ---- found = 1; cp_deprecated ("-fexternal-templates"); } + else if (!strncmp (p, "vtable-thunks", 13)) + { + if (p[13] == '=') + { + flag_vtable_thunks = + read_integral_parameter (p+14, p, 1); + } + else + { + /* If the machine file has a default setting, use that + for -fvtable-thunks. Otherwise, set it to version + 2. */ + #if DEFAULT_VTABLE_THUNKS + flag_vtable_thunks = DEFAULT_VTABLE_THUNKS; + #else + flag_vtable_thunks = 1; + #endif + } + if (flag_vtable_thunks == 2) + /* v2 is a compatibility mode between v1 and v3. */ + flag_vtable_thunks_compat = 1; + else if(flag_vtable_thunks == 3) + flag_vtable_thunks_compat = 0; + found = 1; + } else if (!strcmp (p, "handle-signatures")) { flag_handle_signatures = 1; *************** lang_decode_option (argc, argv) *** 644,650 **** flag_new_abi = 1; flag_do_squangling = 1; flag_honor_std = 1; ! flag_vtable_thunks = 1; } else if (!strcmp (p, "no-new-abi")) { --- 676,682 ---- flag_new_abi = 1; flag_do_squangling = 1; flag_honor_std = 1; ! flag_vtable_thunks = 2; } else if (!strcmp (p, "no-new-abi")) { *************** grok_x_components (specs) *** 917,933 **** This function adds the "in-charge" flag to member function FN if appropriate. It is called from grokclassfn and tsubst. ! FN must be either a constructor or destructor. */ void maybe_retrofit_in_chrg (fn) tree fn; { tree basetype, arg_types, parms, parm, fntype; if (DECL_CONSTRUCTOR_P (fn) && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn)) ! && ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn)) /* OK */; else if (! DECL_CONSTRUCTOR_P (fn) && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE) --- 949,975 ---- This function adds the "in-charge" flag to member function FN if appropriate. It is called from grokclassfn and tsubst. ! FN must be either a constructor or destructor. ! ! For vtable thunks, types with polymorphic virtual bases need an ! additional "vlist" argument which is an array of virtual tables. ! In addition, if backwards-compatibility to v1 thunks is requested, ! a wrapper constructor may be needed as well. */ void maybe_retrofit_in_chrg (fn) tree fn; { tree basetype, arg_types, parms, parm, fntype; + tree wrapper; + + if (CLASSTYPE_IS_TEMPLATE (DECL_CLASS_CONTEXT (fn))) + /* Never retrofit arguments on template methods. */ + return; if (DECL_CONSTRUCTOR_P (fn) && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn)) ! && DECL_CONSTRUCTOR_FOR_VBASE (fn) == 0) /* OK */; else if (! DECL_CONSTRUCTOR_P (fn) && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE) *************** maybe_retrofit_in_chrg (fn) *** 936,942 **** return; if (DECL_CONSTRUCTOR_P (fn)) ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1; /* First add it to DECL_ARGUMENTS... */ parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); --- 978,1018 ---- return; if (DECL_CONSTRUCTOR_P (fn)) ! { ! if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn))) ! { ! DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_PVBASE; ! if (flag_vtable_thunks_compat && varargs_function_p (fn)) ! sorry ("-fvtable-thunks=2 for vararg constructor", fn); ! } ! else ! DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_VBASE; ! } ! else if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn))) ! DECL_CONSTRUCTOR_FOR_VBASE (fn) = DESTRUCTOR_FOR_PVBASE; ! ! /* Retrieve the arguments, because it is potentially modified twice. */ ! arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); ! basetype = TREE_TYPE (TREE_VALUE (arg_types)); ! arg_types = TREE_CHAIN (arg_types); ! ! if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fn) ! || DECL_DESTRUCTOR_FOR_PVBASE_P (fn)) ! { ! /* Add the __vlist argument first. See __in_chrg below. */ ! tree id = vlist_identifier; ! if (DECL_DESTRUCTOR_FOR_PVBASE_P (fn)) ! id = get_identifier (VLIST1_NAME); ! parm = build_decl (PARM_DECL, id, vlist_type_node); ! SET_DECL_ARTIFICIAL (parm); ! DECL_ARG_TYPE (parm) = vlist_type_node; ! parms = DECL_ARGUMENTS (fn); ! /* Add it after 'this'. */ ! TREE_CHAIN (parm) = TREE_CHAIN (parms); ! TREE_CHAIN (parms) = parm; ! ! arg_types = hash_tree_chain (vlist_type_node, arg_types); ! } /* First add it to DECL_ARGUMENTS... */ parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); *************** maybe_retrofit_in_chrg (fn) *** 949,957 **** TREE_CHAIN (parms) = parm; /* ...and then to TYPE_ARG_TYPES. */ ! arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); ! basetype = TREE_TYPE (TREE_VALUE (arg_types)); ! arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types)); fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), arg_types); if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) --- 1025,1031 ---- TREE_CHAIN (parms) = parm; /* ...and then to TYPE_ARG_TYPES. */ ! arg_types = hash_tree_chain (integer_type_node, arg_types); fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), arg_types); if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) *************** grokclassfn (ctype, function, flags, qua *** 1042,1048 **** if (flags == DTOR_FLAG) { ! DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype); TYPE_HAS_DESTRUCTOR (ctype) = 1; } else --- 1116,1123 ---- if (flags == DTOR_FLAG) { ! DECL_ASSEMBLER_NAME (function) = ! build_destructor_name (ctype, DECL_DESTRUCTOR_FOR_PVBASE_P (function)); TYPE_HAS_DESTRUCTOR (ctype) = 1; } else *************** void *** 2485,2493 **** maybe_make_one_only (decl) tree decl; { ! /* This is not necessary on targets that support weak symbols, because ! the implicit instantiations will defer to the explicit one. */ ! if (! supports_one_only () || SUPPORTS_WEAK) return; /* We can't set DECL_COMDAT on functions, or finish_file will think --- 2560,2572 ---- maybe_make_one_only (decl) tree decl; { ! /* We used to say that this was not necessary on targets that support weak ! symbols, because the implicit instantiations will defer to the explicit ! one. However, that's not actually the case in SVR4; a strong definition ! after a weak one is an error. Also, not making explicit ! instantiations one_only means that we can end up with two copies of ! some template instantiations. */ ! if (! supports_one_only ()) return; /* We can't set DECL_COMDAT on functions, or finish_file will think *************** import_export_decl (decl) *** 2775,2780 **** --- 2854,2883 ---- else DECL_NOT_REALLY_EXTERN (decl) = 0; } + else if (DECL_VLIST_CTOR_WRAPPER_P (decl)) + { + int implement; + tree ctype = DECL_CLASS_CONTEXT (decl); + import_export_class (ctype); + if (!DECL_THIS_INLINE (DECL_VLIST_CTOR_WRAPPED (decl))) + { + /* No change. */ + } + else if (CLASSTYPE_INTERFACE_KNOWN (ctype)) + { + implement = !CLASSTYPE_INTERFACE_ONLY (ctype) + && flag_implement_inlines; + DECL_NOT_REALLY_EXTERN (decl) = implement; + DECL_EXTERNAL (decl) = !implement; + } + else + { + DECL_NOT_REALLY_EXTERN (decl) = 1; + DECL_EXTERNAL (decl) = 1; + } + if (flag_weak) + comdat_linkage (decl); + } else if (DECL_FUNCTION_MEMBER_P (decl)) { tree ctype = DECL_CLASS_CONTEXT (decl); *************** generate_ctor_and_dtor_functions_for_pri *** 3527,3532 **** --- 3630,3662 ---- return 0; } + /* Returns non-zero if T is a vlist ctor wrapper. */ + + static int + vlist_ctor_wrapper_p (t, data) + tree t; + void *data ATTRIBUTE_UNUSED; + { + return (TREE_CODE (t) == FUNCTION_DECL) && DECL_VLIST_CTOR_WRAPPER_P (t); + } + + /* Emits a vlist ctor wrapper if necessary. */ + + static int + finish_vlist_ctor_wrapper (t, data) + tree *t; + void *data ATTRIBUTE_UNUSED; + { + import_export_decl (*t); + if (!DECL_EXTERNAL (*t) && !TREE_USED (*t)) + { + mark_used (*t); + synthesize_method (*t); + return 1; + } + return 0; + } + /* This routine is called from the last rule in yyparse (). Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction *************** finish_file () *** 3603,3608 **** --- 3733,3744 ---- /*data=*/0)) reconsider = 1; + if (walk_globals (vlist_ctor_wrapper_p, + finish_vlist_ctor_wrapper, + /*data=*/0)) + reconsider = 1; + + /* The list of objects with static storage duration is built up in reverse order, so we reverse it here. We also clear STATIC_AGGREGATES so that any new aggregates added during the diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/exception.cc gcc-2.95.3/gcc/cp/exception.cc *** gcc-2.95.2/gcc/cp/exception.cc Wed Dec 16 21:15:22 1998 --- gcc-2.95.3/gcc/cp/exception.cc Thu Apr 20 06:13:25 2000 *************** __cp_pop_exception (cp_eh_info *p) *** 247,256 **** if (p->cleanup) /* 2 is a magic value for destructors; see build_delete(). */ ! p->cleanup (p->value, 2); if (! __is_pointer (p->type)) ! __eh_free (p->original_value); // value may have been co-erced. __eh_free (p); } --- 247,256 ---- if (p->cleanup) /* 2 is a magic value for destructors; see build_delete(). */ ! p->cleanup (p->original_value, 2); // value may have been adjusted. if (! __is_pointer (p->type)) ! __eh_free (p->original_value); // value may have been adjusted. __eh_free (p); } diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/gxxint.texi gcc-2.95.3/gcc/cp/gxxint.texi *** gcc-2.95.2/gcc/cp/gxxint.texi Wed May 19 02:57:45 1999 --- gcc-2.95.3/gcc/cp/gxxint.texi Wed Apr 12 07:53:33 2000 *************** Questions and comments to Benjamin Kosni *** 26,31 **** --- 26,32 ---- * Exception Handling:: * Free Store:: * Mangling:: Function name mangling for C++ and Java + * Vtables:: Two ways to do virtual functions * Concept Index:: @end menu *************** accessed by the BINFO_ accessor macros. *** 190,196 **** The virtual function table holds information used in virtual function dispatching. In the compiler, they are usually referred to as vtables, or vtbls. The first index is not used in the normal way, I believe it ! is probably used for the virtual destructor. @item vfield --- 191,199 ---- The virtual function table holds information used in virtual function dispatching. In the compiler, they are usually referred to as vtables, or vtbls. The first index is not used in the normal way, I believe it ! is probably used for the virtual destructor. There are two forms of ! virtual tables, one that has offsets in addition to pointers, and one ! using thunks. @xref{Vtables}. @item vfield *************** To meet the first goal, we defer emissio *** 1455,1461 **** the end of the translation unit, where we can decide whether or not they are needed, and how to emit them if they are. ! @node Mangling, Concept Index, Free Store, Top @section Function name mangling for C++ and Java Both C++ and Jave provide overloaded function and methods, --- 1458,1464 ---- the end of the translation unit, where we can decide whether or not they are needed, and how to emit them if they are. ! @node Mangling, Vtables, Free Store, Top @section Function name mangling for C++ and Java Both C++ and Jave provide overloaded function and methods, *************** Used for template type parameters. *** 1839,1845 **** The letters @samp{G}, @samp{M}, @samp{O}, and @samp{p} also seem to be used for obscure purposes ... ! @node Concept Index, , Mangling, Top @section Concept Index --- 1842,2072 ---- The letters @samp{G}, @samp{M}, @samp{O}, and @samp{p} also seem to be used for obscure purposes ... ! @node Vtables, Concept Index, Mangling, Top ! @section Virtual Tables ! ! In order to invoke virtual functions, GNU C++ uses virtual tables. Each ! virtual function gets an index, and the table entry points to the ! overridden function to call. Sometimes, and adjustment to the this ! pointer has to be made before calling a virtual function: ! ! @example ! struct A@{ ! int i; ! virtual void foo(); ! @}; ! ! struct B@{ ! int j; ! virtual void bar(); ! @}; ! ! struct C:A,B@{ ! virtual void bar(); ! @}; ! ! void C::bar() ! @{ ! i++; ! @} ! ! int main() ! @{ ! C *c = new C; ! B *b = c; ! c->bar(); ! @} ! @end example ! ! Here, casting from @samp{c} to @samp{b} adds an offset. When @samp{bar} ! is called, this offset needs to be subtracted, so that @samp{C::bar} can ! properly access @samp{i}. One approach of achieving this is to use ! @emph{thunks}, which are small half-functions put into the virtual ! table. The modify the first argument (the @samp{this} pointer), and then ! jump into the real function. ! ! The other (traditional) approach is to have an additional integer in the ! virtual table which is added to this. This is an additional overhead ! both at the function call, and in the size of virtual tables: In the ! case of single inheritance (or for the first base class), these integers ! will always be zero. ! ! @subsection Virtual Base Classes with Virtual Tables ! ! In case of virtual bases, the code is even more ! complicated. Constructors and destructors need to know whether they are ! "in charge" of the virtual bases, and an implicit integer ! @samp{__in_chrg} for that purpose. ! ! @example ! struct A@{ ! int i; ! virtual void bar(); ! void call_bar()@{bar();@} ! @}; ! ! struct B:virtual A@{ ! B(); ! int j; ! virtual void bar(); ! @}; ! ! B::B()@{ ! call_bar(); ! @} ! ! struct C@{ ! int k; ! @}; ! ! struct D:C,B@{ ! int l; ! virtual void bar(); ! @}; ! ! @end example ! ! When constructing an instance of B, it will have the following layout: ! @samp{vbase pointer to A}, @samp{j}, @samp{A virtual table}, @samp{i}. ! On a 32-bit machine, downcasting from @samp{A*} to @samp{B*} would need ! to subtract 8, which would be the thunk executed when calling ! @samp{B::bar} inside @samp{call_bar}. ! ! When constructing an instance of D, it will have a different layout: ! @samp{k}, @samp{vbase pointer to A}, @samp{j}, @samp{l}, @samp{A virtual ! table}, @samp{i}. So, when downcasting from @samp{A*} to @samp{B*} in a ! @samp{D} object, the offset would be @samp{12}. ! ! This means that during construction of the @samp{B} base of a @samp{D} ! object, a virtual table is needed which has a @samp{-12} thunk to ! @samp{B::bar}. This is @emph{only} needed during construction and ! destruction, as the full object will use a @samp{-16} thunk to ! @samp{D::bar}. ! ! In order to implement this, the compiler generates an implicit argument ! (in addition to @code{__in_chrg}): the virtual list argument ! @code{__vlist}. This is a list of virtual tables needed during ! construction and destruction. The virtual pointers are ordered in the ! way they are used during construction; the destructors will process the ! array in reverse order. The ordering is as follows: ! @itemize @bullet ! @item ! If the class is in charge, the vlist starts with virtual table pointers ! for the virtual bases that have virtual bases themselves. Here, only ! @emph{polymorphic} virtual bases (pvbases) are interesting: if a vbase ! has no virtual functions, it doesn't have a virtual table. ! ! @item ! Next, the vlist has virtual tables for the initialization of the ! non-virtual bases. These bases are not in charge, so the layout is ! recursive, but ignores virtual bases during recursion. ! ! @item ! Next, there is a number of virtual tables for each virtual base. These ! are sorted in the order in which virtual bases are constructed. Each ! virtual base may have more than one @code{vfield}, and therefore require ! more than one @code{vtable}. The order of vtables is the same as used ! when initializing vfields of non-virtual bases in a constructor. ! @end itemize ! ! The compiler emits a virtual table list in a variable mangled as ! @code{__vl.classname}. ! ! Class with virtual bases, but without pvbases, only have the ! @code{__in_chrg} argument to their ctors and dtors: they don't have any ! vfields in the vbases to initialize. ! ! A further problem arises with virtual destructors: A destructor ! typically has only the @code{__in_chrg} argument, which also indicates ! whether the destructor should call @code{operator delete}. A dtor of a ! class with pvbases has an additional argument. Unfortunately, a caller ! of a virtual dtor might not know whether to pass that argument or not. ! Therefore, the dtor processes the @code{__vlist} argument in an ! automatic variable, which is initialized from the class' vlist if the ! __in_chrg flag has a zero value in bit 2 (bit mask 4), or from the ! argument @code{__vlist1} if bit 2 of the __in_chrg parameter is set to ! one. ! ! @subsection Specification of non-thunked vtables ! ! In the traditional implementation of vtables, each slot contains three ! fields: The offset to be added to the this pointer before invoking a ! virtual function, an unused field that is always zero, and the pointer ! to the virtual function. The first two fields are typically 16 bits ! wide. The unused field is called `index'; it may be non-zero in ! pointer-to-member-functions, which use the same layout. ! ! The virtual table then is an array of vtable slots. The first slot is ! always the virtual type info function, the other slots are in the order ! in which the virtual functions appear in the class declaration. ! ! If a class has base classes, it may inherit other bases' vfields. Each ! class may have a primary vfield; the primary vfield of the derived class ! is the primary vfield of the left-most non-virtual base class. If a ! class inherits a primary vfield, any new virtual functions in the ! derived class are appended to the virtual table of the primary ! vfield. If there are new virtual functions in the derived class, and no ! primary vfield is inherited, a new vfield is introduced which becomes ! primary. The redefined virtual functions fill the vtable slots inherited ! from the base; new virtual functions are put into the primary vtable in ! the order of declaration. If no new virtual functions are introduced, no ! primary vfield is allocated. ! ! In a base class that has pvbases, virtual tables are needed which are ! used only in the constructor (see example above). At run-time, the ! virtual tables of the base class are adjusted, to reflect the new offset ! of the pvbase. The compiler knows statically what offset the pvbase has ! for a complete object. At run-time, the offset of the pvbase can be ! extracted from the vbase pointer, which is set in the constructor of the ! complete object. These two offsets result in a delta, which is used to ! adjust the deltas in the vtable (the adjustment might be different for ! different vtable slots). To adjust the vtables, the compiler emits code ! that creates a vtable on the stack. This vtable is initialized with the ! vtable for the complete base type, and then adjusted. ! ! In order to call a virtual function, the compiler gets the offset field ! from the vtable entry, and adds it to the this pointer. It then ! indirectly calls the virtual function pointer, passing the adjusted this ! pointer, and any arguments the virtual function may have. ! ! To implement dynamic casting, the dynamic_cast function needs typeinfos ! for the complete type, and the pointer to the complete type. The ! typeinfo pointer is obtained by calling the virtual typeinfo function ! (which doesn't take a this parameter). The pointer to the complete ! object is obtained by adding the offset of the virtual typeinfo vtable ! slot, since this virtual function is always implemented in the complete ! object. ! ! @subsection Specification of thunked vtables ! ! For vtable thunks, each slot only consists of a pointer to the virtual ! function, which might be a thunk function. The first slot in the vtable ! is an offset of the this pointer to the complete object, which is needed ! as a parameter to __dynamic_cast. The second slot is the virtual ! typeinfo function. All other slots are allocated with the same procedure ! as in the non-thunked case. Allocation of vfields also uses the same ! procedure as described above. ! ! If the virtual function needs an adjusted this pointer, a thunk function ! is emitted. If supported by the target architecture, this is only a ! half-function. Such a thunk has no stack frame; it merely adjusts the ! first argument of the function, and then directly branches into the ! implementation of the virtual function. If the architecture does not ! support half-functions (i.e. if ASM_OUTPUT_MI_THUNK is not defined), the ! compiler emits a wrapper function, which copies all arguments, adjust ! the this pointer, and then calls the original function. Since objects of ! non-aggregate type are passed by invisible reference, this copies only ! POD arguments. The approach fails for virtual functions with a variable ! number of arguments. ! ! In order to support the vtables needed in base constructors with ! pvbases, the compiler passes an implicit __vlist argument as described ! above, if the version 2 thunks are used. For version 1 thunks, the base ! class constructor will fill in the vtables for the complete base class, ! which will incorrectly adjust the this pointer, leading to a dynamic ! error. ! ! @node Concept Index, , Vtables, Top @section Concept Index diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/init.c gcc-2.95.3/gcc/cp/init.c *** gcc-2.95.2/gcc/cp/init.c Tue Jun 22 08:23:30 1999 --- gcc-2.95.3/gcc/cp/init.c Sat Jun 10 01:06:44 2000 *************** static tree initializing_context PROTO(( *** 59,65 **** static void expand_vec_init_try_block PROTO((tree)); static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree)); static tree build_java_class_ref PROTO((tree)); ! static void expand_cleanup_for_base PROTO((tree, tree)); /* Cache the identifier nodes for the magic field of a new cookie. */ static tree nc_nelts_field_id; --- 59,66 ---- static void expand_vec_init_try_block PROTO((tree)); static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree)); static tree build_java_class_ref PROTO((tree)); ! static void expand_cleanup_for_base PROTO((tree, tree, tree)); ! static int pvbasecount PROTO((tree, int)); /* Cache the identifier nodes for the magic field of a new cookie. */ static tree nc_nelts_field_id; *************** sort_base_init (t, rbase_ptr, vbase_ptr) *** 478,483 **** --- 479,571 ---- *vbase_ptr = vbases; } + /* Invoke a base-class destructor. REF is the object being destroyed, + BINFO is the base class, and DTOR_ARG indicates whether the base + class should invoke delete. */ + + tree + build_base_dtor_call (ref, binfo, dtor_arg) + tree ref, binfo, dtor_arg; + { + tree args = NULL_TREE; + tree vlist = lookup_name (vlist_identifier, 0); + tree call, decr; + + if (TYPE_USES_PVBASES (BINFO_TYPE (binfo))) + { + args = expr_tree_cons (NULL_TREE, vlist, args); + dtor_arg = build (BIT_IOR_EXPR, integer_type_node, + dtor_arg, build_int_2 (4, 0)); + dtor_arg = fold (dtor_arg); + } + args = expr_tree_cons (NULL_TREE, dtor_arg, args); + call = build_scoped_method_call (ref, binfo, dtor_identifier, args); + + if (!TYPE_USES_PVBASES (BINFO_TYPE (binfo))) + /* For plain inheritance, do not try to adjust __vlist. */ + return call; + + /* Now decrement __vlist by the number of slots consumed by the base + dtor. */ + decr = build_int_2 (pvbasecount (BINFO_TYPE (binfo), 0), 0); + decr = build_binary_op (MINUS_EXPR, vlist, decr); + decr = build_modify_expr (vlist, NOP_EXPR, decr); + + return build (COMPOUND_EXPR, void_type_node, call, decr); + } + + /* Return the number of vlist entries needed to initialize TYPE, + depending on whether it is IN_CHARGE. */ + + static int + pvbasecount (type, in_charge) + tree type; + int in_charge; + { + int i; + int result = 0; + tree vbase; + + for (vbase = (CLASSTYPE_VBASECLASSES (type)); vbase; + vbase = TREE_CHAIN (vbase)) + { + result += list_length (CLASSTYPE_VFIELDS (BINFO_TYPE (vbase))); + if (in_charge) + result += pvbasecount (BINFO_TYPE (vbase), 0); + } + + for (i=0; i < CLASSTYPE_N_BASECLASSES (type); i++) + { + tree base = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i); + if (TREE_VIA_VIRTUAL (base)) + continue; + result += pvbasecount (BINFO_TYPE (base), 0); + } + return result; + } + + void + init_vlist (t) + tree t; + { + char *name; + tree expr; + tree vlist = lookup_name (vlist_identifier, 0); + + name = alloca (strlen (VLIST_NAME_FORMAT) + + TYPE_ASSEMBLER_NAME_LENGTH (t) + 2); + sprintf (name, VLIST_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (t)); + + expr = get_identifier (name); + expr = lookup_name (expr, 0); + expr = build1 (ADDR_EXPR, TREE_TYPE (vlist), expr); + if (DECL_DESTRUCTOR_FOR_PVBASE_P (current_function_decl)) + /* Move to the end of the vlist. */ + expr = build_binary_op (PLUS_EXPR, expr, + build_int_2 (pvbasecount (t, 1), 0)); + expand_expr_stmt (build_modify_expr (vlist, NOP_EXPR, expr)); + } + /* Perform whatever initializations have yet to be done on the base class of the class variable. These actions are in the global variable CURRENT_BASE_INIT_LIST. Such an action could be *************** emit_base_init (t, immediately) *** 510,515 **** --- 598,604 ---- tree binfos = BINFO_BASETYPES (t_binfo); int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; tree expr = NULL_TREE; + tree vlist = lookup_name (vlist_identifier, 0); if (! immediately) { *************** emit_base_init (t, immediately) *** 581,587 **** free_temp_slots (); } ! expand_cleanup_for_base (base_binfo, NULL_TREE); rbase_init_list = TREE_CHAIN (rbase_init_list); } --- 670,676 ---- free_temp_slots (); } ! expand_cleanup_for_base (base_binfo, vlist, NULL_TREE); rbase_init_list = TREE_CHAIN (rbase_init_list); } *************** expand_virtual_init (binfo, decl) *** 750,779 **** destroyed. */ static void ! expand_cleanup_for_base (binfo, flag) tree binfo; tree flag; { tree expr; ! if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo))) ! return; ! /* All cleanups must be on the function_obstack. */ ! push_obstacks_nochange (); ! resume_temporary_allocation (); ! /* Call the destructor. */ ! expr = (build_scoped_method_call ! (current_class_ref, binfo, dtor_identifier, ! build_expr_list (NULL_TREE, integer_zero_node))); ! if (flag) ! expr = fold (build (COND_EXPR, void_type_node, ! truthvalue_conversion (flag), ! expr, integer_zero_node)); ! pop_obstacks (); ! add_partial_entry (expr); } /* Subroutine of `expand_aggr_vbase_init'. --- 839,877 ---- destroyed. */ static void ! expand_cleanup_for_base (binfo, vlist, flag) tree binfo; + tree vlist; tree flag; { tree expr; ! if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo))) ! { ! /* All cleanups must be on the function_obstack. */ ! push_obstacks_nochange (); ! resume_temporary_allocation (); ! /* Call the destructor. */ ! expr = build_base_dtor_call (current_class_ref, binfo, ! integer_zero_node); ! if (flag) ! expr = fold (build (COND_EXPR, void_type_node, ! truthvalue_conversion (flag), ! expr, integer_zero_node)); ! pop_obstacks (); ! add_partial_entry (expr); ! } ! if (TYPE_USES_PVBASES (BINFO_TYPE (binfo))) ! { ! /* Increment vlist by number of base's vbase classes. */ ! expr = build_int_2 (pvbasecount (BINFO_TYPE (binfo), 0), 0); ! expr = build_binary_op (PLUS_EXPR, vlist, expr); ! expr = build_modify_expr (vlist, NOP_EXPR, expr); ! expand_expr_stmt (expr); ! } } /* Subroutine of `expand_aggr_vbase_init'. *************** construct_virtual_bases (type, this_ref, *** 813,818 **** --- 911,917 ---- { tree vbases; tree result; + tree vlist = NULL_TREE; /* If there are no virtual baseclasses, we shouldn't even be here. */ my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621); *************** construct_virtual_bases (type, this_ref, *** 820,825 **** --- 919,929 ---- /* First set the pointers in our object that tell us where to find our virtual baseclasses. */ expand_start_cond (flag, 0); + if (TYPE_USES_PVBASES (type)) + { + init_vlist (type); + vlist = lookup_name (vlist_identifier, 0); + } result = init_vbase_pointers (type, this_ptr); if (result) expand_expr_stmt (build_compound_expr (result)); *************** construct_virtual_bases (type, this_ref, *** 851,857 **** init_list); expand_end_cond (); ! expand_cleanup_for_base (vbases, flag); } } --- 955,961 ---- init_list); expand_end_cond (); ! expand_cleanup_for_base (vbases, vlist, flag); } } *************** expand_aggr_init (exp, init, flags) *** 1146,1151 **** --- 1250,1301 ---- TREE_THIS_VOLATILE (exp) = was_volatile; } + static tree + no_vlist_base_init (rval, exp, init, binfo, flags) + tree rval, exp, init, binfo; + int flags; + { + tree nrval, func, parms; + + /* Obtain the vlist-expecting ctor. */ + func = rval; + my_friendly_assert (TREE_CODE (func) == CALL_EXPR, 20000131); + func = TREE_OPERAND (func, 0); + my_friendly_assert (TREE_CODE (func) == ADDR_EXPR, 20000132); + func = TREE_OPERAND (func, 0); + my_friendly_assert (TREE_CODE (func) == FUNCTION_DECL, 20000133); + + /* If we have already seen a definition for the wrapped function, + we don't need to declare it weak. Also, declare_weak will complain + if we do. */ + if (!TREE_ASM_WRITTEN (func)) + declare_weak (func); + + if (init == NULL_TREE + || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init))) + { + parms = init; + if (parms) + init = TREE_VALUE (parms); + } + else + parms = build_expr_list (NULL_TREE, init); + + flags &= ~LOOKUP_HAS_VLIST; + + parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms); + flags |= LOOKUP_HAS_IN_CHARGE; + + nrval = build_method_call (exp, ctor_identifier, + parms, binfo, flags); + + func = build (NE_EXPR, boolean_type_node, + func, null_pointer_node); + nrval = build (COND_EXPR, void_type_node, + func, rval, nrval); + return nrval; + } + static void expand_default_init (binfo, true_exp, exp, init, flags) tree binfo; *************** expand_default_init (binfo, true_exp, ex *** 1163,1168 **** --- 1313,1320 ---- out, then look hard. */ tree rval; tree parms; + tree vlist = NULL_TREE; + tree orig_init = init; if (init && TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING)) *************** expand_default_init (binfo, true_exp, ex *** 1206,1211 **** --- 1358,1378 ---- if (TYPE_USES_VIRTUAL_BASECLASSES (type)) { + if (TYPE_USES_PVBASES (type)) + { + /* In compatibility mode, when not calling a base ctor, + we do not pass the vlist argument. */ + if (true_exp == exp) + vlist = flag_vtable_thunks_compat? NULL_TREE : vlist_zero_node; + else + vlist = lookup_name (vlist_identifier, 0); + + if (vlist) + { + parms = expr_tree_cons (NULL_TREE, vlist, parms); + flags |= LOOKUP_HAS_VLIST; + } + } if (true_exp == exp) parms = expr_tree_cons (NULL_TREE, integer_one_node, parms); else *************** expand_default_init (binfo, true_exp, ex *** 1215,1220 **** --- 1382,1391 ---- rval = build_method_call (exp, ctor_identifier, parms, binfo, flags); + if (vlist && true_exp != exp && flag_vtable_thunks_compat) + { + rval = no_vlist_base_init (rval, exp, orig_init, binfo, flags); + } if (TREE_SIDE_EFFECTS (rval)) expand_expr_stmt (rval); } *************** build_new_1 (exp) *** 2408,2413 **** --- 2579,2590 ---- if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type)) { + if (TYPE_USES_PVBASES (true_type) + && !flag_vtable_thunks_compat) + { + init = expr_tree_cons (NULL_TREE, vlist_zero_node, init); + flags |= LOOKUP_HAS_VLIST; + } init = expr_tree_cons (NULL_TREE, integer_one_node, init); flags |= LOOKUP_HAS_IN_CHARGE; } *************** build_delete (type, addr, auto_delete, f *** 3123,3131 **** else passed_auto_delete = auto_delete; ! expr = build_method_call ! (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete), ! NULL_TREE, flags); if (do_delete) expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); --- 3300,3320 ---- else passed_auto_delete = auto_delete; ! /* Maybe pass vlist pointer to destructor. */ ! if (TYPE_USES_PVBASES (type)) ! { ! /* Pass vlist_zero even if in backwards compatibility mode, ! as the extra argument should not hurt if it is not used. */ ! expr = build_expr_list (NULL_TREE, vlist_zero_node); ! flags |= LOOKUP_HAS_VLIST; ! } ! else ! expr = NULL_TREE; ! ! expr = expr_tree_cons (NULL_TREE, passed_auto_delete, expr); ! ! expr = build_method_call (ref, dtor_identifier, expr, ! NULL_TREE, flags); if (do_delete) expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); *************** build_delete (type, addr, auto_delete, f *** 3181,3194 **** { tree this_auto_delete; if (BINFO_OFFSET_ZEROP (base_binfo)) this_auto_delete = parent_auto_delete; else this_auto_delete = integer_zero_node; ! expr = build_scoped_method_call ! (ref, base_binfo, dtor_identifier, ! build_expr_list (NULL_TREE, this_auto_delete)); exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); } --- 3370,3382 ---- { tree this_auto_delete; + /* Should the base invoke delete? */ if (BINFO_OFFSET_ZEROP (base_binfo)) this_auto_delete = parent_auto_delete; else this_auto_delete = integer_zero_node; ! expr = build_base_dtor_call (ref, base_binfo, this_auto_delete); exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); } *************** build_delete (type, addr, auto_delete, f *** 3200,3208 **** || TREE_VIA_VIRTUAL (base_binfo)) continue; ! expr = build_scoped_method_call ! (ref, base_binfo, dtor_identifier, ! build_expr_list (NULL_TREE, integer_zero_node)); exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); } --- 3388,3394 ---- || TREE_VIA_VIRTUAL (base_binfo)) continue; ! expr = build_base_dtor_call (ref, base_binfo, integer_zero_node); exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt); } diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/lang-specs.h gcc-2.95.3/gcc/cp/lang-specs.h *** gcc-2.95.2/gcc/cp/lang-specs.h Tue May 18 00:28:09 1999 --- gcc-2.95.3/gcc/cp/lang-specs.h Thu Jan 25 14:03:38 2001 *************** *** 1,5 **** /* Definitions for specs for C++. ! Copyright (C) 1995, 96-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,5 ---- /* Definitions for specs for C++. ! Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of GNU CC. *************** Boston, MA 02111-1307, USA. */ *** 30,36 **** {"@c++", #if USE_CPPLIB { ! "%{E|M|MM:cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C++ does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\ --- 30,36 ---- {"@c++", #if USE_CPPLIB { ! "%{E|M|MM:cpp0 -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C++ does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\ *************** Boston, MA 02111-1307, USA. */ *** 62,68 **** %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ %{!pipe:%g.s} %A\n }}}}"}}, #else /* ! USE_CPPLIB */ ! {"cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C++ does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\ --- 62,68 ---- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ %{!pipe:%g.s} %A\n }}}}"}}, #else /* ! USE_CPPLIB */ ! {"cpp0 -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C++ does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\ diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/method.c gcc-2.95.3/gcc/cp/method.c *** gcc-2.95.2/gcc/cp/method.c Wed Jun 16 18:49:59 1999 --- gcc-2.95.3/gcc/cp/method.c Sat Jun 10 01:06:44 2000 *************** Boston, MA 02111-1307, USA. */ *** 41,46 **** --- 41,47 ---- #include "hard-reg-set.h" #include "flags.h" #include "toplev.h" + #include "decl.h" /* TREE_LIST of the current inline functions that need to be processed. */ *************** static int is_back_referenceable_type PR *** 88,93 **** --- 89,96 ---- static int check_btype PROTO((tree)); static void build_mangled_name_for_type PROTO((tree)); static void build_mangled_name_for_type_with_Gcode PROTO((tree, int)); + static tree build_base_path PROTO((tree, int)); + # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) *************** process_overload_item (parmtype, extra_G *** 1349,1354 **** --- 1352,1366 ---- #endif case POINTER_TYPE: + /* Even though the vlist_type_node is PPPFe (i.e. `int + (***)(...)'), it is different from the any other occurence of + the pointer type, because the underlying function type is + different. */ + if (parmtype == vlist_type_node) + { + OB_PUTS (VLIST_TYPE_NAME); + return; + } OB_PUTC ('P'); more: build_mangled_name_for_type (TREE_TYPE (parmtype)); *************** get_id_2 (name, name2) *** 1809,1822 **** return get_identifier (obstack_base (&scratch_obstack)); } ! /* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */ tree ! build_destructor_name (type) tree type; { ! return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX), ! type); } /* Given a tree_code CODE, and some arguments (at least one), --- 1821,1884 ---- return get_identifier (obstack_base (&scratch_obstack)); } ! /* Print a binfo path T, starting with the most derived class. If ! OMIT_LAST is set, drop and return the most derived class. */ ! ! static tree ! build_base_path (t, omit_last) ! tree t; ! int omit_last; ! { ! tree ret = NULL_TREE; ! if (BINFO_INHERITANCE_CHAIN (t)) ! ret = build_base_path (BINFO_INHERITANCE_CHAIN (t), omit_last); ! else if (omit_last) ! return t; ! process_overload_item (BINFO_TYPE (t), 0); ! return ret; ! } ! ! /* Return a mangled name for a vlist vtable, using the path of both ! BASE and VBASE. */ ! ! tree ! get_vlist_vtable_id (base, vbase) ! tree base, vbase; ! { ! tree last; ! OB_INIT (); ! OB_PUTS (VCTABLE_NAME); ! build_base_path (base, 0); ! OB_PUTC ('_'); ! /* Since the base path should end where the vbase path starts, we ! can omit the most-derived class in the vbase path. Check below ! that this really happens. */ ! last = build_base_path (vbase, 1); ! my_friendly_assert (BINFO_TYPE (last) == BINFO_TYPE (base), 990402); ! OB_FINISH (); ! return get_identifier (obstack_base (&scratch_obstack)); ! } ! ! /* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. If ! HAS_VLIST is set, also add the vlist argument. */ tree ! build_destructor_name (type, has_vlist) tree type; + int has_vlist; { ! OB_INIT (); ! OB_PUTS (DESTRUCTOR_DECL_PREFIX); ! start_squangling (); ! build_mangled_name_for_type (type); ! /* If we need backwards compatibility, we can get aways by ! not linking type-safely, as the dtor will check whether ! the argument was provided. */ ! if (has_vlist && !flag_vtable_thunks_compat) ! OB_PUTS (VLIST_TYPE_NAME); ! OB_FINISH (); ! end_squangling (); ! return get_identifier (obstack_base (&scratch_obstack)); } /* Given a tree_code CODE, and some arguments (at least one), *************** emit_thunk (thunk_fndecl) *** 2178,2183 **** --- 2240,2388 ---- TREE_SET_CODE (thunk_fndecl, THUNK_DECL); } + void + maybe_vlist_ctor_wrapper (fn, definep) + tree fn; + int definep; + { + tree fntype, decl; + tree arg_types, parms, parm, basetype, pbasetype; + tree t, ctors; + + if (!flag_vtable_thunks_compat + || !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + return; + + arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); + pbasetype = TREE_VALUE (arg_types); + basetype = TREE_TYPE (pbasetype); + parms = DECL_ARGUMENTS (fn); + + /* Skip this, __in_chrg, and _vlist */ + arg_types = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_types))); + + + /* Add __in_charge. */ + arg_types = hash_tree_chain (integer_type_node, arg_types); + + /* Don't add this to arg_types, as build_cplus_method_type does so. */ + + fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)), + arg_types); + + decl = build_lang_decl (FUNCTION_DECL, DECL_NAME (fn), fntype); + DECL_LANG_SPECIFIC (decl)->decl_flags = DECL_LANG_SPECIFIC (fn)->decl_flags; + DECL_EXTERNAL (decl) = 0; + TREE_PUBLIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_CONSTRUCTOR_P (decl) = 1; + DECL_CONSTRUCTOR_FOR_VBASE (decl) = CONSTRUCTOR_FOR_VBASE; + /* Claim that this is never a template instantiation. */ + DECL_USE_TEMPLATE (decl) = 0; + DECL_TEMPLATE_INFO (decl) = NULL_TREE; + + /* Set up clone argument trees for the thunk. */ + parms = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (parms))); + /* Add this */ + t = build_decl (PARM_DECL, this_identifier, pbasetype); + SET_DECL_ARTIFICIAL (t); + DECL_ARG_TYPE (t) = pbasetype; + DECL_REGISTER (t) = 1; + /* Add __in_charge. */ + parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); + SET_DECL_ARTIFICIAL (parm); + DECL_ARG_TYPE (parm) = integer_type_node; + TREE_CHAIN (parm) = t; + t = parm; + + while (parms) + { + tree x = copy_node (parms); + TREE_CHAIN (x) = t; + DECL_CONTEXT (x) = decl; + t = x; + parms = TREE_CHAIN (parms); + } + parms = nreverse (t); + DECL_ARGUMENTS (decl) = parms; + + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload (DECL_NAME (decl), + TYPE_ARG_TYPES (TREE_TYPE (decl)), 2); + + ctors = CLASSTYPE_METHOD_VEC (basetype); + if (ctors) + ctors = TREE_VEC_ELT (ctors, 0); + for ( ; ctors; ctors = OVL_NEXT (ctors)) + if (DECL_ASSEMBLER_NAME (OVL_CURRENT (ctors)) + == DECL_ASSEMBLER_NAME (decl)) + break; + + if (!ctors) + { + add_method (basetype, 0, decl); + cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0, 0); + } + else + decl = OVL_CURRENT (ctors); + + /* Remember the original function. */ + DECL_VLIST_CTOR_WRAPPED (decl) = fn; + + /* If this is called from start_method, definep is -1. Then we + are inside the class, and fn is inline by default. */ + if (definep) + { + /* Record that the ctor is being defined, so we also emit the + wrapper later. */ + if (DECL_THIS_INLINE (fn) || (definep == -1)) + { + DECL_THIS_INLINE (decl) = 1; + DECL_INLINE (decl) = 1; + pushdecl_top_level (decl); + } + else + { + TREE_USED (decl) = 1; + TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1; + } + mark_inline_for_output (decl); + } + } + + static void + emit_vlist_ctor_wrapper (decl) + tree decl; + { + tree t, parms, fn; + + current_function_is_thunk = 1; + + parms = DECL_ARGUMENTS (decl); + fn = DECL_VLIST_CTOR_WRAPPED (decl); + mark_used (fn); + + /* Build up the call to the real function. */ + t = NULL_TREE; + /* Push this, __in_charge. */ + t = expr_tree_cons (NULL_TREE, parms, t); + parms = TREE_CHAIN (parms); + t = expr_tree_cons (NULL_TREE, parms, t); + parms = TREE_CHAIN (parms); + /* Push 0 as __vlist. */ + t = expr_tree_cons (NULL_TREE, vlist_zero_node, t); + /* Push rest of arguments. */ + while (parms) + { + t = expr_tree_cons (NULL_TREE, parms, t); + parms = TREE_CHAIN (parms); + } + t = nreverse (t); + t = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), t); + expand_expr_stmt (t); + } + + /* Code for synthesizing methods which have default semantics defined. */ /* For the anonymous union in TYPE, return the member that is at least as *************** do_build_copy_constructor (fndecl) *** 2212,2217 **** --- 2417,2424 ---- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) parm = TREE_CHAIN (parm); + if (TYPE_USES_PVBASES (current_class_type)) + parm = TREE_CHAIN (parm); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) *************** synthesize_method (fndecl) *** 2408,2413 **** --- 2615,2630 ---- int nested = (current_function_decl != NULL_TREE); tree context = hack_decl_function_context (fndecl); + /* If this is a wrapper around a undefined vlist ctor, don't emit it + even if it is used. */ + if (DECL_VLIST_CTOR_WRAPPER_P (fndecl)) + { + tree orig_fn = DECL_VLIST_CTOR_WRAPPED (fndecl); + mark_used (orig_fn); + if (DECL_INITIAL (orig_fn) == NULL_TREE) + return; + } + if (at_eof) import_export_decl (fndecl); *************** synthesize_method (fndecl) *** 2429,2435 **** tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl)) arg_chain = TREE_CHAIN (arg_chain); ! if (arg_chain != void_list_node) do_build_copy_constructor (fndecl); else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) setup_vtbl_ptr (); --- 2646,2656 ---- tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl)) arg_chain = TREE_CHAIN (arg_chain); ! else if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fndecl)) ! arg_chain = TREE_CHAIN (TREE_CHAIN (arg_chain)); ! if (DECL_VLIST_CTOR_WRAPPER_P (fndecl)) ! emit_vlist_ctor_wrapper (fndecl); ! else if (arg_chain != void_list_node) do_build_copy_constructor (fndecl); else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) setup_vtbl_ptr (); diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/pt.c gcc-2.95.3/gcc/cp/pt.c *** gcc-2.95.2/gcc/cp/pt.c Tue Sep 7 08:52:06 1999 --- gcc-2.95.3/gcc/cp/pt.c Wed Apr 12 07:53:33 2000 *************** static int coerce_template_template_parm *** 161,166 **** --- 161,167 ---- static tree determine_specialization PROTO((tree, tree, tree *, int)); static int template_args_equal PROTO((tree, tree)); static void print_template_context PROTO((int)); + static int has_pvbases_p PROTO((tree, tree)); /* We use TREE_VECs to hold template arguments. If there is only one level of template arguments, then the TREE_VEC contains the *************** tsubst_friend_class (friend_tmpl, args) *** 4685,4690 **** --- 4686,4708 ---- return friend_type; } + static int + has_pvbases_p (t, pattern) + tree t, pattern; + { + if (!TYPE_USES_VIRTUAL_BASECLASSES (t)) + return 0; + + if (TYPE_USES_PVBASES (pattern)) + return 1; + + for (t = CLASSTYPE_VBASECLASSES (t); t; t = TREE_CHAIN (t)) + if (TYPE_VIRTUAL_P (BINFO_TYPE (t))) + return 1; + + return 0; + } + tree instantiate_class_template (type) tree type; *************** instantiate_class_template (type) *** 5035,5040 **** --- 5053,5065 ---- } } + /* After we have calculated the bases, we can now compute whether we + have polymorphic vbases. This needs to happen before we + instantiate the methods, because the constructors may take + additional arguments. */ + if (flag_vtable_thunks >= 2) + TYPE_USES_PVBASES (type) = has_pvbases_p (type, pattern); + /* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC) for this instantiation. */ for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t)) *************** tsubst_decl (t, args, type, in_decl) *** 5716,5724 **** SET_DECL_IMPLICIT_INSTANTIATION (r); register_specialization (r, gen_tmpl, argvec); /* Set the mangled name for R. */ if (DECL_DESTRUCTOR_P (t)) ! DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx); else { /* Instantiations of template functions must be mangled --- 5741,5757 ---- SET_DECL_IMPLICIT_INSTANTIATION (r); register_specialization (r, gen_tmpl, argvec); + + if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r)) + { + maybe_retrofit_in_chrg (r); + grok_ctor_properties (ctx, r); + } + /* Set the mangled name for R. */ if (DECL_DESTRUCTOR_P (t)) ! DECL_ASSEMBLER_NAME (r) = ! build_destructor_name (ctx, DECL_DESTRUCTOR_FOR_PVBASE_P (r)); else { /* Instantiations of template functions must be mangled *************** tsubst_decl (t, args, type, in_decl) *** 5761,5771 **** --- 5794,5807 ---- in_decl); } + #if 0 + /* This has now moved further up. */ if (DECL_CONSTRUCTOR_P (r)) { maybe_retrofit_in_chrg (r); grok_ctor_properties (ctx, r); } + #endif if (IDENTIFIER_OPNAME_P (DECL_NAME (r))) grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r)); } diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/rtti.c gcc-2.95.3/gcc/cp/rtti.c *** gcc-2.95.2/gcc/cp/rtti.c Tue Apr 27 10:41:31 1999 --- gcc-2.95.3/gcc/cp/rtti.c Thu Apr 20 06:13:25 2000 *************** get_tinfo_var (type) *** 363,370 **** return tdecl; } tree ! get_tinfo_fn (type) tree type; { tree name; --- 363,381 ---- return tdecl; } + /* Returns the decl for a function which will return a type_info node for + TYPE. This version does not mark the function used, for use in + set_rtti_entry; for the vtable case, we'll get marked in + finish_vtable_vardecl, when we know that we want to be emitted. + + We do this to avoid emitting the tinfo node itself, since we don't + currently support DECL_DEFER_OUTPUT for variables. Also, we don't + associate constant pools with their functions properly, so we would + emit string constants and such even though we don't emit the actual + function. When those bugs are fixed, this function should go away. */ + tree ! get_tinfo_fn_unused (type) tree type; { tree name; *************** get_tinfo_fn (type) *** 393,402 **** pushdecl_top_level (d); make_function_rtl (d); - mark_used (d); mark_inline_for_output (d); pop_obstacks (); return d; } --- 404,423 ---- pushdecl_top_level (d); make_function_rtl (d); mark_inline_for_output (d); pop_obstacks (); + return d; + } + + /* Likewise, but also mark it used. Called by various EH and RTTI code. */ + + tree + get_tinfo_fn (type) + tree type; + { + tree d = get_tinfo_fn_unused (type); + mark_used (d); return d; } diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/search.c gcc-2.95.3/gcc/cp/search.c *** gcc-2.95.2/gcc/cp/search.c Tue Jun 15 17:48:27 1999 --- gcc-2.95.3/gcc/cp/search.c Wed Apr 12 07:53:34 2000 *************** static int protected_accessible_p PROTO *** 151,156 **** --- 151,159 ---- static int friend_accessible_p PROTO ((tree, tree, tree, tree)); static void setup_class_bindings PROTO ((tree, int)); static int template_self_reference_p PROTO ((tree, tree)); + static void expand_direct_vtbls_init_thunks PROTO((tree, tree, int)); + static void expand_indirect_vtbls_init_thunks PROTO((tree, tree, tree)); + /* Allocate a level of searching. */ *************** fixup_virtual_upcast_offsets (real_binfo *** 2626,2631 **** --- 2629,2745 ---- } } + /* Emit initialization of vfields of BASE, where the complete object + is pointed to by decl_ptr. DO_SELF indicates we have to do our own + vfield, otherwise only proceed to our own direct non-virtual bases. */ + + static void + expand_direct_vtbls_init_thunks (base, decl_ptr, do_self) + tree base, decl_ptr; + int do_self; + { + tree addr, expr; + tree type = BINFO_TYPE (base); + tree binfos = BINFO_BASETYPES (base); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree vlist = lookup_name (vlist_identifier, 0); + int in_dtor = DECL_DESTRUCTOR_FOR_PVBASE_P (current_function_decl); + + my_friendly_assert (vlist != NULL_TREE, 990320); + + if (in_dtor) + /* In the destructor, we find the vfield pointers for the bases in + reverse order, before we find our own vfield pointer. */ + for (i = n_baselinks - 1; i >= 0; i--) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable + = i != CLASSTYPE_VFIELD_PARENT (type); + if (! TREE_VIA_VIRTUAL (base_binfo)) + expand_direct_vtbls_init_thunks (base_binfo, decl_ptr, + is_not_base_vtable); + } + + if (do_self && CLASSTYPE_VFIELDS (type)) + { + addr = build_vbase_path (PLUS_EXPR, build_pointer_type (type), + decl_ptr, base, 1); + addr = build_indirect_ref (addr, "vptr"); + addr = build_vfield_ref (addr, type); + + /* In a destructor, we decrease the vlist before we retrieve the + value. In a constructor, we increase the vlist after we + retrieve the value. */ + if (in_dtor) + { + expr = build_binary_op (MINUS_EXPR, vlist, integer_one_node); + expr = build_modify_expr (vlist, NOP_EXPR, expr); + expand_expr_stmt (expr); + } + + /* Store the next vptr into the vbase's vptr. */ + expr = build_indirect_ref (vlist, "__vlist"); + expr = convert_force (TREE_TYPE (addr), expr, 0); + expr = build_modify_expr (addr, NOP_EXPR, expr); + expand_expr_stmt (expr); + + /* Advance the vlist. */ + if (!in_dtor) + { + expr = build_binary_op (PLUS_EXPR, vlist, integer_one_node); + expr = build_modify_expr (vlist, NOP_EXPR, expr); + expand_expr_stmt (expr); + } + } + + if (!in_dtor) + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable = i != CLASSTYPE_VFIELD_PARENT (type); + if (! TREE_VIA_VIRTUAL (base_binfo)) + expand_direct_vtbls_init_thunks (base_binfo, decl_ptr, + is_not_base_vtable); + } + } + + /* Like expand_indirect_vtbls_init below, but based on the vtable list + passed to the constructor. */ + + static void + expand_indirect_vtbls_init_thunks (binfo, true_exp, decl_ptr) + tree binfo; + tree true_exp, decl_ptr; + { + tree type = BINFO_TYPE (binfo); + tree vbases = CLASSTYPE_VBASECLASSES (type); + struct vbase_info vi; + + vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) + : decl_ptr); + vi.vbase_types = vbases; + + dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi); + + /* Initialized with vtables of type TYPE. */ + for (; vbases; vbases = TREE_CHAIN (vbases)) + { + tree addr; + + if (!CLASSTYPE_VFIELD (BINFO_TYPE (vbases))) + /* This vbase doesn't have a vptr of its own. */ + /* FIXME: check */ + continue; + + addr = convert_pointer_to_vbase (TREE_TYPE (vbases), decl_ptr); + expand_direct_vtbls_init_thunks (TYPE_BINFO (BINFO_TYPE (vbases)), + addr, 1); + + } + + dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0); + } + /* Build a COMPOUND_EXPR which when expanded will generate the code needed to initialize all the virtual function table slots of all the virtual baseclasses. MAIN_BINFO is the binfo which determines *************** expand_indirect_vtbls_init (binfo, true_ *** 2656,2661 **** --- 2770,2781 ---- temporary space as unavailable prevents this from happening. */ mark_all_temps_used(); + + if (TYPE_USES_PVBASES (type)) + { + expand_indirect_vtbls_init_thunks (binfo, true_exp, decl_ptr); + return; + } if (TYPE_USES_VIRTUAL_BASECLASSES (type)) { diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/gcc/cp/typeck2.c gcc-2.95.3/gcc/cp/typeck2.c *** gcc-2.95.2/gcc/cp/typeck2.c Mon Aug 9 07:47:02 1999 --- gcc-2.95.3/gcc/cp/typeck2.c Fri Feb 18 17:19:30 2000 *************** my_friendly_abort (i) *** 344,350 **** else ack ("Internal compiler error %d.", i); ack ("Please submit a full bug report."); ! ack ("See for instructions."); } else error ("confused by earlier errors, bailing out"); --- 344,350 ---- else ack ("Internal compiler error %d.", i); ack ("Please submit a full bug report."); ! ack ("See %s for instructions.", GCCBUGURL); } else error ("confused by earlier errors, bailing out"); *************** my_friendly_abort (i) *** 359,365 **** error ("Internal compiler error %d.", i); error ("Please submit a full bug report."); ! fatal ("See for instructions."); } void --- 359,365 ---- error ("Internal compiler error %d.", i); error ("Please submit a full bug report."); ! fatal ("See %s for instructions.", GCCBUGURL); } void diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/ChangeLog gcc-2.95.3/libio/ChangeLog *** gcc-2.95.2/libio/ChangeLog Mon Oct 25 07:59:15 1999 --- gcc-2.95.3/libio/ChangeLog Fri Mar 16 12:52:19 2001 *************** *** 1,3 **** --- 1,53 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + + 2000-12-10 Bernd Schmidt + + 2000-10-16 Jakub Jelinek + * iostream.cc (ostream::operator<<(double n)) [__GLIBC_MINOR__ >= 2]: + Initialize new fields wide and i18n of struct printf_info. + (ostream::operator<<(long double n)) [__GLIBC_MINOR__ >= 2]: + Likewise. + + 2000-09-23 Franz Sirl + * stdstreams.cc: Include , not "libio.h". + * iolibio.h: Likewise. + (_IO_pos_BAD): Use _IO_off_t instead of _IO_fpos_t. + * libio.h (_IO_USER_LOCK): Define. + + 1999-12-22 Jakub Jelinek + * libio.h (_IO_cookie_io_functions_t): Use _IO_off_t instead of + _IO_fpos_t. + (_IO_seekoff, _IO_seekpos): Likewise. Use _IO_off64_t instead of + _IO_fpos64_t. + * libioP.h (_IO_seekoff_t, _IO_seekpos_t, _IO_seek_t): Likewise. + (_IO_seekoff, _IO_seekpos): Likewise. + (_IO_default_seekoff, _IO_default_seekpos): Likewise. + (_IO_default_seek): Likewise. + (_IO_file_seekoff, _IO_file_seek, _IO_str_seekoff): Likewise. + * streambuf.h (streampos): Typedef to _IO_off_t resp. _IO_off64_t. + * parsestream.h (class parsebuf::pos_at_line_start): Change type + to _IO_off_t. + + 2000-01-28 Martin v. Löwis + + * fstream.h (ifstream::ifstream): Add ios::in to mode. + (ifstream::open): Likewise. + (ofstream::ofstream): Add ios::out to mode. + (ofstream::open): Likewise. + + 1999-12-21 Martin v. Löwis + + * filebuf.cc (open): Support ios::ate if _G_HAVE_IO_FILE_OPEN. + Remove seek for ios::app if not. + + 1999-12-14 Martin v. Löwis + + * strstream.h (strstreambuf::streambuf): Rename parameters to + avoid shadow warning. + * stream.h (WS): Likewise. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/filebuf.cc gcc-2.95.3/libio/filebuf.cc *** gcc-2.95.2/libio/filebuf.cc Tue Feb 24 20:09:49 1998 --- gcc-2.95.3/libio/filebuf.cc Tue Dec 21 18:13:32 1999 *************** *** 1,5 **** /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993, 1995 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the --- 1,5 ---- /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993, 1995, 1999 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the *************** filebuf* filebuf::open(const char *filen *** 112,126 **** if (mode & (int)ios::noreplace) posix_mode |= O_EXCL; #if _G_HAVE_IO_FILE_OPEN ! return (filebuf*)_IO_file_open (this, filename, posix_mode, prot, ! read_write, 0); #else int fd = ::open(filename, posix_mode, prot); if (fd < 0) return NULL; _fileno = fd; xsetflags(read_write, _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); ! if (mode & (ios::ate|ios::app)) { if (pubseekoff(0, ios::end) == EOF) return NULL; } --- 112,134 ---- if (mode & (int)ios::noreplace) posix_mode |= O_EXCL; #if _G_HAVE_IO_FILE_OPEN ! if (!_IO_file_open (this, filename, posix_mode, prot, ! read_write, 0)) ! return NULL; ! if (mode & ios::ate) { ! if (pubseekoff(0, ios::end) == EOF) { ! _IO_un_link (this); ! return NULL; ! } ! } ! return this; #else int fd = ::open(filename, posix_mode, prot); if (fd < 0) return NULL; _fileno = fd; xsetflags(read_write, _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); ! if (mode & ios::ate) { if (pubseekoff(0, ios::end) == EOF) return NULL; } diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/fstream.h gcc-2.95.3/libio/fstream.h *** gcc-2.95.2/libio/fstream.h Thu Aug 21 23:58:15 1997 --- gcc-2.95.3/libio/fstream.h Fri Jan 28 09:54:58 2000 *************** *** 1,5 **** /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the --- 1,5 ---- /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993, 2000 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the *************** class ifstream : public fstreambase, pub *** 62,70 **** ifstream(int fd) : fstreambase(fd) { } ifstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ ifstream(const char *name, int mode=ios::in, int prot=0664) ! : fstreambase(name, mode, prot) { } void open(const char *name, int mode=ios::in, int prot=0664) ! { fstreambase::open(name, mode, prot); } }; class ofstream : public fstreambase, public ostream { --- 62,70 ---- ifstream(int fd) : fstreambase(fd) { } ifstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ ifstream(const char *name, int mode=ios::in, int prot=0664) ! : fstreambase(name, mode | ios::in, prot) { } void open(const char *name, int mode=ios::in, int prot=0664) ! { fstreambase::open(name, mode | ios::in, prot); } }; class ofstream : public fstreambase, public ostream { *************** class ofstream : public fstreambase, pub *** 73,81 **** ofstream(int fd) : fstreambase(fd) { } ofstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ ofstream(const char *name, int mode=ios::out, int prot=0664) ! : fstreambase(name, mode, prot) { } void open(const char *name, int mode=ios::out, int prot=0664) ! { fstreambase::open(name, mode, prot); } }; class fstream : public fstreambase, public iostream { --- 73,81 ---- ofstream(int fd) : fstreambase(fd) { } ofstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ ofstream(const char *name, int mode=ios::out, int prot=0664) ! : fstreambase(name, mode | ios::out, prot) { } void open(const char *name, int mode=ios::out, int prot=0664) ! { fstreambase::open(name, mode | ios::out, prot); } }; class fstream : public fstreambase, public iostream { diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/iolibio.h gcc-2.95.3/libio/iolibio.h *** gcc-2.95.2/libio/iolibio.h Tue Feb 24 20:09:50 1998 --- gcc-2.95.3/libio/iolibio.h Sun Dec 10 17:45:08 2000 *************** *** 1,4 **** ! #include "libio.h" /* These emulate stdio functionality, but with a different name (_IO_ungetc instead of ungetc), and using _IO_FILE instead of FILE. */ --- 1,4 ---- ! #include /* These emulate stdio functionality, but with a different name (_IO_ungetc instead of ungetc), and using _IO_FILE instead of FILE. */ *************** extern int _IO_obstack_vprintf __P ((str *** 38,44 **** _IO_va_list)); extern int _IO_obstack_printf __P ((struct obstack *, const char *, ...)); #ifndef _IO_pos_BAD ! #define _IO_pos_BAD ((_IO_fpos_t)(-1)) #endif #define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN)) #define _IO_fseek(__fp, __offset, __whence) \ --- 38,48 ---- _IO_va_list)); extern int _IO_obstack_printf __P ((struct obstack *, const char *, ...)); #ifndef _IO_pos_BAD ! # if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! # define _IO_pos_BAD ((_IO_off64_t) -1) ! # else ! # define _IO_pos_BAD ((_IO_off_t) -1) ! # endif #endif #define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN)) #define _IO_fseek(__fp, __offset, __whence) \ diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/iostream.cc gcc-2.95.3/libio/iostream.cc *** gcc-2.95.2/libio/iostream.cc Sat Aug 7 07:01:46 1999 --- gcc-2.95.3/libio/iostream.cc Sun Dec 10 17:45:08 2000 *************** *** 1,5 **** /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993, 1997 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the --- 1,5 ---- /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993, 1997, 2000 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the *************** ostream& ostream::operator<<(double n) *** 687,692 **** --- 687,696 ---- /* extra: */ 0, #if __GLIBC_MINOR__ >= 1 /* is_char: */ 0, + #if __GLIBC_MINOR__ >= 2 + /* wide: */ 0, + /* i18n: */ 0, + #endif #endif #endif /* pad: */ fill() *************** ostream& ostream::operator<<(long double *** 793,798 **** --- 797,806 ---- /* extra: */ 0, #if __GLIBC_MINOR__ >= 1 /* is_char: */ 0, + #if __GLIBC_MINOR__ >= 2 + /* wide: */ 0, + /* i18n: */ 0, + #endif #endif #endif /* pad: */ fill() diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/libio.h gcc-2.95.3/libio/libio.h *** gcc-2.95.2/libio/libio.h Mon Jun 29 19:06:26 1998 --- gcc-2.95.3/libio/libio.h Sun Dec 10 17:45:08 2000 *************** *** 136,141 **** --- 136,142 ---- #define _IO_IS_APPENDING 0x1000 #define _IO_IS_FILEBUF 0x2000 #define _IO_BAD_SEEN 0x4000 + #define _IO_USER_LOCK 0x8000 /* These are "formatting flags" matching the iostream fmtflags enum values. */ #define _IO_SKIPWS 01 *************** typedef struct *** 277,283 **** { _IO_ssize_t (*read) __PMT ((struct _IO_FILE *, void *, _IO_ssize_t)); _IO_ssize_t (*write) __PMT ((struct _IO_FILE *, const void *, _IO_ssize_t)); ! _IO_fpos_t (*seek) __PMT ((struct _IO_FILE *, _IO_off_t, int)); int (*close) __PMT ((struct _IO_FILE *)); } _IO_cookie_io_functions_t; --- 278,284 ---- { _IO_ssize_t (*read) __PMT ((struct _IO_FILE *, void *, _IO_ssize_t)); _IO_ssize_t (*write) __PMT ((struct _IO_FILE *, const void *, _IO_ssize_t)); ! _IO_off_t (*seek) __PMT ((struct _IO_FILE *, _IO_off_t, int)); int (*close) __PMT ((struct _IO_FILE *)); } _IO_cookie_io_functions_t; *************** extern _IO_ssize_t _IO_padn __P ((_IO_FI *** 348,358 **** extern _IO_size_t _IO_sgetn __P ((_IO_FILE *, void *, _IO_size_t)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_fpos64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_fpos64_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos64_t, int)); #else ! extern _IO_fpos_t _IO_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_fpos_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos_t, int)); #endif extern void _IO_free_backup_area __P ((_IO_FILE *)); --- 349,359 ---- extern _IO_size_t _IO_sgetn __P ((_IO_FILE *, void *, _IO_size_t)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_off64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_off64_t _IO_seekpos __P ((_IO_FILE *, _IO_off64_t, int)); #else ! extern _IO_off_t _IO_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_off_t _IO_seekpos __P ((_IO_FILE *, _IO_off_t, int)); #endif extern void _IO_free_backup_area __P ((_IO_FILE *)); diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/libioP.h gcc-2.95.3/libio/libioP.h *** gcc-2.95.2/libio/libioP.h Mon May 17 23:58:56 1999 --- gcc-2.95.3/libio/libioP.h Sun Dec 10 17:45:08 2000 *************** typedef _IO_size_t (*_IO_xsgetn_t) __PMT *** 146,155 **** It matches the streambuf::seekoff virtual function. It is also used for the ANSI fseek function. */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! typedef _IO_fpos64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF, int DIR, int MODE)); #else ! typedef _IO_fpos_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off_t OFF, int DIR, int MODE)); #endif #define _IO_SEEKOFF(FP, OFF, DIR, MODE) JUMP3 (__seekoff, FP, OFF, DIR, MODE) --- 146,155 ---- It matches the streambuf::seekoff virtual function. It is also used for the ANSI fseek function. */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! typedef _IO_off64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF, int DIR, int MODE)); #else ! typedef _IO_off_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off_t OFF, int DIR, int MODE)); #endif #define _IO_SEEKOFF(FP, OFF, DIR, MODE) JUMP3 (__seekoff, FP, OFF, DIR, MODE) *************** typedef _IO_fpos_t (*_IO_seekoff_t) __PM *** 160,168 **** It is also used for the ANSI fgetpos and fsetpos functions. */ /* The _IO_seek_cur and _IO_seek_end options are not allowed. */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! typedef _IO_fpos64_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_fpos64_t, int)); #else ! typedef _IO_fpos_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_fpos_t, int)); #endif #define _IO_SEEKPOS(FP, POS, FLAGS) JUMP2 (__seekpos, FP, POS, FLAGS) --- 160,168 ---- It is also used for the ANSI fgetpos and fsetpos functions. */ /* The _IO_seek_cur and _IO_seek_end options are not allowed. */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! typedef _IO_off64_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_off64_t, int)); #else ! typedef _IO_off_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_off_t, int)); #endif #define _IO_SEEKPOS(FP, POS, FLAGS) JUMP2 (__seekpos, FP, POS, FLAGS) *************** typedef _IO_ssize_t (*_IO_write_t) __PMT *** 213,221 **** It matches the streambuf::sys_seek virtual function, which is specific to this implementation. */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! typedef _IO_fpos64_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off64_t, int)); #else ! typedef _IO_fpos_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off_t, int)); #endif #define _IO_SYSSEEK(FP, OFFSET, MODE) JUMP2 (__seek, FP, OFFSET, MODE) --- 213,221 ---- It matches the streambuf::sys_seek virtual function, which is specific to this implementation. */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! typedef _IO_off64_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off64_t, int)); #else ! typedef _IO_off_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off_t, int)); #endif #define _IO_SYSSEEK(FP, OFFSET, MODE) JUMP2 (__seek, FP, OFFSET, MODE) *************** struct _IO_FILE_plus *** 298,308 **** /* Generic functions */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_fpos64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_fpos64_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos64_t, int)); #else ! extern _IO_fpos_t _IO_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_fpos_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos_t, int)); #endif extern void _IO_switch_to_main_get_area __P ((_IO_FILE *)); --- 298,308 ---- /* Generic functions */ #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_off64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_off64_t _IO_seekpos __P ((_IO_FILE *, _IO_off64_t, int)); #else ! extern _IO_off_t _IO_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_off_t _IO_seekpos __P ((_IO_FILE *, _IO_off_t, int)); #endif extern void _IO_switch_to_main_get_area __P ((_IO_FILE *)); *************** extern _IO_size_t _IO_default_xsputn __P *** 340,361 **** _IO_size_t)); extern _IO_size_t _IO_default_xsgetn __P ((_IO_FILE *, void *, _IO_size_t)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_fpos64_t _IO_default_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_fpos64_t _IO_default_seekpos __P ((_IO_FILE *, ! _IO_fpos64_t, int)); #else ! extern _IO_fpos_t _IO_default_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_fpos_t _IO_default_seekpos __P ((_IO_FILE *, _IO_fpos_t, int)); #endif extern _IO_ssize_t _IO_default_write __P ((_IO_FILE *, const void *, _IO_ssize_t)); extern _IO_ssize_t _IO_default_read __P ((_IO_FILE *, void *, _IO_ssize_t)); extern int _IO_default_stat __P ((_IO_FILE *, void *)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_fpos64_t _IO_default_seek __P ((_IO_FILE *, _IO_off64_t, int)); #else ! extern _IO_fpos_t _IO_default_seek __P ((_IO_FILE *, _IO_off_t, int)); #endif extern int _IO_default_sync __P ((_IO_FILE *)); #define _IO_default_close ((_IO_close_t) _IO_default_sync) --- 340,361 ---- _IO_size_t)); extern _IO_size_t _IO_default_xsgetn __P ((_IO_FILE *, void *, _IO_size_t)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_off64_t _IO_default_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_off64_t _IO_default_seekpos __P ((_IO_FILE *, ! _IO_off64_t, int)); #else ! extern _IO_off_t _IO_default_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_off_t _IO_default_seekpos __P ((_IO_FILE *, _IO_off_t, int)); #endif extern _IO_ssize_t _IO_default_write __P ((_IO_FILE *, const void *, _IO_ssize_t)); extern _IO_ssize_t _IO_default_read __P ((_IO_FILE *, void *, _IO_ssize_t)); extern int _IO_default_stat __P ((_IO_FILE *, void *)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_off64_t _IO_default_seek __P ((_IO_FILE *, _IO_off64_t, int)); #else ! extern _IO_off_t _IO_default_seek __P ((_IO_FILE *, _IO_off_t, int)); #endif extern int _IO_default_sync __P ((_IO_FILE *)); #define _IO_default_close ((_IO_close_t) _IO_default_sync) *************** extern void _IO_flush_all_linebuffered _ *** 389,399 **** extern int _IO_file_doallocate __P ((_IO_FILE *)); extern _IO_FILE* _IO_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_fpos64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_fpos64_t _IO_file_seek __P ((_IO_FILE *, _IO_off64_t, int)); #else ! extern _IO_fpos_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_fpos_t _IO_file_seek __P ((_IO_FILE *, _IO_off_t, int)); #endif extern _IO_size_t _IO_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t)); extern int _IO_file_stat __P ((_IO_FILE *, void *)); --- 389,399 ---- extern int _IO_file_doallocate __P ((_IO_FILE *)); extern _IO_FILE* _IO_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_off64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); ! extern _IO_off64_t _IO_file_seek __P ((_IO_FILE *, _IO_off64_t, int)); #else ! extern _IO_off_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); ! extern _IO_off_t _IO_file_seek __P ((_IO_FILE *, _IO_off_t, int)); #endif extern _IO_size_t _IO_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t)); extern int _IO_file_stat __P ((_IO_FILE *, void *)); *************** extern int _IO_str_underflow __P ((_IO_F *** 427,435 **** extern int _IO_str_overflow __P ((_IO_FILE *, int)); extern int _IO_str_pbackfail __P ((_IO_FILE *, int)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_fpos64_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); #else ! extern _IO_fpos_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); #endif extern void _IO_str_finish __P ((_IO_FILE *, int)); --- 427,435 ---- extern int _IO_str_overflow __P ((_IO_FILE *, int)); extern int _IO_str_pbackfail __P ((_IO_FILE *, int)); #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! extern _IO_off64_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); #else ! extern _IO_off_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off_t, int, int)); #endif extern void _IO_str_finish __P ((_IO_FILE *, int)); *************** extern int _IO_vscanf __P ((const char * *** 544,555 **** where an _IO_fpos_t is a struct. Note that _IO_off_t must be an integral type. */ ! /* _IO_pos_BAD is an _IO_fpos_t value indicating error, unknown, or EOF. */ #ifndef _IO_pos_BAD # if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! # define _IO_pos_BAD ((_IO_fpos64_t) -1) # else ! # define _IO_pos_BAD ((_IO_fpos_t) -1) # endif #endif /* _IO_pos_as_off converts an _IO_fpos_t value to an _IO_off_t value. */ --- 544,555 ---- where an _IO_fpos_t is a struct. Note that _IO_off_t must be an integral type. */ ! /* _IO_pos_BAD is an _IO_off_t value indicating error, unknown, or EOF. */ #ifndef _IO_pos_BAD # if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 ! # define _IO_pos_BAD ((_IO_off64_t) -1) # else ! # define _IO_pos_BAD ((_IO_off_t) -1) # endif #endif /* _IO_pos_as_off converts an _IO_fpos_t value to an _IO_off_t value. */ diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/parsestream.h gcc-2.95.3/libio/parsestream.h *** gcc-2.95.2/libio/parsestream.h Thu Aug 21 23:58:20 1997 --- gcc-2.95.3/libio/parsestream.h Sun Dec 10 17:45:08 2000 *************** extern "C++" { *** 42,48 **** class parsebuf : public streambuf { protected: ! _IO_fpos_t pos_at_line_start; long _line_length; unsigned long __line_number; char *buf_start; --- 42,48 ---- class parsebuf : public streambuf { protected: ! _IO_off_t pos_at_line_start; long _line_length; unsigned long __line_number; char *buf_start; diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/stdio/ChangeLog gcc-2.95.3/libio/stdio/ChangeLog *** gcc-2.95.2/libio/stdio/ChangeLog Mon Oct 25 07:59:15 1999 --- gcc-2.95.3/libio/stdio/ChangeLog Fri Mar 16 12:52:19 2001 *************** *** 1,3 **** --- 1,7 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/stdstreams.cc gcc-2.95.3/libio/stdstreams.cc *** gcc-2.95.2/libio/stdstreams.cc Thu Aug 21 23:58:21 1997 --- gcc-2.95.3/libio/stdstreams.cc Sun Dec 10 17:45:08 2000 *************** the executable file might be covered by *** 36,42 **** // then we don't need to, since in that case stdin/stdout/stderr // are identical to _IO_stdin/_IO_stdout/_IO_stderr. ! #include "libio.h" #ifdef _STDIO_USES_IOSTREAM #define CIN_SBUF _IO_stdin_ --- 36,42 ---- // then we don't need to, since in that case stdin/stdout/stderr // are identical to _IO_stdin/_IO_stdout/_IO_stderr. ! #include #ifdef _STDIO_USES_IOSTREAM #define CIN_SBUF _IO_stdin_ diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/stream.h gcc-2.95.3/libio/stream.h *** gcc-2.95.2/libio/stream.h Thu Aug 21 23:58:21 1997 --- gcc-2.95.3/libio/stream.h Wed Dec 15 07:47:38 1999 *************** *** 1,5 **** /* ! Copyright (C) 1993 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the --- 1,5 ---- /* ! Copyright (C) 1993, 1999 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the *************** extern char* oct(unsigned int, int=0); *** 53,59 **** char* chr(char ch, int width = 0); char* str(const char* s, int width = 0); ! inline istream& WS(istream& str) { return ws(str); } } // extern "C++" #endif /* !_COMPAT_STREAM_H */ --- 53,59 ---- char* chr(char ch, int width = 0); char* str(const char* s, int width = 0); ! inline istream& WS(istream& __str) { return ws(__str); } } // extern "C++" #endif /* !_COMPAT_STREAM_H */ diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/streambuf.h gcc-2.95.3/libio/streambuf.h *** gcc-2.95.2/libio/streambuf.h Mon Aug 9 01:07:01 1999 --- gcc-2.95.3/libio/streambuf.h Sun Dec 10 17:45:08 2000 *************** class ostream; class streambuf; *** 72,81 **** #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 typedef _IO_off64_t streamoff; ! typedef _IO_fpos64_t streampos; #else typedef _IO_off_t streamoff; ! typedef _IO_fpos_t streampos; #endif typedef _IO_ssize_t streamsize; --- 72,81 ---- #if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001 typedef _IO_off64_t streamoff; ! typedef _IO_off64_t streampos; #else typedef _IO_off_t streamoff; ! typedef _IO_off_t streampos; #endif typedef _IO_ssize_t streamsize; diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/strstream.h gcc-2.95.3/libio/strstream.h *** gcc-2.95.2/libio/strstream.h Thu Aug 21 23:58:22 1997 --- gcc-2.95.3/libio/strstream.h Wed Dec 15 07:47:38 1999 *************** *** 1,5 **** /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the --- 1,5 ---- /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! Copyright (C) 1993, 1999 Free Software Foundation This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or modify it under the *************** class strstreambuf : public streambuf *** 50,57 **** virtual ~strstreambuf(); strstreambuf() { init_dynamic(0, 0); } strstreambuf(int initial_size) { init_dynamic(0, 0, initial_size); } ! strstreambuf(void *(*alloc)(_IO_size_t), void (*free)(void*)) ! { init_dynamic(alloc, free); } strstreambuf(char *ptr, int size, char *pstart = NULL) { init_static(ptr, size, pstart); } strstreambuf(unsigned char *ptr, int size, unsigned char *pstart = NULL) --- 50,57 ---- virtual ~strstreambuf(); strstreambuf() { init_dynamic(0, 0); } strstreambuf(int initial_size) { init_dynamic(0, 0, initial_size); } ! strstreambuf(void *(*__alloc)(_IO_size_t), void (*__free)(void*)) ! { init_dynamic(__alloc, __free); } strstreambuf(char *ptr, int size, char *pstart = NULL) { init_static(ptr, size, pstart); } strstreambuf(unsigned char *ptr, int size, unsigned char *pstart = NULL) diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/tests/ChangeLog gcc-2.95.3/libio/tests/ChangeLog *** gcc-2.95.2/libio/tests/ChangeLog Mon Oct 25 07:59:15 1999 --- gcc-2.95.3/libio/tests/ChangeLog Fri Mar 16 12:52:20 2001 *************** *** 1,3 **** --- 1,7 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libio/testsuite/ChangeLog gcc-2.95.3/libio/testsuite/ChangeLog *** gcc-2.95.2/libio/testsuite/ChangeLog Mon Oct 25 07:59:15 1999 --- gcc-2.95.3/libio/testsuite/ChangeLog Fri Mar 16 12:52:20 2001 *************** *** 1,3 **** --- 1,7 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/ChangeLog gcc-2.95.3/libstdc++/ChangeLog *** gcc-2.95.2/libstdc++/ChangeLog Mon Oct 25 07:59:16 1999 --- gcc-2.95.3/libstdc++/ChangeLog Fri Mar 16 12:52:21 2001 *************** *** 1,3 **** --- 1,59 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + + 2001-01-01 Bernd Schmidt + + 1999-12-07 Martin v. Löwis + * stl_deque.h (_Deque_base::const_iterator): Change third + template argument to pointer type. + Reported by Carlo Wood + + 1999-11-10 Benjamin Kosnik + Matthias Klose + * stl_rope.h: Fix initialization order. + * stl_deque.h: Use static_casts(signed_type). + + 2000-11-24 Magnus Fromreide + + * sstream: Backport libstdc++-V3 sstream to V2. + + 2000-04-24 Magnus Fromreide + + * sstream: New file. + * Makefile.in (HEADERS): Add it. + + 2000-03-12 Gabriel Dos Reis + + * std/bastring.h (basic_string<>::push_back): Define. + + Tue Mar 7 21:37:56 2000 Jeffrey A Law (law@cygnus.com) + + 1999-11-19 Gabriel Dos Reis + * std/valarray_meta.h (_DEFINE_EXPR_UNARY_FUNCTION): Don't forget + to define tanh. + + 1999-11-05 Gabriel Dos Reis + * std/valarray_meta.h (_DEFINE_EXPR_UNARY_FUNCTION): When + building meta-expressions don't forget to take the contained + closures. + + 1999-10-19 Gabriel Dos Reis + * std/valarray_meta.h: (_BinClos::_BinClos): Fix typo. + + 1999-09-17 Gabriel Dos Reis + * std/complext.cc (pow): Don't expect floating point promotion + in presence of template argument deduction. There is no such + thing. + + 2000-02-06 Gabriel Dos Reis + * std/valarray_array.h (__valarray_copy): Fix typo. + + 1999-12-14 Martin v. Löwis + * std/bastring.h (basic_string::basic_string): Rename parameters + to avoid shadow warnings. + * std/bastring.cc (alloc): Likewise. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/Makefile.in gcc-2.95.3/libstdc++/Makefile.in *** gcc-2.95.2/libstdc++/Makefile.in Thu Aug 5 09:00:40 1999 --- gcc-2.95.3/libstdc++/Makefile.in Mon Apr 24 18:34:25 2000 *************** HEADERS= cassert cctype cerrno cfloat ci *** 28,34 **** cwchar cwctype string stdexcept \ algorithm deque functional hash_map hash_set iterator list map \ memory numeric pthread_alloc queue rope set slist stack utility \ ! vector fstream iomanip iostream strstream iosfwd bitset valarray ARLIB = libstdc++.a.$(VERSION) ARLINK = libstdc++.a --- 28,35 ---- cwchar cwctype string stdexcept \ algorithm deque functional hash_map hash_set iterator list map \ memory numeric pthread_alloc queue rope set slist stack utility \ ! vector fstream iomanip iostream strstream iosfwd bitset valarray \ ! sstream ARLIB = libstdc++.a.$(VERSION) ARLINK = libstdc++.a diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/sstream gcc-2.95.3/libstdc++/sstream *** gcc-2.95.2/libstdc++/sstream Thu Jan 1 01:00:00 1970 --- gcc-2.95.3/libstdc++/sstream Mon Dec 4 17:03:42 2000 *************** *** 0 **** --- 1,343 ---- + /* This is part of libio/iostream, providing -*- C++ -*- input/output. + Copyright (C) 2000 Free Software Foundation + + This file is part of the GNU IO Library. This library is free + software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) + any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + + /* Written by Magnus Fromreide (magfr@lysator.liu.se). */ + /* seekoff and ideas for overflow is largely borrowed from libstdc++-v3 */ + + #ifndef __SSTREAM__ + #define __SSTREAM__ + + #include + #include + #include + + namespace std + { + class stringbuf : public streambuf + { + public: + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + + explicit + stringbuf(int which=ios::in|ios::out) + : streambuf(), mode(static_cast(which)), + stream(NULL), stream_len(0) + { + stringbuf_init(); + } + + explicit + stringbuf(const string &str, int which=ios::in|ios::out) + : streambuf(), mode(static_cast(which)), + stream(NULL), stream_len(0) + { + if (mode & (ios::in|ios::out)) + { + stream_len = str.size(); + stream = new char_type[stream_len]; + str.copy(stream, stream_len); + } + stringbuf_init(); + } + + virtual + ~stringbuf() + { + delete[] stream; + } + + string + str() const + { + if (pbase() != 0) + return string(stream, pptr()-pbase()); + else + return string(); + } + + void + str(const string& str) + { + delete[] stream; + stream_len = str.size(); + stream = new char_type[stream_len]; + str.copy(stream, stream_len); + stringbuf_init(); + } + + protected: + // The buffer is already in gptr, so if it ends then it is out of data. + virtual int + underflow() + { + return EOF; + } + + virtual int + overflow(int c = EOF) + { + int res; + if (mode & ios::out) + { + if (c != EOF) + { + streamsize old_stream_len = stream_len; + stream_len += 1; + char_type* new_stream = new char_type[stream_len]; + memcpy(new_stream, stream, old_stream_len); + delete[] stream; + stream = new_stream; + stringbuf_sync(gptr()-eback(), pptr()-pbase()); + sputc(c); + res = c; + } + else + res = EOF; + } + else + res = 0; + return res; + } + + virtual streambuf* + setbuf(char_type* s, streamsize n) + { + if (n != 0) + { + delete[] stream; + stream = new char_type[n]; + memcpy(stream, s, n); + stream_len = n; + stringbuf_sync(0, 0); + } + return this; + } + + virtual pos_type + seekoff(off_type off, ios::seek_dir way, int which = ios::in | ios::out) + { + pos_type ret = pos_type(off_type(-1)); + bool testin = which & ios::in && mode & ios::in; + bool testout = which & ios::out && mode & ios::out; + bool testboth = testin && testout && way != ios::cur; + + if (stream_len && ((testin != testout) || testboth)) + { + char_type* beg = stream; + char_type* curi = NULL; + char_type* curo = NULL; + char_type* endi = NULL; + char_type* endo = NULL; + + if (testin) + { + curi = gptr(); + endi = egptr(); + } + if (testout) + { + curo = pptr(); + endo = epptr(); + } + + off_type newoffi = 0; + off_type newoffo = 0; + if (way == ios::beg) + { + newoffi = beg - curi; + newoffo = beg - curo; + } + else if (way == ios::end) + { + newoffi = endi - curi; + newoffo = endo - curo; + } + + if (testin && newoffi + off + curi - beg >= 0 && + endi - beg >= newoffi + off + curi - beg) + { + gbump(newoffi + off); + ret = pos_type(newoffi + off + curi); + } + if (testout && newoffo + off + curo - beg >= 0 && + endo - beg >= newoffo + off + curo - beg) + { + pbump(newoffo + off); + ret = pos_type(newoffo + off + curo); + } + } + return ret; + } + + virtual pos_type + seekpos(pos_type sp, int which = ios::in | ios::out) + { + pos_type ret = seekoff(sp, ios::beg, which); + return ret; + } + + private: + void + stringbuf_sync(streamsize i, streamsize o) + { + if (mode & ios::in) + setg(stream, stream + i, stream + stream_len); + if (mode & ios::out) + { + setp(stream, stream + stream_len); + pbump(o); + } + } + void + stringbuf_init() + { + if (mode & ios::ate) + stringbuf_sync(0, stream_len); + else + stringbuf_sync(0, 0); + } + + private: + ios::open_mode mode; + char_type* stream; + streamsize stream_len; + }; + + class istringstream : public istream { + public: + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + + explicit + istringstream(int which=ios::in) + : istream(&sb), sb(which | ios::in) + { } + + explicit + istringstream(const string& str, int which=ios::in) + : istream(&sb), sb(str, which | ios::in) + { } + + stringbuf* + rdbuf() const + { + return const_cast(&sb); + } + + string + str() const + { + return rdbuf()->str(); + } + void + str(const string& s) + { + rdbuf()->str(s); + } + private: + stringbuf sb; + }; + + class ostringstream : public ostream { + public: + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + + explicit + ostringstream(int which=ios::out) + : ostream(&sb), sb(which | ios::out) + { } + + explicit + ostringstream(const string& str, int which=ios::out) + : ostream(&sb), sb(str, which | ios::out) + { } + + stringbuf* + rdbuf() const + { + return const_cast(&sb); + } + + string + str() const + { + return rdbuf()->str(); + } + + void str(const string& s) + { + rdbuf()->str(s); + } + private: + stringbuf sb; + }; + + class stringstream : public iostream { + public: + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + + explicit + stringstream(int which=ios::out|ios::in) + : iostream(&sb), sb(which) + { } + + explicit + stringstream(const string& str, int which=ios::out|ios::in) + : iostream(&sb), sb(str, which) + { } + + stringbuf* + rdbuf() const + { + return const_cast(&sb); + } + + string + str() const + { + return rdbuf()->str(); + } + + void + str(const string& s) + { + rdbuf()->str(s); + } + private: + stringbuf sb; + }; + }; + + #endif /* not __STRSTREAM__ */ diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/std/bastring.cc gcc-2.95.3/libstdc++/std/bastring.cc *** gcc-2.95.2/libstdc++/std/bastring.cc Mon Nov 30 09:40:56 1998 --- gcc-2.95.3/libstdc++/std/bastring.cc Wed Dec 15 07:42:12 1999 *************** *** 1,5 **** // Member templates for the -*- C++ -*- string classes. ! // Copyright (C) 1994 Free Software Foundation // This file is part of the GNU ANSI C++ Library. This library is free // software; you can redistribute it and/or modify it under the --- 1,5 ---- // Member templates for the -*- C++ -*- string classes. ! // Copyright (C) 1994, 1999 Free Software Foundation // This file is part of the GNU ANSI C++ Library. This library is free // software; you can redistribute it and/or modify it under the *************** check_realloc (basic_string::size_type s *** 94,107 **** template void basic_string :: ! alloc (basic_string::size_type size, bool save) { ! if (! check_realloc (size)) return; ! Rep *p = Rep::create (size); ! if (save) { p->copy (0, data (), length ()); p->len = length (); --- 94,107 ---- template void basic_string :: ! alloc (basic_string::size_type __size, bool __save) { ! if (! check_realloc (__size)) return; ! Rep *p = Rep::create (__size); ! if (__save) { p->copy (0, data (), length ()); p->len = length (); diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/std/bastring.h gcc-2.95.3/libstdc++/std/bastring.h *** gcc-2.95.2/libstdc++/std/bastring.h Wed Jun 2 00:27:35 1999 --- gcc-2.95.3/libstdc++/std/bastring.h Sun Mar 12 16:36:14 2000 *************** *** 1,5 **** // Main templates for the -*- C++ -*- string classes. ! // Copyright (C) 1994, 1995 Free Software Foundation // This file is part of the GNU ANSI C++ Library. This library is free // software; you can redistribute it and/or modify it under the --- 1,5 ---- // Main templates for the -*- C++ -*- string classes. ! // Copyright (C) 1994, 1995, 1999 Free Software Foundation // This file is part of the GNU ANSI C++ Library. This library is free // software; you can redistribute it and/or modify it under the *************** public: *** 180,190 **** : dat (nilRep.grab ()) { assign (n, c); } #ifdef __STL_MEMBER_TEMPLATES template ! basic_string(InputIterator begin, InputIterator end) #else ! basic_string(const_iterator begin, const_iterator end) #endif ! : dat (nilRep.grab ()) { assign (begin, end); } ~basic_string () { rep ()->release (); } --- 180,190 ---- : dat (nilRep.grab ()) { assign (n, c); } #ifdef __STL_MEMBER_TEMPLATES template ! basic_string(InputIterator __begin, InputIterator __end) #else ! basic_string(const_iterator __begin, const_iterator __end) #endif ! : dat (nilRep.grab ()) { assign (__begin, __end); } ~basic_string () { rep ()->release (); } *************** public: *** 208,213 **** --- 208,216 ---- #endif { return replace (iend (), iend (), first, last); } + void push_back(charT __c) + { append(1, __c); } + basic_string& assign (const basic_string& str, size_type pos = 0, size_type n = npos) { return replace (0, npos, str, pos, n); } diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/std/complext.cc gcc-2.95.3/libstdc++/std/complext.cc *** gcc-2.95.2/libstdc++/std/complext.cc Fri Oct 10 07:56:55 1997 --- gcc-2.95.3/libstdc++/std/complext.cc Wed Mar 8 04:38:45 2000 *************** pow (const complex& xin, int y) *** 236,242 **** if (y < 0) { y = -y; ! x = 1/x; } for (;;) { --- 236,242 ---- if (y < 0) { y = -y; ! x = FLOAT(1)/x; } for (;;) { diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/std/valarray_array.h gcc-2.95.3/libstdc++/std/valarray_array.h *** gcc-2.95.2/libstdc++/std/valarray_array.h Fri Jun 4 22:17:45 1999 --- gcc-2.95.3/libstdc++/std/valarray_array.h Sun Feb 6 10:42:58 2000 *************** template *** 73,79 **** inline void __valarray_copy (const _Tp* __restrict__ __a, size_t __n, size_t __s, _Tp* __restrict__ __b) ! { for (size_t __i=0; __i<__n; ++__i, ++__b, __a += __s) *__b += *__a; } // copy plain __a[<__n>] in strided __b[<__n : __s>] template --- 73,79 ---- inline void __valarray_copy (const _Tp* __restrict__ __a, size_t __n, size_t __s, _Tp* __restrict__ __b) ! { for (size_t __i=0; __i<__n; ++__i, ++__b, __a += __s) *__b = *__a; } // copy plain __a[<__n>] in strided __b[<__n : __s>] template diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/std/valarray_meta.h gcc-2.95.3/libstdc++/std/valarray_meta.h *** gcc-2.95.2/libstdc++/std/valarray_meta.h Fri Jun 4 22:17:47 1999 --- gcc-2.95.3/libstdc++/std/valarray_meta.h Wed Mar 8 04:38:45 2000 *************** struct _BinClos<_Oper,_ValArray,_Expr,t *** 449,455 **** typedef _BinBase<_Oper,valarray<_Tp>,_Dom> _Base; typedef typename _Base::value_type value_type; ! _BinClos (const valarray<_Tp> __e1, const _Dom& __e2) : _Base (__e1, __e2) {} }; --- 449,455 ---- typedef _BinBase<_Oper,valarray<_Tp>,_Dom> _Base; typedef typename _Base::value_type value_type; ! _BinClos (const valarray<_Tp>& __e1, const _Dom& __e2) : _Base (__e1, __e2) {} }; *************** _Name(const _Expr<_Dom,typename _Dom::va *** 917,923 **** { \ typedef typename _Dom::value_type _Tp; \ typedef _UnFunClos<_Expr,_Dom> _Closure; \ ! return _Expr<_Closure,_Tp> (_Closure (__e, (_Tp(*)(_Tp))(&_Name))); \ } \ \ template \ --- 917,923 ---- { \ typedef typename _Dom::value_type _Tp; \ typedef _UnFunClos<_Expr,_Dom> _Closure; \ ! return _Expr<_Closure,_Tp>(_Closure(__e(), (_Tp(*)(_Tp))(&_Name))); \ } \ \ template \ *************** _Name(const valarray<_Tp>& __v) *** 936,942 **** _DEFINE_EXPR_UNARY_FUNCTION(sin) _DEFINE_EXPR_UNARY_FUNCTION(asin) _DEFINE_EXPR_UNARY_FUNCTION(sinh) ! _DEFINE_EXPR_UNARY_FUNCTION(tan) _DEFINE_EXPR_UNARY_FUNCTION(atan) _DEFINE_EXPR_UNARY_FUNCTION(exp) _DEFINE_EXPR_UNARY_FUNCTION(log) --- 936,943 ---- _DEFINE_EXPR_UNARY_FUNCTION(sin) _DEFINE_EXPR_UNARY_FUNCTION(asin) _DEFINE_EXPR_UNARY_FUNCTION(sinh) ! _DEFINE_EXPR_UNARY_FUNCTION(tan) ! _DEFINE_EXPR_UNARY_FUNCTION(tanh) _DEFINE_EXPR_UNARY_FUNCTION(atan) _DEFINE_EXPR_UNARY_FUNCTION(exp) _DEFINE_EXPR_UNARY_FUNCTION(log) diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/stl/ChangeLog gcc-2.95.3/libstdc++/stl/ChangeLog *** gcc-2.95.2/libstdc++/stl/ChangeLog Mon Oct 25 07:59:16 1999 --- gcc-2.95.3/libstdc++/stl/ChangeLog Fri Mar 16 12:52:21 2001 *************** *** 1,3 **** --- 1,12 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + + 1999-11-06 Martin v. Löwis + + * bitset (class bitset): Declare reference as our friend. + * bitset: Include limits.h. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/stl/bitset gcc-2.95.3/libstdc++/stl/bitset *** gcc-2.95.2/libstdc++/stl/bitset Sun Apr 11 23:53:05 1999 --- gcc-2.95.3/libstdc++/stl/bitset Sat Nov 6 16:23:16 1999 *************** *** 36,41 **** --- 36,42 ---- #include // for size_t + #include // for CHAR_BIT #include #include // for invalid_argument, out_of_range, overflow_error #include // for istream, ostream *************** private: *** 568,573 **** --- 569,576 ---- public: // bit reference: + class reference; + friend class reference; class reference { friend class bitset; diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/stl/stl_deque.h gcc-2.95.3/libstdc++/stl/stl_deque.h *** gcc-2.95.2/libstdc++/stl/stl_deque.h Wed Sep 2 18:24:47 1998 --- gcc-2.95.3/libstdc++/stl/stl_deque.h Mon Jan 1 17:48:22 2001 *************** public: *** 342,348 **** _Base; typedef typename _Base::allocator_type allocator_type; typedef _Deque_iterator<_Tp,_Tp&,_Tp*,__bufsiz> iterator; ! typedef _Deque_iterator<_Tp,const _Tp&,const _Tp&, __bufsiz> const_iterator; _Deque_base(const allocator_type& __a, size_t __num_elements) : _Base(__a), _M_start(), _M_finish() --- 342,348 ---- _Base; typedef typename _Base::allocator_type allocator_type; typedef _Deque_iterator<_Tp,_Tp&,_Tp*,__bufsiz> iterator; ! typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*, __bufsiz> const_iterator; _Deque_base(const allocator_type& __a, size_t __num_elements) : _Base(__a), _M_start(), _M_finish() *************** public: // Erase *** 815,821 **** iterator __next = __pos; ++__next; difference_type __index = __pos - _M_start; ! if (__index < (size() >> 1)) { copy_backward(_M_start, __pos, __next); pop_front(); } --- 815,821 ---- iterator __next = __pos; ++__next; difference_type __index = __pos - _M_start; ! if (static_cast(__index) < (size() >> 1)) { copy_backward(_M_start, __pos, __next); pop_front(); } *************** deque<_Tp,_Alloc,__bufsize>::erase(itera *** 1048,1054 **** else { difference_type __n = __last - __first; difference_type __elems_before = __first - _M_start; ! if (__elems_before < (size() - __n) / 2) { copy_backward(_M_start, __first, __last); iterator __new_start = _M_start + __n; destroy(_M_start, __new_start); --- 1048,1054 ---- else { difference_type __n = __last - __first; difference_type __elems_before = __first - _M_start; ! if (static_cast(__elems_before) < (size() - __n) / 2) { copy_backward(_M_start, __first, __last); iterator __new_start = _M_start + __n; destroy(_M_start, __new_start); *************** deque<_Tp,_Alloc,__bufsize>::_M_insert_a *** 1282,1288 **** { difference_type __index = __pos - _M_start; value_type __x_copy = __x; ! if (__index < size() / 2) { push_front(front()); iterator __front1 = _M_start; ++__front1; --- 1282,1288 ---- { difference_type __index = __pos - _M_start; value_type __x_copy = __x; ! if (static_cast(__index) < size() / 2) { push_front(front()); iterator __front1 = _M_start; ++__front1; *************** typename deque<_Tp,_Alloc,__bufsize>::it *** 1311,1317 **** deque<_Tp,_Alloc,__bufsize>::_M_insert_aux(iterator __pos) { difference_type __index = __pos - _M_start; ! if (__index < size() / 2) { push_front(front()); iterator __front1 = _M_start; ++__front1; --- 1311,1317 ---- deque<_Tp,_Alloc,__bufsize>::_M_insert_aux(iterator __pos) { difference_type __index = __pos - _M_start; ! if (static_cast(__index) < size() / 2) { push_front(front()); iterator __front1 = _M_start; ++__front1; *************** deque<_Tp,_Alloc,__bufsize>::_M_insert_a *** 1344,1350 **** const difference_type __elems_before = __pos - _M_start; size_type __length = size(); value_type __x_copy = __x; ! if (__elems_before < __length / 2) { iterator __new_start = _M_reserve_elements_at_front(__n); iterator __old_start = _M_start; __pos = _M_start + __elems_before; --- 1344,1350 ---- const difference_type __elems_before = __pos - _M_start; size_type __length = size(); value_type __x_copy = __x; ! if (static_cast(__elems_before) < __length / 2) { iterator __new_start = _M_reserve_elements_at_front(__n); iterator __old_start = _M_start; __pos = _M_start + __elems_before; *************** deque<_Tp,_Alloc,__bufsize>::_M_insert_a *** 1403,1409 **** { const difference_type __elemsbefore = __pos - _M_start; size_type __length = size(); ! if (__elemsbefore < __length / 2) { iterator __new_start = _M_reserve_elements_at_front(__n); iterator __old_start = _M_start; __pos = _M_start + __elemsbefore; --- 1403,1409 ---- { const difference_type __elemsbefore = __pos - _M_start; size_type __length = size(); ! if (static_cast(__elemsbefore) < __length / 2) { iterator __new_start = _M_reserve_elements_at_front(__n); iterator __old_start = _M_start; __pos = _M_start + __elemsbefore; diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/stl/stl_rope.h gcc-2.95.3/libstdc++/stl/stl_rope.h *** gcc-2.95.2/libstdc++/stl/stl_rope.h Wed Sep 2 18:25:05 1998 --- gcc-2.95.3/libstdc++/stl/stl_rope.h Mon Jan 1 17:48:22 2001 *************** struct _Rope_RopeRep : public _Rope_rep_ *** 386,393 **** typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeRep(_Tag __t, int __d, bool __b, size_t __size, allocator_type __a) ! : _M_tag(__t), _M_depth(__d), _M_is_balanced(__b), _M_c_string(0), ! _Rope_rep_base<_CharT,_Alloc>(__size, __a) { # ifndef __GC _M_refcount = 1; --- 386,393 ---- typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeRep(_Tag __t, int __d, bool __b, size_t __size, allocator_type __a) ! : _Rope_rep_base<_CharT,_Alloc>(__size, __a), ! _M_tag(__t), _M_depth(__d), _M_is_balanced(__b), _M_c_string(0) { # ifndef __GC _M_refcount = 1; *************** struct _Rope_RopeLeaf : public _Rope_Rop *** 562,569 **** /* doesn't matter. */ typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size, allocator_type __a) ! : _M_data(__d) ! , _Rope_RopeRep<_CharT,_Alloc>(_S_leaf, 0, true, __size, __a) { __stl_assert(__size > 0); if (_S_is_basic_char_type((_CharT *)0)) { --- 562,569 ---- /* doesn't matter. */ typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size, allocator_type __a) ! : _Rope_RopeRep<_CharT,_Alloc>(_S_leaf, 0, true, __size, __a), ! _M_data(__d) { __stl_assert(__size > 0); if (_S_is_basic_char_type((_CharT *)0)) { *************** struct _Rope_RopeConcatenation : public *** 593,602 **** _Rope_RopeConcatenation(_Rope_RopeRep<_CharT,_Alloc>* __l, _Rope_RopeRep<_CharT,_Alloc>* __r, allocator_type __a) ! : _M_left(__l), _M_right(__r) ! , _Rope_RopeRep<_CharT,_Alloc>( _S_concat, max(__l->_M_depth, __r->_M_depth) + 1, false, ! __l->_M_size + __r->_M_size, __a) {} # ifndef __GC ~_Rope_RopeConcatenation() { --- 593,602 ---- _Rope_RopeConcatenation(_Rope_RopeRep<_CharT,_Alloc>* __l, _Rope_RopeRep<_CharT,_Alloc>* __r, allocator_type __a) ! : _Rope_RopeRep<_CharT,_Alloc>( _S_concat, max(__l->_M_depth, __r->_M_depth) + 1, false, ! __l->_M_size + __r->_M_size, __a), ! _M_left(__l), _M_right(__r) {} # ifndef __GC ~_Rope_RopeConcatenation() { *************** struct _Rope_RopeFunction : public _Rope *** 629,639 **** typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size, bool __d, allocator_type __a) ! : _M_fn(__f) # ifndef __GC , _M_delete_when_done(__d) # endif ! , _Rope_RopeRep<_CharT,_Alloc>(_S_function, 0, true, __size, __a) { __stl_assert(__size > 0); # ifdef __GC if (__d) { --- 629,640 ---- typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size, bool __d, allocator_type __a) ! :_Rope_RopeRep<_CharT,_Alloc>(_S_function, 0, true, __size, __a), ! _M_fn(__f) # ifndef __GC , _M_delete_when_done(__d) # endif ! { __stl_assert(__size > 0); # ifdef __GC if (__d) { *************** struct _Rope_RopeSubstring : public _Rop *** 693,701 **** typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s, size_t __l, allocator_type __a) ! : _M_base(__b) , _M_start(__s) - , _Rope_RopeFunction<_CharT,_Alloc>(this, __l, false, __a) { __stl_assert(__l > 0); __stl_assert(__s + __l <= __b->_M_size); --- 694,701 ---- typedef _Rope_rep_base<_CharT,_Alloc>::allocator_type allocator_type; _Rope_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s, size_t __l, allocator_type __a) ! : _Rope_RopeFunction<_CharT,_Alloc>(this, __l, false, __a), _M_base(__b) , _M_start(__s) { __stl_assert(__l > 0); __stl_assert(__s + __l <= __b->_M_size); *************** class _Rope_char_ref_proxy { *** 766,781 **** _My_rope* _M_root; // The whole rope. public: _Rope_char_ref_proxy(_My_rope* __r, size_t __p) : ! _M_pos(__p), _M_root(__r), _M_current_valid(false) {} _Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x) : ! _M_pos(__x._M_pos), _M_root(__x._M_root), _M_current_valid(false) {} // Don't preserve cache if the reference can outlive the // expression. We claim that's not possible without calling // a copy constructor or generating reference to a proxy // reference. We declare the latter to have undefined semantics. _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c) : ! _M_pos(__p), _M_root(__r), _M_current(__c), _M_current_valid(true) {} inline operator _CharT () const; _Rope_char_ref_proxy& operator= (_CharT __c); _Rope_char_ptr_proxy<_CharT,_Alloc> operator& () const; --- 766,781 ---- _My_rope* _M_root; // The whole rope. public: _Rope_char_ref_proxy(_My_rope* __r, size_t __p) : ! _M_pos(__p), _M_current_valid(false), _M_root(__r) {} _Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x) : ! _M_pos(__x._M_pos), _M_current_valid(false), _M_root(__x._M_root) {} // Don't preserve cache if the reference can outlive the // expression. We claim that's not possible without calling // a copy constructor or generating reference to a proxy // reference. We declare the latter to have undefined semantics. _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c) : ! _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) {} inline operator _CharT () const; _Rope_char_ref_proxy& operator= (_CharT __c); _Rope_char_ptr_proxy<_CharT,_Alloc> operator& () const; diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/tests/ChangeLog gcc-2.95.3/libstdc++/tests/ChangeLog *** gcc-2.95.2/libstdc++/tests/ChangeLog Mon Oct 25 07:59:16 1999 --- gcc-2.95.3/libstdc++/tests/ChangeLog Fri Mar 16 12:52:21 2001 *************** *** 1,3 **** --- 1,7 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released. diff -x de.gmo -x fr.gmo -Nrc3p gcc-2.95.2/libstdc++/testsuite/ChangeLog gcc-2.95.3/libstdc++/testsuite/ChangeLog *** gcc-2.95.2/libstdc++/testsuite/ChangeLog Mon Oct 25 07:59:16 1999 --- gcc-2.95.3/libstdc++/testsuite/ChangeLog Fri Mar 16 12:52:21 2001 *************** *** 1,3 **** --- 1,7 ---- + Fri Mar 16 12:46:19 GMT 2001 Bernd Schmidt (bernds@redhat.com) + + * gcc-2.95.3 Released. + Sun Oct 24 23:54:10 PDT 1999 Jeff Law (law@cygnus.com) * gcc-2.95.2 Released.