diff options
author | Daniel Jacobowitz <drow@false.org> | 2007-09-23 16:25:06 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2007-09-23 16:25:06 +0000 |
commit | 41f1b6975dce5616800a8ff1acb544019c7bc132 (patch) | |
tree | f3e49925507634d70cb6d6e1fbd9ce7c6b8ec313 /gdb/gnu-v3-abi.c | |
parent | 3f213f78ed9182dbdeb3500dab729a6aad17dfd9 (diff) | |
download | gdb-41f1b6975dce5616800a8ff1acb544019c7bc132.zip gdb-41f1b6975dce5616800a8ff1acb544019c7bc132.tar.gz gdb-41f1b6975dce5616800a8ff1acb544019c7bc132.tar.bz2 |
* 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.
Diffstat (limited to 'gdb/gnu-v3-abi.c')
-rw-r--r-- | gdb/gnu-v3-abi.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c index 469fc57..c3e07a1 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 */ |