summaryrefslogtreecommitdiff
path: root/toolchain/gdb/patches/700-debian_cp-pass-by-reference.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain/gdb/patches/700-debian_cp-pass-by-reference.patch')
-rw-r--r--toolchain/gdb/patches/700-debian_cp-pass-by-reference.patch464
1 files changed, 464 insertions, 0 deletions
diff --git a/toolchain/gdb/patches/700-debian_cp-pass-by-reference.patch b/toolchain/gdb/patches/700-debian_cp-pass-by-reference.patch
new file mode 100644
index 0000000..666d343
--- /dev/null
+++ b/toolchain/gdb/patches/700-debian_cp-pass-by-reference.patch
@@ -0,0 +1,464 @@
+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;
++}