123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- This patch needs to be submitted for the FSF. Also, there may be testcases
- already in the GDB testsuite (currently disabled) that it would probably fix.
- Index: gdb-6.3/gdb/infcall.c
- ===================================================================
- --- gdb-6.3.orig/gdb/infcall.c 2004-10-08 04:15:56.000000000 -0400
- +++ gdb-6.3/gdb/infcall.c 2004-11-10 12:30:07.000000000 -0500
- @@ -36,6 +36,7 @@
- #include "gdb_string.h"
- #include "infcall.h"
- #include "dummy-frame.h"
- +#include "cp-abi.h"
-
- /* NOTE: cagney/2003-04-16: What's the future of this code?
-
- @@ -297,8 +298,8 @@ call_function_by_hand (struct value *fun
- {
- CORE_ADDR sp;
- CORE_ADDR dummy_addr;
- - struct type *value_type;
- - unsigned char struct_return;
- + struct type *value_type, *target_value_type;
- + unsigned char struct_return = 0, cp_struct_return = 0;
- CORE_ADDR struct_addr = 0;
- struct regcache *retbuf;
- struct cleanup *retbuf_cleanup;
- @@ -312,6 +313,7 @@ call_function_by_hand (struct value *fun
- struct regcache *caller_regcache;
- struct cleanup *caller_regcache_cleanup;
- struct frame_id dummy_id;
- + struct cleanup *args_cleanup;
-
- if (!target_has_execution)
- noprocess ();
- @@ -410,10 +412,31 @@ call_function_by_hand (struct value *fun
- using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
- }
-
- - /* Are we returning a value using a structure return or a normal
- - value return? */
- + /* Are we returning a value using a structure return (passing a
- + hidden argument pointing to storage) or a normal value return?
- + There are two cases: C++ ABI mandated structure return and
- + target ABI structure return. The variable STRUCT_RETURN only
- + describes the latter. The C++ version is handled by passing
- + the return location as the first parameter to the function,
- + even preceding "this". This is different from the target
- + ABI version, which is target-specific; for instance, on ia64
- + the first argument is passed in out0 but the hidden structure
- + return pointer would normally be passed in r8. */
-
- - struct_return = using_struct_return (value_type, using_gcc);
- + if (current_language->la_language == language_cplus
- + && cp_pass_by_reference (value_type))
- + {
- + cp_struct_return = 1;
- +
- + /* Tell the target specific argument pushing routine not to
- + expect a value. */
- + target_value_type = builtin_type_void;
- + }
- + else
- + {
- + struct_return = using_struct_return (value_type, using_gcc);
- + target_value_type = value_type;
- + }
-
- /* Determine the location of the breakpoint (and possibly other
- stuff) that the called function will return to. The SPARC, for a
- @@ -432,7 +455,7 @@ call_function_by_hand (struct value *fun
- if (INNER_THAN (1, 2))
- {
- sp = push_dummy_code (current_gdbarch, sp, funaddr,
- - using_gcc, args, nargs, value_type,
- + using_gcc, args, nargs, target_value_type,
- &real_pc, &bp_addr);
- dummy_addr = sp;
- }
- @@ -440,7 +463,7 @@ call_function_by_hand (struct value *fun
- {
- dummy_addr = sp;
- sp = push_dummy_code (current_gdbarch, sp, funaddr,
- - using_gcc, args, nargs, value_type,
- + using_gcc, args, nargs, target_value_type,
- &real_pc, &bp_addr);
- }
- break;
- @@ -507,9 +530,15 @@ call_function_by_hand (struct value *fun
- param_type = TYPE_FIELD_TYPE (ftype, i);
- else
- param_type = NULL;
- -
- +
- args[i] = value_arg_coerce (args[i], param_type, prototyped);
-
- + /* FIXME: Is current_language the right language? */
- + if (current_language->la_language == language_cplus
- + && param_type != NULL
- + && cp_pass_by_reference (param_type))
- + args[i] = value_addr (args[i]);
- +
- /* elz: this code is to handle the case in which the function
- to be called has a pointer to function as parameter and the
- corresponding actual argument is the address of a function
- @@ -607,7 +636,7 @@ You must use a pointer to function type
- stack, if necessary. Make certain that the value is correctly
- aligned. */
-
- - if (struct_return)
- + if (struct_return || cp_struct_return)
- {
- int len = TYPE_LENGTH (value_type);
- if (INNER_THAN (1, 2))
- @@ -632,6 +661,22 @@ You must use a pointer to function type
- }
- }
-
- + if (cp_struct_return)
- + {
- + struct value **new_args;
- +
- + /* Add the new argument to the front of the argument list. */
- + new_args = xmalloc (sizeof (struct value *) * (nargs + 1));
- + new_args[0] = value_from_pointer (lookup_pointer_type (value_type),
- + struct_addr);
- + memcpy (&new_args[1], &args[0], sizeof (struct value *) * nargs);
- + args = new_args;
- + nargs++;
- + args_cleanup = make_cleanup (xfree, args);
- + }
- + else
- + args_cleanup = make_cleanup (null_cleanup, NULL);
- +
- /* Create the dummy stack frame. Pass in the call dummy address as,
- presumably, the ABI code knows where, in the call dummy, the
- return address should be pointed. */
- @@ -649,6 +694,8 @@ You must use a pointer to function type
- else
- error ("This target does not support function calls");
-
- + do_cleanups (args_cleanup);
- +
- /* Set up a frame ID for the dummy frame so we can pass it to
- set_momentary_breakpoint. We need to give the breakpoint a frame
- ID so that the breakpoint code can correctly re-identify the
- @@ -839,11 +886,7 @@ the function call).", name);
- /* Figure out the value returned by the function, return that. */
- {
- struct value *retval;
- - if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
- - /* If the function returns void, don't bother fetching the
- - return value. */
- - retval = allocate_value (value_type);
- - else if (struct_return)
- + if (struct_return || cp_struct_return)
- /* NOTE: cagney/2003-09-27: This assumes that PUSH_DUMMY_CALL
- has correctly stored STRUCT_ADDR in the target. In the past
- that hasn't been the case, the old MIPS PUSH_ARGUMENTS
- @@ -853,6 +896,10 @@ the function call).", name);
- "struct return convention", check that PUSH_DUMMY_CALL isn't
- playing tricks. */
- retval = value_at (value_type, struct_addr, NULL);
- + else if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
- + /* If the function returns void, don't bother fetching the
- + return value. */
- + retval = allocate_value (value_type);
- else
- {
- /* This code only handles "register convention". */
- Index: gdb-6.3/gdb/cp-abi.h
- ===================================================================
- --- gdb-6.3.orig/gdb/cp-abi.h 2003-04-12 13:41:25.000000000 -0400
- +++ gdb-6.3/gdb/cp-abi.h 2004-11-10 12:30:07.000000000 -0500
- @@ -1,7 +1,7 @@
- /* Abstraction of various C++ ABI's we support, and the info we need
- to get from them.
- Contributed by Daniel Berlin <dberlin@redhat.com>
- - Copyright 2001 Free Software Foundation, Inc.
- + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- @@ -145,6 +145,10 @@ extern struct type *value_rtti_type (str
- extern int baseclass_offset (struct type *type, int index, char *valaddr,
- CORE_ADDR address);
-
- +/* Return non-zero if an argument of type TYPE should be passed by reference
- + instead of value. */
- +extern int cp_pass_by_reference (struct type *type);
- +
- struct cp_abi_ops
- {
- const char *shortname;
- @@ -162,6 +166,7 @@ struct cp_abi_ops
- int *using_enc);
- int (*baseclass_offset) (struct type *type, int index, char *valaddr,
- CORE_ADDR address);
- + int (*pass_by_reference) (struct type *type);
- };
-
-
- Index: gdb-6.3/gdb/cp-abi.c
- ===================================================================
- --- gdb-6.3.orig/gdb/cp-abi.c 2003-11-26 17:04:00.000000000 -0500
- +++ gdb-6.3/gdb/cp-abi.c 2004-11-10 12:30:07.000000000 -0500
- @@ -1,5 +1,5 @@
- /* Generic code for supporting multiple C++ ABI's
- - Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
- + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- @@ -94,6 +94,14 @@ value_rtti_type (struct value *v, int *f
- return (*current_cp_abi.rtti_type) (v, full, top, using_enc);
- }
-
- +int
- +cp_pass_by_reference (struct type *type)
- +{
- + if ((current_cp_abi.pass_by_reference) == NULL)
- + return 0;
- + return (*current_cp_abi.pass_by_reference) (type);
- +}
- +
- /* Set the current C++ ABI to SHORT_NAME. */
-
- static int
- Index: gdb-6.3/gdb/gnu-v3-abi.c
- ===================================================================
- --- gdb-6.3.orig/gdb/gnu-v3-abi.c 2004-03-15 15:38:08.000000000 -0500
- +++ gdb-6.3/gdb/gnu-v3-abi.c 2004-11-10 12:30:07.000000000 -0500
- @@ -1,7 +1,7 @@
- /* Abstraction of GNU v3 abi.
- Contributed by Jim Blandy <jimb@redhat.com>
-
- - Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
- + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- @@ -419,6 +419,84 @@ gnuv3_baseclass_offset (struct type *typ
- return base_offset;
- }
-
- +/* 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 yet,
- + but we have to get the argument passing right anyway. */
- +static int
- +gnuv3_pass_by_reference (struct type *type)
- +{
- + int fieldnum, fieldelem, basenum;
- +
- + 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/2004-05-27: 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. */
- + for (basenum = 0; basenum < TYPE_N_BASECLASSES (type); basenum++)
- + if (gnuv3_pass_by_reference (TYPE_BASECLASS (type, basenum)))
- + return 1;
- +
- + return 0;
- +}
- +
- static void
- init_gnuv3_ops (void)
- {
- @@ -434,6 +512,7 @@ init_gnuv3_ops (void)
- gnu_v3_abi_ops.rtti_type = gnuv3_rtti_type;
- gnu_v3_abi_ops.virtual_fn_field = gnuv3_virtual_fn_field;
- gnu_v3_abi_ops.baseclass_offset = gnuv3_baseclass_offset;
- + gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
- }
-
- extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */
- Index: gdb-6.3/gdb/hpacc-abi.c
- ===================================================================
- --- gdb-6.3.orig/gdb/hpacc-abi.c 2003-06-08 14:27:13.000000000 -0400
- +++ gdb-6.3/gdb/hpacc-abi.c 2004-11-10 12:30:07.000000000 -0500
- @@ -3,7 +3,7 @@
- Most of the real code is from HP, i've just fiddled it to fit in
- the C++ ABI abstraction framework.
-
- - Copyright 2001 Free Software Foundation, Inc.
- + Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- Index: gdb-6.3/gdb/Makefile.in
- ===================================================================
- --- gdb-6.3.orig/gdb/Makefile.in 2004-11-10 12:30:06.000000000 -0500
- +++ gdb-6.3/gdb/Makefile.in 2004-11-10 12:30:07.000000000 -0500
- @@ -2073,7 +2073,7 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inf
- infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
- $(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
- $(objfiles_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h) \
- - $(dummy_frame_h)
- + $(dummy_frame_h) $(cp_abi_h)
- inf-child.o: inf-child.c $(defs_h) $(regcache_h) $(memattr_h) $(symtab_h) \
- $(target_h) $(inferior_h) $(gdb_string_h)
- infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
- Index: gdb-6.3/gdb/testsuite/gdb.cp/pass-by-ref.exp
- ===================================================================
- --- /dev/null 1970-01-01 00:00:00.000000000 +0000
- +++ gdb-6.3/gdb/testsuite/gdb.cp/pass-by-ref.exp 2004-11-11 09:48:00.498518899 -0500
- @@ -0,0 +1,38 @@
- +# This testcase is part of GDB, the GNU debugger.
- +
- +# Copyright 2004 Free Software Foundation, Inc.
- +
- +# This program 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 of the License, or
- +# (at your option) any later version.
- +#
- +# This program 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 program; if not, write to the Free Software
- +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- +
- +# Check that GDB can call C++ functions whose parameters have
- +# object type, but are passed by reference.
- +
- +set testfile "pass-by-ref"
- +set srcfile ${testfile}.cc
- +set binfile ${objdir}/${subdir}/${testfile}
- +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
- + return -1
- +}
- +
- +gdb_exit
- +gdb_start
- +gdb_reinitialize_dir $srcdir/$subdir
- +gdb_load ${binfile}
- +
- +if ![runto_main] then {
- + return -1
- +}
- +
- +gdb_test "print foo (global_obj)" " = 3" "call function"
- Index: gdb-6.3/gdb/testsuite/gdb.cp/pass-by-ref.cc
- ===================================================================
- --- /dev/null 1970-01-01 00:00:00.000000000 +0000
- +++ gdb-6.3/gdb/testsuite/gdb.cp/pass-by-ref.cc 2004-11-11 09:44:17.815014667 -0500
- @@ -0,0 +1,57 @@
- +/* This testcase is part of GDB, the GNU debugger.
- +
- + Copyright 2004 Free Software Foundation, Inc.
- +
- + This program 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 of the License, or
- + (at your option) any later version.
- +
- + This program 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 program; if not, write to the Free Software
- + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- + USA. */
- +
- +class Obj {
- +public:
- + Obj ();
- + Obj (const Obj &);
- + ~Obj ();
- + int var[2];
- +};
- +
- +int foo (Obj arg)
- +{
- + return arg.var[0] + arg.var[1];
- +}
- +
- +Obj::Obj ()
- +{
- + var[0] = 1;
- + var[1] = 2;
- +}
- +
- +Obj::Obj (const Obj &obj)
- +{
- + var[0] = obj.var[0];
- + var[1] = obj.var[1];
- +}
- +
- +Obj::~Obj ()
- +{
- +
- +}
- +
- +Obj global_obj;
- +
- +int
- +main ()
- +{
- + int bar = foo (global_obj);
- + return bar;
- +}
|