From 1eb27a8e4fa6e0e8068a2ebe1f746c3b13cc38ff Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Sun, 23 Sep 2007 16:25:06 +0000 Subject: * infcall.c (call_function_by_hand): Handle language-specific pass and return by reference. * cp-abi.c (cp_pass_by_reference): New. * cp-abi.h (cp_pass_by_reference): Declare. (struct cp_abi_ops): Add pass_by_reference. * gnu-v3-abi.c (gnuv3_pass_by_reference): New. (init_gnuv3_ops): Set pass_by_reference. * language.c (language_pass_by_reference): New. (default_pass_by_reference): New. (unknown_language_defn, auto_language_defn, local_language_defn): Add default_pass_by_reference. * langauge.h (struct language_defn): Add la_pass_by_reference. (language_pass_by_reference, default_pass_by_reference): Declare. * ada-lang.c (ada_language_defn): Add default_pass_by_reference. * c-lang.c (c_language_defn, asm_language_defn) (minimal_language_defn): Likewise. (cplus_language_defn): Add cp_pass_by_reference. * f-lang.c (f_language_defn): Add default_pass_by_reference. * jv-lang.c (java_language_defn): Likewise. * m2-lang.c (m2_language_defn): Likewise. * objc-lang.c (objc_language_defn): Likewise. * p-lang.c (pascal_language_defn): Likewise. * scm-lang.c (scm_language_defn): Likewise * gdb.cp/pass-by-ref.cc, gdb.cp/pass-by-ref.exp: New files. --- gdb/gnu-v3-abi.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'gdb/gnu-v3-abi.c') diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c index 469fc57598b..c3e07a10675 100644 --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -716,6 +716,87 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc) return real_stop_pc; } +/* Return nonzero if a type should be passed by reference. + + The rule in the v3 ABI document comes from section 3.1.1. If the + type has a non-trivial copy constructor or destructor, then the + caller must make a copy (by calling the copy constructor if there + is one or perform the copy itself otherwise), pass the address of + the copy, and then destroy the temporary (if necessary). + + For return values with non-trivial copy constructors or + destructors, space will be allocated in the caller, and a pointer + will be passed as the first argument (preceding "this"). + + We don't have a bulletproof mechanism for determining whether a + constructor or destructor is trivial. For GCC and DWARF2 debug + information, we can check the artificial flag. + + We don't do anything with the constructors or destructors, + but we have to get the argument passing right anyway. */ +static int +gnuv3_pass_by_reference (struct type *type) +{ + int fieldnum, fieldelem; + + CHECK_TYPEDEF (type); + + /* We're only interested in things that can have methods. */ + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_CLASS + && TYPE_CODE (type) != TYPE_CODE_UNION) + return 0; + + for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++) + for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum); + fieldelem++) + { + struct fn_field *fn = TYPE_FN_FIELDLIST1 (type, fieldnum); + char *name = TYPE_FN_FIELDLIST_NAME (type, fieldnum); + struct type *fieldtype = TYPE_FN_FIELD_TYPE (fn, fieldelem); + + /* If this function is marked as artificial, it is compiler-generated, + and we assume it is trivial. */ + if (TYPE_FN_FIELD_ARTIFICIAL (fn, fieldelem)) + continue; + + /* If we've found a destructor, we must pass this by reference. */ + if (name[0] == '~') + return 1; + + /* If the mangled name of this method doesn't indicate that it + is a constructor, we're not interested. + + FIXME drow/2007-09-23: We could do this using the name of + the method and the name of the class instead of dealing + with the mangled name. We don't have a convenient function + to strip off both leading scope qualifiers and trailing + template arguments yet. */ + if (!is_constructor_name (TYPE_FN_FIELD_PHYSNAME (fn, fieldelem))) + continue; + + /* If this method takes two arguments, and the second argument is + a reference to this class, then it is a copy constructor. */ + if (TYPE_NFIELDS (fieldtype) == 2 + && TYPE_CODE (TYPE_FIELD_TYPE (fieldtype, 1)) == TYPE_CODE_REF + && check_typedef (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (fieldtype, 1))) == type) + return 1; + } + + /* Even if all the constructors and destructors were artificial, one + of them may have invoked a non-artificial constructor or + destructor in a base class. If any base class needs to be passed + by reference, so does this class. Similarly for members, which + are constructed whenever this class is. We do not need to worry + about recursive loops here, since we are only looking at members + of complete class type. */ + for (fieldnum = 0; fieldnum < TYPE_NFIELDS (type); fieldnum++) + if (gnuv3_pass_by_reference (TYPE_FIELD_TYPE (type, fieldnum))) + return 1; + + return 0; +} + static void init_gnuv3_ops (void) { @@ -738,6 +819,7 @@ init_gnuv3_ops (void) gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr; gnu_v3_abi_ops.method_ptr_to_value = gnuv3_method_ptr_to_value; gnu_v3_abi_ops.skip_trampoline = gnuv3_skip_trampoline; + gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference; } extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */ -- cgit v1.2.1