diff options
Diffstat (limited to 'gnu/egcs/gcc/cp/method.c')
-rw-r--r-- | gnu/egcs/gcc/cp/method.c | 221 |
1 files changed, 216 insertions, 5 deletions
diff --git a/gnu/egcs/gcc/cp/method.c b/gnu/egcs/gcc/cp/method.c index d4a667bdf82..d60bfda5242 100644 --- a/gnu/egcs/gcc/cp/method.c +++ b/gnu/egcs/gcc/cp/method.c @@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */ #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. */ @@ -88,6 +89,8 @@ static int is_back_referenceable_type PROTO((tree)); 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))) @@ -1349,6 +1352,15 @@ process_overload_item (parmtype, extra_Gcode) #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)); @@ -1809,14 +1821,64 @@ get_id_2 (name, name2) return get_identifier (obstack_base (&scratch_obstack)); } -/* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */ +/* 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) +build_destructor_name (type, has_vlist) tree type; + int has_vlist; { - return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX), - type); + 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), @@ -2178,6 +2240,136 @@ emit_thunk (thunk_fndecl) TREE_SET_CODE (thunk_fndecl, THUNK_DECL); } +void +make_vlist_ctor_wrapper (fn) + tree fn; +{ + tree fntype, decl; + tree arg_types, parms, parm, basetype, pbasetype; + tree t, ctors; + + 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; + + /* When fn is declared, DECL_INITIAL is null. When it is defined, + DECL_INITIAL will be error_mark_node. */ + if (DECL_INITIAL (fn) == error_mark_node) + { + /* Record that the ctor is being defined, so we also emit the + wrapper later. */ + TREE_USED (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 1; + DECL_INITIAL (decl) = NULL_TREE; + 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 @@ -2212,6 +2404,8 @@ do_build_copy_constructor (fndecl) 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) @@ -2408,6 +2602,16 @@ synthesize_method (fndecl) 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); @@ -2429,7 +2633,11 @@ synthesize_method (fndecl) 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) + 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 (); @@ -2443,3 +2651,6 @@ synthesize_method (fndecl) else if (nested) pop_cp_function_context (context); } + + + |