* symtab.c (find_pc_sect_line): Use SYMBOL_VALUE_ADDRESS instead
[deliverable/binutils-gdb.git] / gdb / gnu-v3-abi.c
index 4914b4692cbb35c8d245544fb42924b5a610bd42..fa251267ecc2b308754f6a407a14874d8996cb29 100644 (file)
@@ -1,15 +1,15 @@
 /* Abstraction of GNU v3 abi.
    Contributed by Jim Blandy <jimb@redhat.com>
 
-   Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007
+   Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 
-   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 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
@@ -17,9 +17,7 @@
    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., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "value.h"
@@ -100,9 +98,7 @@ enum {
    described above, laid out appropriately for ARCH.
 
    We use this function as the gdbarch per-architecture data
-   initialization function.  We assume that the gdbarch framework
-   calls the per-architecture data initialization functions after it
-   sets current_gdbarch to the new architecture.  */
+   initialization function.  */
 static void *
 build_gdb_vtable_type (struct gdbarch *arch)
 {
@@ -118,7 +114,7 @@ build_gdb_vtable_type (struct gdbarch *arch)
   /* ARCH can't give us the true ptrdiff_t type, so we guess.  */
   struct type *ptrdiff_type
     = init_type (TYPE_CODE_INT,
-                gdbarch_ptr_bit (current_gdbarch) / TARGET_CHAR_BIT, 0,
+                gdbarch_ptr_bit (arch) / TARGET_CHAR_BIT, 0,
                  "ptrdiff_t", 0);
 
   /* We assume no padding is necessary, since GDB doesn't know
@@ -682,12 +678,12 @@ static CORE_ADDR
 gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
 {
   CORE_ADDR real_stop_pc, method_stop_pc;
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   struct minimal_symbol *thunk_sym, *fn_sym;
   struct obj_section *section;
   char *thunk_name, *fn_name;
   
-  real_stop_pc = gdbarch_skip_trampoline_code
-                  (current_gdbarch, frame, stop_pc);
+  real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
   if (real_stop_pc == 0)
     real_stop_pc = stop_pc;
 
@@ -711,13 +707,94 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
 
   method_stop_pc = SYMBOL_VALUE_ADDRESS (fn_sym);
   real_stop_pc = gdbarch_skip_trampoline_code
-                  (current_gdbarch, frame, method_stop_pc);
+                  (gdbarch, frame, method_stop_pc);
   if (real_stop_pc == 0)
     real_stop_pc = method_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)
 {
@@ -740,6 +817,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 */
This page took 0.026118 seconds and 4 git commands to generate.