This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] Improve C++ pass and return by reference


A Debian bug report long ago (2004, I believe) prompted me to write
this patch; later comments from Nathan Sidwell improved it.  There
are some types in C++ which must be passed and returned by reference,
even if the platform-specific ABI would allow them to be passed and
returned in registers.

As an additional wrinkle, this is separate from the equivalent
platform-specific passing by reference in some cases.  On IA-64
when a function's return value must go through memory, the address
is passed in a special register, not the first parameter register.
But if the transformation is done by C++ rather than by the
IA-64 tdep code, we must use the first parameter register.  So
we pretend such functions return void and have an extra argument,
which is what the C++ ABI specifies.

On some platforms (those where std::string would fit in a register?),
this fixes a failure in bs15503.exp.  On all platforms it fixes the
new pass-by-ref.exp test case.  Tested on x86_64-pc-linux-gnu and
checked in.

-- 
Daniel Jacobowitz
CodeSourcery

2007-09-23  Daniel Jacobowitz  <dan@codesourcery.com>

	* 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

2007-09-23  Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.cp/pass-by-ref.cc, gdb.cp/pass-by-ref.exp: New files.

Index: ada-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/ada-lang.c,v
retrieving revision 1.105
diff -u -p -r1.105 ada-lang.c
--- ada-lang.c	23 Aug 2007 18:08:25 -0000	1.105
+++ ada-lang.c	23 Sep 2007 15:19:42 -0000
@@ -10441,6 +10441,7 @@ const struct language_defn ada_language_
   ada_get_gdb_completer_word_break_characters,
   ada_language_arch_info,
   ada_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.45
diff -u -p -r1.45 c-lang.c
--- c-lang.c	23 Aug 2007 18:08:26 -0000	1.45
+++ c-lang.c	23 Sep 2007 15:19:42 -0000
@@ -606,6 +606,7 @@ const struct language_defn c_language_de
   default_word_break_characters,
   c_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
@@ -711,6 +712,7 @@ const struct language_defn cplus_languag
   default_word_break_characters,
   cplus_language_arch_info,
   default_print_array_index,
+  cp_pass_by_reference,
   LANG_MAGIC
 };
 
@@ -747,6 +749,7 @@ const struct language_defn asm_language_
   default_word_break_characters,
   c_language_arch_info, /* FIXME: la_language_arch_info.  */
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
@@ -788,6 +791,7 @@ const struct language_defn minimal_langu
   default_word_break_characters,
   c_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: cp-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-abi.c,v
retrieving revision 1.18
diff -u -p -r1.18 cp-abi.c
--- cp-abi.c	23 Aug 2007 18:08:27 -0000	1.18
+++ cp-abi.c	23 Sep 2007 15:19:42 -0000
@@ -135,6 +135,14 @@ cplus_method_ptr_to_value (struct value 
   return (*current_cp_abi.method_ptr_to_value) (this_p, method_ptr);
 }
 
+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: cp-abi.h
===================================================================
RCS file: /cvs/src/src/gdb/cp-abi.h,v
retrieving revision 1.14
diff -u -p -r1.14 cp-abi.h
--- cp-abi.h	23 Aug 2007 18:08:27 -0000	1.14
+++ cp-abi.h	23 Sep 2007 15:19:42 -0000
@@ -172,6 +172,10 @@ void cplus_make_method_ptr (gdb_byte *CO
 
 CORE_ADDR cplus_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc);
 
+/* 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;
@@ -195,6 +199,7 @@ struct cp_abi_ops
   void (*make_method_ptr) (gdb_byte *, CORE_ADDR, int);
   struct value * (*method_ptr_to_value) (struct value **, struct value *);
   CORE_ADDR (*skip_trampoline) (struct frame_info *, CORE_ADDR);
+  int (*pass_by_reference) (struct type *type);
 };
 
 
Index: f-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/f-lang.c,v
retrieving revision 1.40
diff -u -p -r1.40 f-lang.c
--- f-lang.c	23 Aug 2007 18:08:30 -0000	1.40
+++ f-lang.c	23 Sep 2007 15:19:42 -0000
@@ -503,6 +503,7 @@ const struct language_defn f_language_de
   default_word_break_characters,
   f_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: gnu-v3-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v
retrieving revision 1.36
diff -u -p -r1.36 gnu-v3-abi.c
--- gnu-v3-abi.c	23 Aug 2007 18:08:33 -0000	1.36
+++ gnu-v3-abi.c	23 Sep 2007 15:19:42 -0000
@@ -716,6 +716,87 @@ gnuv3_skip_trampoline (struct frame_info
   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 */
Index: infcall.c
===================================================================
RCS file: /cvs/src/src/gdb/infcall.c,v
retrieving revision 1.87
diff -u -p -r1.87 infcall.c
--- infcall.c	23 Aug 2007 18:08:35 -0000	1.87
+++ infcall.c	23 Sep 2007 15:19:43 -0000
@@ -339,8 +339,8 @@ call_function_by_hand (struct value *fun
 {
   CORE_ADDR sp;
   CORE_ADDR dummy_addr;
-  struct type *values_type;
-  unsigned char struct_return;
+  struct type *values_type, *target_values_type;
+  unsigned char struct_return = 0, lang_struct_return = 0;
   CORE_ADDR struct_addr = 0;
   struct regcache *retbuf;
   struct cleanup *retbuf_cleanup;
@@ -354,6 +354,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 (TYPE_CODE (ftype) == TYPE_CODE_PTR)
     ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
@@ -460,10 +461,30 @@ 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: language-mandated structure return and
+     target ABI structure return.  The variable STRUCT_RETURN only
+     describes the latter.  The language 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 (values_type, using_gcc);
+  if (language_pass_by_reference (values_type))
+    {
+      lang_struct_return = 1;
+
+      /* Tell the target specific argument pushing routine not to
+	 expect a value.  */
+      target_values_type = builtin_type_void;
+    }
+  else
+    {
+      struct_return = using_struct_return (values_type, using_gcc);
+      target_values_type = values_type;
+    }
 
   /* Determine the location of the breakpoint (and possibly other
      stuff) that the called function will return to.  The SPARC, for a
@@ -482,7 +503,7 @@ call_function_by_hand (struct value *fun
       if (gdbarch_inner_than (current_gdbarch, 1, 2))
 	{
 	  sp = push_dummy_code (current_gdbarch, sp, funaddr,
-				using_gcc, args, nargs, values_type,
+				using_gcc, args, nargs, target_values_type,
 				&real_pc, &bp_addr, get_current_regcache ());
 	  dummy_addr = sp;
 	}
@@ -490,7 +511,7 @@ call_function_by_hand (struct value *fun
 	{
 	  dummy_addr = sp;
 	  sp = push_dummy_code (current_gdbarch, sp, funaddr,
-				using_gcc, args, nargs, values_type,
+				using_gcc, args, nargs, target_values_type,
 				&real_pc, &bp_addr, get_current_regcache ());
 	}
       break;
@@ -557,9 +578,12 @@ 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);
 
+	if (param_type != NULL && language_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
@@ -659,7 +683,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 || lang_struct_return)
     {
       int len = TYPE_LENGTH (values_type);
       if (gdbarch_inner_than (current_gdbarch, 1, 2))
@@ -684,6 +708,22 @@ You must use a pointer to function type 
 	}
     }
 
+  if (lang_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 (values_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.  */
@@ -691,6 +731,8 @@ You must use a pointer to function type 
 				get_current_regcache (), bp_addr, nargs, args,
 				sp, struct_return, struct_addr);
 
+  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
@@ -882,7 +924,9 @@ the function call)."), name);
   {
     struct value *retval = NULL;
 
-    if (TYPE_CODE (values_type) == TYPE_CODE_VOID)
+    if (lang_struct_return)
+      retval = value_at (values_type, struct_addr);
+    else if (TYPE_CODE (target_values_type) == TYPE_CODE_VOID)
       {
 	/* If the function returns void, don't bother fetching the
 	   return value.  */
@@ -892,7 +936,7 @@ the function call)."), name);
       {
 	struct gdbarch *arch = current_gdbarch;
 
-	switch (gdbarch_return_value (arch, values_type, NULL, NULL, NULL))
+	switch (gdbarch_return_value (arch, target_values_type, NULL, NULL, NULL))
 	  {
 	  case RETURN_VALUE_REGISTER_CONVENTION:
 	  case RETURN_VALUE_ABI_RETURNS_ADDRESS:
Index: jv-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/jv-lang.c,v
retrieving revision 1.49
diff -u -p -r1.49 jv-lang.c
--- jv-lang.c	23 Aug 2007 18:08:35 -0000	1.49
+++ jv-lang.c	23 Sep 2007 15:19:43 -0000
@@ -1115,6 +1115,7 @@ const struct language_defn java_language
   default_word_break_characters,
   c_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: language.c
===================================================================
RCS file: /cvs/src/src/gdb/language.c,v
retrieving revision 1.67
diff -u -p -r1.67 language.c
--- language.c	23 Aug 2007 18:08:35 -0000	1.67
+++ language.c	23 Sep 2007 15:19:43 -0000
@@ -1045,6 +1045,23 @@ language_class_name_from_physname (const
   return NULL;
 }
 
+/* Return non-zero if TYPE should be passed (and returned) by
+   reference at the language level.  */
+int
+language_pass_by_reference (struct type *type)
+{
+  return current_language->la_pass_by_reference (type);
+}
+
+/* Return zero; by default, types are passed by value at the language
+   level.  The target ABI may pass or return some structs by reference
+   independent of this.  */
+int
+default_pass_by_reference (struct type *type)
+{
+  return 0;
+}
+
 /* Return the default string containing the list of characters
    delimiting words.  This is a reasonable default value that
    most languages should be able to use.  */
@@ -1191,6 +1208,7 @@ const struct language_defn unknown_langu
   default_word_break_characters,
   unknown_language_arch_info,	/* la_language_arch_info.  */
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
@@ -1228,6 +1246,7 @@ const struct language_defn auto_language
   default_word_break_characters,
   unknown_language_arch_info,	/* la_language_arch_info.  */
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
@@ -1264,6 +1283,7 @@ const struct language_defn local_languag
   default_word_break_characters,
   unknown_language_arch_info,	/* la_language_arch_info.  */
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: language.h
===================================================================
RCS file: /cvs/src/src/gdb/language.h,v
retrieving revision 1.40
diff -u -p -r1.40 language.h
--- language.h	23 Aug 2007 18:08:35 -0000	1.40
+++ language.h	23 Sep 2007 15:19:43 -0000
@@ -280,6 +280,10 @@ struct language_defn
                                   int format,
                                   enum val_prettyprint pretty);
 
+    /* Return non-zero if TYPE should be passed (and returned) by
+       reference at the language level.  */
+    int (*la_pass_by_reference) (struct type *type);
+
     /* Add fields above this point, so the magic number is always last. */
     /* Magic number for compat checking */
 
@@ -471,4 +475,13 @@ extern void default_print_array_index (s
                                        int format,
                                        enum val_prettyprint pretty);
 
+/* Return non-zero if TYPE should be passed (and returned) by
+   reference at the language level.  */
+int language_pass_by_reference (struct type *type);
+
+/* Return zero; by default, types are passed by value at the language
+   level.  The target ABI may pass or return some structs by reference
+   independent of this.  */
+int default_pass_by_reference (struct type *type);
+
 #endif /* defined (LANGUAGE_H) */
Index: m2-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/m2-lang.c,v
retrieving revision 1.31
diff -u -p -r1.31 m2-lang.c
--- m2-lang.c	23 Aug 2007 18:08:35 -0000	1.31
+++ m2-lang.c	23 Sep 2007 15:19:43 -0000
@@ -459,6 +459,7 @@ const struct language_defn m2_language_d
   default_word_break_characters,
   m2_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: objc-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/objc-lang.c,v
retrieving revision 1.59
diff -u -p -r1.59 objc-lang.c
--- objc-lang.c	23 Aug 2007 18:08:36 -0000	1.59
+++ objc-lang.c	23 Sep 2007 15:19:43 -0000
@@ -668,6 +668,7 @@ const struct language_defn objc_language
   default_word_break_characters,
   c_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: p-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/p-lang.c,v
retrieving revision 1.32
diff -u -p -r1.32 p-lang.c
--- p-lang.c	23 Aug 2007 18:08:36 -0000	1.32
+++ p-lang.c	23 Sep 2007 15:19:43 -0000
@@ -525,6 +525,7 @@ const struct language_defn pascal_langua
   default_word_break_characters,
   pascal_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: scm-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/scm-lang.c,v
retrieving revision 1.38
diff -u -p -r1.38 scm-lang.c
--- scm-lang.c	23 Aug 2007 18:08:37 -0000	1.38
+++ scm-lang.c	23 Sep 2007 15:19:43 -0000
@@ -267,6 +267,7 @@ const struct language_defn scm_language_
   default_word_break_characters,
   c_language_arch_info,
   default_print_array_index,
+  default_pass_by_reference,
   LANG_MAGIC
 };
 
Index: testsuite/gdb.cp/pass-by-ref.cc
===================================================================
RCS file: testsuite/gdb.cp/pass-by-ref.cc
diff -N testsuite/gdb.cp/pass-by-ref.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.cp/pass-by-ref.cc	23 Sep 2007 15:33:32 -0000
@@ -0,0 +1,79 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2007 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+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 ()
+{
+
+}
+
+struct Derived : public Obj
+{
+  int other;
+};
+
+int blap (Derived arg)
+{
+  return foo (arg);
+}
+
+struct Container
+{
+  Obj obj;
+};
+
+int blip (Container arg)
+{
+  return foo (arg.obj);
+}
+
+Obj global_obj;
+Derived global_derived;
+Container global_container;
+
+int
+main ()
+{
+  int bar = foo (global_obj);
+  blap (global_derived);
+  blip (global_container);
+  return bar;
+}
Index: testsuite/gdb.cp/pass-by-ref.exp
===================================================================
RCS file: testsuite/gdb.cp/pass-by-ref.exp
diff -N testsuite/gdb.cp/pass-by-ref.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.cp/pass-by-ref.exp	23 Sep 2007 15:33:32 -0000
@@ -0,0 +1,41 @@
+# Copyright 2007 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 3 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, see <http://www.gnu.org/licenses/>.
+
+# Check that GDB can call C++ functions whose parameters have
+# object type, but are passed by reference.
+
+if { [skip_cplus_tests] } { continue }
+
+set testfile "pass-by-ref"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+	  executable {debug c++}] != "" } {
+    untested pass-by-ref.exp
+    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 in obj"
+gdb_test "print blap (global_derived)" " = 3" "call function in derived"
+gdb_test "print blip (global_container)" " = 3" "call function in container"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]