mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			465 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			465 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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;
 | |
| +}
 |