* NEWS: Mention pointer to member improvements.
authorDaniel Jacobowitz <drow@false.org>
Wed, 3 Jan 2007 18:05:45 +0000 (18:05 +0000)
committerDaniel Jacobowitz <drow@false.org>
Wed, 3 Jan 2007 18:05:45 +0000 (18:05 +0000)
* Makefile.in (gnu-v3-abi.o): Delete special rule.
(eval.o, gnu-v3-abi.o, ia64-tdep.o): Update.
* ada-valprint.c (ada_print_scalar): Update for new type codes.
* c-typeprint.c (c_print_type): Update for new type codes.
(c_type_print_varspec_prefix, c_type_print_varspec_suffix)
(c_type_print_base): Likewise.
(c_type_print_args): Rewrite.
* c-valprint.c (c_val_print): Update for new type codes.  Remove
support for references to members.  Treat methods like functions.
* cp-abi.c (cplus_print_method_ptr, cplus_method_ptr_size)
(cplus_make_method_ptr, cplus_method_ptr_to_value): New.
* cp-abi.h (cplus_print_method_ptr, cplus_method_ptr_size)
(cplus_make_method_ptr, cplus_method_ptr_to_value): New prototypes.
(struct cp_abi_ops): Add corresponding members.
* cp-valprint.c (cp_print_class_method): Delete.
(cp_find_class_member): New function.
(cp_print_class_member): Use it.  Simplify support for bogus
member pointers.
* dwarf2read.c (quirk_gcc_member_function_pointer): Use
lookup_methodptr_type.
(read_tag_ptr_to_member_type): Likewise, and lookup_memberptr_type.
* eval.c (evaluate_subexp_standard): Implement EVAL_SKIP for
OP_SCOPE.  Update call to value_aggregate_elt.  Rewrite member
pointer support.
(evaluate_subexp_for_address): Handle OP_SCOPE explicitly.  Handle
references returned by user defined operators.
* f-typeprint.c (f_print_type, f_type_print_varspec_prefix)
(f_type_print_varspec_suffix): Remove support for member pointers.
* gdbtypes.c (lookup_memberptr_type): Renamed from lookup_member_type
and adjusted.
(smash_to_memberptr_type): Likewise, from smash_to_member_type.
(lookup_methodptr_type): New.
(rank_one_type): Adjust for TYPE_CODE_MEMBERPTR.
(recursive_dump_type): Update for new types.
* gdbtypes.h (enum type_code): Replace TYPE_CODE_MEMBER with
TYPE_CODE_MEMBERPTR and TYPE_CODE_METHODPTR.
(lookup_memberptr_type, lookup_methodptr_type)
(smash_to_memberptr_type): New prototypes.
(smash_to_method_type): Formatting fix.
(lookup_member_type, smash_to_member_type): Delete prototypes.
* gnu-v3-abi.c (gnuv3_get_vtable, gnuv3_get_virtual_fn): New.
Do not rely on debug information for the vptr or the method's
enclosing type.  Handle function descriptors for IA64.
(gnuv3_virtual_fn_field): Rewrite using the new functions.
(gnuv3_find_method_in, gnuv3_print_method_ptr)
(gnuv3_method_ptr_size, gnuv3_make_method_ptr)
(gnuv3_method_ptr_to_value): New.
(init_gnuv3_ops): Set new members of gnu_v3_abi_ops.
* hpread.c (hpread_type_lookup): Update for new types.
* infcall.c (value_arg_coerce): Likewise.
* m2-typeprint.c (m2_print_type): Remove explicit support
for member pointers.
* m2-valprint.c (m2_val_print): Likewise.
* p-typeprint.c (pascal_type_print_varspec_prefix)
(pascal_type_print_varspec_suffix, pascal_type_print_base): Likewise.
* p-valprint.c (pascal_val_print): Likewise.
(pascal_object_print_class_method, pascal_object_print_class_member):
Delete.
* p-lang.h (pascal_object_print_class_method)
(pascal_object_print_class_member): Delete prototypes.
* stabsread.c (read_type): Update for new types.
* typeprint.c (print_type_scalar): Likewise.
* valops.c (value_struct_elt_for_reference, value_namespace_elt)
(value_maybe_namespace_elt, value_aggregate_elt): Add want_address
argument.  Construct a pointer to member if the address of a
function or data member is requested.
(value_cast_pointers): Don't modify the input value.
(value_cast): Adjust pointer to member handling for new types.
Allow null pointer to member constants.  Don't modify the input
value.
(value_ind): Remove pointer to member check.  Handle function
descriptors for function pointers.
(value_struct_elt, value_find_oload_method_list, check_field):
Remove pointer to member checks.
* value.c (unpack_long): Allow pointers to data members.
(value_from_longest): Allow member pointers.
* value.h (value_aggregate_elt): Add want_address.
* varobj.c (c_variable_editable): Remove check for members.
* gdbarch.sh: Add vtable_function_descriptors and vbit_in_delta.
* ia64-tdep.c (ia64_convert_from_func_ptr_addr): Handle descriptors
in virtual tables.
(ia64_gdbarch_init): Call set_gdbarch_vtable_function_descriptors.
* c-lang.h (cp_print_class_method): Delete prototype.
* arm-tdep.c (arm_gdbarch_init): Call set_gdbarch_vbit_in_delta.
* mips-tdep.c (mips_gdbarch_init): Likewise.
* gdbarch.c, gdbarch.h: Regenerated.

* gdb.cp/classes.exp (test_pointers_to_class_members): Update expected
output.  Test the types of members and member pointers.
* gdb.cp/inherit.exp (test_print_mi_member_types): Remove KFAILs for
gdb/2092.
* gdb.cp/member-ptr.exp: Search for a comment instead of a
statement.  Enable for GCC.  Update expected output for some tests
and add new tests.  Remove obsolete GCC KFAILs.  Allow GCC's class
layout.
* gdb.cp/member-ptr.cc (Padding, Padding::vspacer, Base, Base::get_x)
(Base::vget_base, Left, Left::vget, Right, Right::vget, Diamond)
(Diamond::vget_base): New.
(main): Add new tests.
* gdb.cp/printmethod.exp: Update expected output for member functions.
* gdb.cp/virtfunc.exp (test_virtual_calls): Add a KFAIL for
print pEe->D::vg().

42 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/ada-valprint.c
gdb/arm-tdep.c
gdb/c-lang.h
gdb/c-typeprint.c
gdb/c-valprint.c
gdb/cp-abi.c
gdb/cp-abi.h
gdb/cp-valprint.c
gdb/dwarf2read.c
gdb/eval.c
gdb/f-typeprint.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/gnu-v3-abi.c
gdb/hpread.c
gdb/ia64-tdep.c
gdb/infcall.c
gdb/m2-typeprint.c
gdb/m2-valprint.c
gdb/mips-tdep.c
gdb/p-lang.h
gdb/p-typeprint.c
gdb/p-valprint.c
gdb/stabsread.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/classes.exp
gdb/testsuite/gdb.cp/inherit.exp
gdb/testsuite/gdb.cp/member-ptr.cc
gdb/testsuite/gdb.cp/member-ptr.exp
gdb/testsuite/gdb.cp/printmethod.exp
gdb/testsuite/gdb.cp/virtfunc.exp
gdb/typeprint.c
gdb/valops.c
gdb/value.c
gdb/value.h
gdb/varobj.c

index 4c35ceb0e54dcd08929896ec0a25f3b20e9a23ab..cd956b62d0506e7a2b92ba8289b06a3fd9300b31 100644 (file)
@@ -1,3 +1,93 @@
+2007-01-03  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * NEWS: Mention pointer to member improvements.
+       * Makefile.in (gnu-v3-abi.o): Delete special rule.
+       (eval.o, gnu-v3-abi.o, ia64-tdep.o): Update.
+       * ada-valprint.c (ada_print_scalar): Update for new type codes.
+       * c-typeprint.c (c_print_type): Update for new type codes.
+       (c_type_print_varspec_prefix, c_type_print_varspec_suffix)
+       (c_type_print_base): Likewise.
+       (c_type_print_args): Rewrite.
+       * c-valprint.c (c_val_print): Update for new type codes.  Remove
+       support for references to members.  Treat methods like functions.
+       * cp-abi.c (cplus_print_method_ptr, cplus_method_ptr_size)
+       (cplus_make_method_ptr, cplus_method_ptr_to_value): New.
+       * cp-abi.h (cplus_print_method_ptr, cplus_method_ptr_size)
+       (cplus_make_method_ptr, cplus_method_ptr_to_value): New prototypes.
+       (struct cp_abi_ops): Add corresponding members.
+       * cp-valprint.c (cp_print_class_method): Delete.
+       (cp_find_class_member): New function.
+       (cp_print_class_member): Use it.  Simplify support for bogus
+       member pointers.
+       * dwarf2read.c (quirk_gcc_member_function_pointer): Use
+       lookup_methodptr_type.
+       (read_tag_ptr_to_member_type): Likewise, and lookup_memberptr_type.
+       * eval.c (evaluate_subexp_standard): Implement EVAL_SKIP for
+       OP_SCOPE.  Update call to value_aggregate_elt.  Rewrite member
+       pointer support.
+       (evaluate_subexp_for_address): Handle OP_SCOPE explicitly.  Handle
+       references returned by user defined operators.
+       * f-typeprint.c (f_print_type, f_type_print_varspec_prefix)
+       (f_type_print_varspec_suffix): Remove support for member pointers.
+       * gdbtypes.c (lookup_memberptr_type): Renamed from lookup_member_type
+       and adjusted.
+       (smash_to_memberptr_type): Likewise, from smash_to_member_type.
+       (lookup_methodptr_type): New.
+       (rank_one_type): Adjust for TYPE_CODE_MEMBERPTR.
+       (recursive_dump_type): Update for new types.
+       * gdbtypes.h (enum type_code): Replace TYPE_CODE_MEMBER with
+       TYPE_CODE_MEMBERPTR and TYPE_CODE_METHODPTR.
+       (lookup_memberptr_type, lookup_methodptr_type)
+       (smash_to_memberptr_type): New prototypes.
+       (smash_to_method_type): Formatting fix.
+       (lookup_member_type, smash_to_member_type): Delete prototypes.
+       * gnu-v3-abi.c (gnuv3_get_vtable, gnuv3_get_virtual_fn): New.
+       Do not rely on debug information for the vptr or the method's
+       enclosing type.  Handle function descriptors for IA64.
+       (gnuv3_virtual_fn_field): Rewrite using the new functions.
+       (gnuv3_find_method_in, gnuv3_print_method_ptr)
+       (gnuv3_method_ptr_size, gnuv3_make_method_ptr)
+       (gnuv3_method_ptr_to_value): New.
+       (init_gnuv3_ops): Set new members of gnu_v3_abi_ops.
+       * hpread.c (hpread_type_lookup): Update for new types.
+       * infcall.c (value_arg_coerce): Likewise.
+       * m2-typeprint.c (m2_print_type): Remove explicit support
+       for member pointers.
+       * m2-valprint.c (m2_val_print): Likewise.
+       * p-typeprint.c (pascal_type_print_varspec_prefix)
+       (pascal_type_print_varspec_suffix, pascal_type_print_base): Likewise.
+       * p-valprint.c (pascal_val_print): Likewise.
+       (pascal_object_print_class_method, pascal_object_print_class_member):
+       Delete.
+       * p-lang.h (pascal_object_print_class_method)
+       (pascal_object_print_class_member): Delete prototypes.
+       * stabsread.c (read_type): Update for new types.
+       * typeprint.c (print_type_scalar): Likewise.
+       * valops.c (value_struct_elt_for_reference, value_namespace_elt)
+       (value_maybe_namespace_elt, value_aggregate_elt): Add want_address
+       argument.  Construct a pointer to member if the address of a
+       function or data member is requested.
+       (value_cast_pointers): Don't modify the input value.
+       (value_cast): Adjust pointer to member handling for new types.
+       Allow null pointer to member constants.  Don't modify the input
+       value.
+       (value_ind): Remove pointer to member check.  Handle function
+       descriptors for function pointers.
+       (value_struct_elt, value_find_oload_method_list, check_field):
+       Remove pointer to member checks.
+       * value.c (unpack_long): Allow pointers to data members.
+       (value_from_longest): Allow member pointers.
+       * value.h (value_aggregate_elt): Add want_address.
+       * varobj.c (c_variable_editable): Remove check for members.
+       * gdbarch.sh: Add vtable_function_descriptors and vbit_in_delta.
+       * ia64-tdep.c (ia64_convert_from_func_ptr_addr): Handle descriptors
+       in virtual tables.
+       (ia64_gdbarch_init): Call set_gdbarch_vtable_function_descriptors.
+       * c-lang.h (cp_print_class_method): Delete prototype.
+       * arm-tdep.c (arm_gdbarch_init): Call set_gdbarch_vbit_in_delta.
+       * mips-tdep.c (mips_gdbarch_init): Likewise.
+       * gdbarch.c, gdbarch.h: Regenerated.
+
 2007-01-01  Mark Kettenis  <kettenis@gnu.org>
 
        * rs6000-tdep.c (rs6000_use_struct_convention)
index ead6f31092bede230ee35a2b3cf99e61b07d438c..1b3e4730d5819ec9fd24a1ace4eb54309031ad3b 100644 (file)
@@ -1527,13 +1527,6 @@ main.o: main.c
        $(CC) -c $(INTERNAL_CFLAGS) $(TARGET_SYSTEM_ROOT_DEFINE) \
                -DBINDIR=\"$(bindir)\" $(srcdir)/main.c
 
-# FIXME: cagney/2004-09-16: "gnu-v3-abi.c", with a GCC 3.4 compiler,
-# gets a "assignment from incompatible pointer type" warning.  The
-# return types - "enum gnu_v3_dtor_kinds" vs "enum ctor_kinds" -
-# conflict.
-gnu-v3-abi.o: $(srcdir)/gnu-v3-abi.c
-       $(CC) -c $(INTERNAL_WARN_CFLAGS) $(srcdir)/gnu-v3-abi.c
-
 # FIXME: cagney/2003-08-10: "monitor.c" gets -Wformat-nonliteral
 # errors.  It turns out that that is the least of monitor.c's
 # problems.  The function print_vsprintf appears to be using
@@ -1973,7 +1966,7 @@ environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
 eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
        $(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
        $(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
-       $(parser_defs_h) $(cp_support_h)
+       $(parser_defs_h) $(cp_support_h) $(gdb_assert_h)
 event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
        $(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
 event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
@@ -2052,7 +2045,7 @@ gnu-v2-abi.o: gnu-v2-abi.c $(defs_h) $(gdb_string_h) $(symtab_h) \
        $(gdbtypes_h) $(value_h) $(demangle_h) $(cp_abi_h) $(cp_support_h) \
        $(gnu_v2_abi_h)
 gnu-v3-abi.o: gnu-v3-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(cp_support_h) \
-       $(demangle_h) $(gdb_assert_h) $(gdb_string_h)
+       $(demangle_h) $(valprint_h) $(gdb_assert_h) $(gdb_string_h)
 go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) $(gdb_wait_h) $(gdbcore_h) \
        $(command_h) $(gdbcmd_h) $(floatformat_h) $(buildsym_h) \
        $(i387_tdep_h) $(i386_tdep_h) $(value_h) $(regcache_h) \
@@ -2168,7 +2161,8 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
        $(frame_h) $(frame_base_h) $(frame_unwind_h) $(doublest_h) \
        $(value_h) $(gdb_assert_h) $(objfiles_h) $(elf_common_h) \
        $(elf_bfd_h) $(dis_asm_h) $(infcall_h) $(osabi_h) $(ia64_tdep_h) \
-       $(elf_ia64_h) $(libunwind_frame_h) $(libunwind_ia64_h)
+       $(elf_ia64_h) $(libunwind_frame_h) $(libunwind_ia64_h) \
+       $(cp_abi_h)
 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) \
index 22b75188ef40a651058f35b1c1bf2128a5ff3daa..3a9f330bb3cabd87f4a7564a0c36512ce50a139d 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -9,6 +9,8 @@ frequency signals (e.g. SIGALRM) via the QPassSignals packet.
 * GDB for MIPS targets now autodetects whether a remote target provides
 32-bit or 64-bit register values.
 
+* Support for C++ member pointers has been improved.
+
 * New commands
 
 set mem inaccessible-by-default
index 7781fada9a257e950e3cc454a3effd4ec97809a5..fd7bceff39e54a797767ad6622b015ac4c1f829c 100644 (file)
@@ -420,7 +420,8 @@ ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream)
     case TYPE_CODE_SET:
     case TYPE_CODE_STRING:
     case TYPE_CODE_ERROR:
-    case TYPE_CODE_MEMBER:
+    case TYPE_CODE_MEMBERPTR:
+    case TYPE_CODE_METHODPTR:
     case TYPE_CODE_METHOD:
     case TYPE_CODE_REF:
       warning (_("internal error: unhandled type in ada_print_scalar"));
index f4a6a37f2ddf24594a42b2ea1e3242b774a9a4f4..a1c90533866b85818612394ac0e45debf6dfb15b 100644 (file)
@@ -2816,6 +2816,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_coff_make_msymbol_special (gdbarch,
                                         arm_coff_make_msymbol_special);
 
+  /* Virtual tables.  */
+  set_gdbarch_vbit_in_delta (gdbarch, 1);
+
   /* Hook in the ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
index 63a92ec2ab361defc6856de752d54cda329b89c3..74d9fe6a326fa8069e17cabf03e76fa0b712e7e0 100644 (file)
@@ -1,7 +1,7 @@
 /* C language support definitions for GDB, the GNU debugger.
 
-   Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2005 Free
-   Software Foundation, Inc.
+   Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2005, 2006
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -79,9 +79,6 @@ extern int static_field_print;
 extern void cp_print_class_member (const gdb_byte *, struct type *,
                                   struct ui_file *, char *);
 
-extern void cp_print_class_method (const gdb_byte *, struct type *,
-                                  struct ui_file *);
-
 extern void cp_print_value_fields (struct type *, struct type *,
                                   const gdb_byte *, int, CORE_ADDR,
                                   struct ui_file *, int,
index 8ac2c037cb6bd315302749fbbc7acb3bc4f2031b..518af681efb34a1309b3b909e3753bc39ccac3f7 100644 (file)
@@ -1,6 +1,6 @@
 /* Support for printing C and C++ types for GDB, the GNU debugger.
    Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
-   1999, 2000, 2001, 2002, 2003
+   1999, 2000, 2001, 2002, 2003, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -80,7 +80,8 @@ c_print_type (struct type *type, char *varstring, struct ui_file *stream,
        (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
        || code == TYPE_CODE_METHOD
        || code == TYPE_CODE_ARRAY
-       || code == TYPE_CODE_MEMBER
+       || code == TYPE_CODE_MEMBERPTR
+       || code == TYPE_CODE_METHODPTR
        || code == TYPE_CODE_REF)))
     fputs_filtered (" ", stream);
   need_post_space = (varstring != NULL && strcmp (varstring, "") != 0);
@@ -218,29 +219,25 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
       c_type_print_modifier (type, stream, 1, need_post_space);
       break;
 
-    case TYPE_CODE_MEMBER:
-      if (passed_a_ptr)
-       fprintf_filtered (stream, "(");
+    case TYPE_CODE_MEMBERPTR:
       c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
-      fprintf_filtered (stream, " ");
       name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
       if (name)
        fputs_filtered (name, stream);
       else
        c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
-      fprintf_filtered (stream, "::");
+      fprintf_filtered (stream, "::*");
       break;
 
-    case TYPE_CODE_METHOD:
-      if (passed_a_ptr)
-       fprintf_filtered (stream, "(");
+    case TYPE_CODE_METHODPTR:
       c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
-      if (passed_a_ptr)
-       {
-         fprintf_filtered (stream, " ");
-         c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
-         fprintf_filtered (stream, "::");
-       }
+      fprintf_filtered (stream, "(");
+      name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
+      if (name)
+       fputs_filtered (name, stream);
+      else
+       c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
+      fprintf_filtered (stream, "::*");
       break;
 
     case TYPE_CODE_REF:
@@ -249,6 +246,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
       c_type_print_modifier (type, stream, 1, need_post_space);
       break;
 
+    case TYPE_CODE_METHOD:
     case TYPE_CODE_FUNC:
       c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
       if (passed_a_ptr)
@@ -337,42 +335,49 @@ c_type_print_modifier (struct type *type, struct ui_file *stream,
 }
 
 
-
+/* Print out the arguments of TYPE, which should have TYPE_CODE_METHOD
+   or TYPE_CODE_FUNC, to STREAM.  Artificial arguments, such as "this"
+   in non-static methods, are displayed.  */
 
 static void
 c_type_print_args (struct type *type, struct ui_file *stream)
 {
-  int i;
+  int i, len;
   struct field *args;
+  int printed_any = 0;
 
   fprintf_filtered (stream, "(");
   args = TYPE_FIELDS (type);
-  if (args != NULL)
-    {
-      int i;
-
-      /* FIXME drow/2002-05-31: Always skips the first argument,
-        should we be checking for static members?  */
+  len = TYPE_NFIELDS (type);
 
-      for (i = 1; i < TYPE_NFIELDS (type); i++)
+  for (i = 0; i < TYPE_NFIELDS (type); i++)
+    {
+      if (printed_any)
        {
-         c_print_type (args[i].type, "", stream, -1, 0);
-         if (i != TYPE_NFIELDS (type))
-           {
-             fprintf_filtered (stream, ",");
-             wrap_here ("    ");
-           }
+         fprintf_filtered (stream, ", ");
+         wrap_here ("    ");
        }
-      if (TYPE_VARARGS (type))
-       fprintf_filtered (stream, "...");
-      else if (i == 1
-              && (current_language->la_language == language_cplus))
-       fprintf_filtered (stream, "void");
+
+      c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
+      printed_any = 1;
     }
-  else if (current_language->la_language == language_cplus)
+
+  if (printed_any && TYPE_VARARGS (type))
     {
-      fprintf_filtered (stream, "void");
+      /* Print out a trailing ellipsis for varargs functions.  Ignore
+        TYPE_VARARGS if the function has no named arguments; that
+        represents unprototyped (K&R style) C functions.  */
+      if (printed_any && TYPE_VARARGS (type))
+       {
+         fprintf_filtered (stream, ", ");
+         wrap_here ("    ");
+         fprintf_filtered (stream, "...");
+       }
     }
+  else if (!printed_any
+      && (TYPE_PROTOTYPED (type)
+         || current_language->la_language == language_cplus))
+    fprintf_filtered (stream, "void");
 
   fprintf_filtered (stream, ")");
 }
@@ -548,22 +553,15 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
                                   0, 0);
       break;
 
-    case TYPE_CODE_MEMBER:
-      if (passed_a_ptr)
-       fprintf_filtered (stream, ")");
+    case TYPE_CODE_MEMBERPTR:
       c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
                                   0, 0);
       break;
 
-    case TYPE_CODE_METHOD:
-      if (passed_a_ptr)
-       fprintf_filtered (stream, ")");
+    case TYPE_CODE_METHODPTR:
+      fprintf_filtered (stream, ")");
       c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
                                   0, 0);
-      if (passed_a_ptr)
-       {
-         c_type_print_args (type, stream);
-       }
       break;
 
     case TYPE_CODE_PTR:
@@ -572,31 +570,12 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
                                   1, 0);
       break;
 
+    case TYPE_CODE_METHOD:
     case TYPE_CODE_FUNC:
       if (passed_a_ptr)
        fprintf_filtered (stream, ")");
       if (!demangled_args)
-       {
-         int i, len = TYPE_NFIELDS (type);
-         fprintf_filtered (stream, "(");
-         if (len == 0
-              && (TYPE_PROTOTYPED (type)
-                  || current_language->la_language == language_cplus))
-           {
-             fprintf_filtered (stream, "void");
-           }
-         else
-           for (i = 0; i < len; i++)
-             {
-               if (i > 0)
-                 {
-                   fputs_filtered (", ", stream);
-                   wrap_here ("    ");
-                 }
-               c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
-             }
-         fprintf_filtered (stream, ")");
-       }
+       c_type_print_args (type, stream);
       c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
                                   passed_a_ptr, 0);
       break;
@@ -696,10 +675,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
     case TYPE_CODE_TYPEDEF:
     case TYPE_CODE_ARRAY:
     case TYPE_CODE_PTR:
-    case TYPE_CODE_MEMBER:
+    case TYPE_CODE_MEMBERPTR:
     case TYPE_CODE_REF:
     case TYPE_CODE_FUNC:
     case TYPE_CODE_METHOD:
+    case TYPE_CODE_METHODPTR:
       c_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
       break;
 
index 861e3bfe2e180a0c72d5ad1ac9c123a43ef0511d..655786f81bcc8f63028832158a5d11eee799f60e 100644 (file)
@@ -142,6 +142,21 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
       addr = address;
       goto print_unpacked_pointer;
 
+    case TYPE_CODE_MEMBERPTR:
+      if (format)
+       {
+         print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+         break;
+       }
+      cp_print_class_member (valaddr + embedded_offset,
+                            TYPE_DOMAIN_TYPE (type),
+                            stream, "&");
+      break;
+
+    case TYPE_CODE_METHODPTR:
+      cplus_print_method_ptr (valaddr + embedded_offset, type, stream);
+      break;
+
     case TYPE_CODE_PTR:
       if (format && format != 's')
        {
@@ -159,17 +174,6 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
          break;
        }
       elttype = check_typedef (TYPE_TARGET_TYPE (type));
-      if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
-       {
-         cp_print_class_method (valaddr + embedded_offset, type, stream);
-       }
-      else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
-       {
-         cp_print_class_member (valaddr + embedded_offset,
-                                TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
-                                stream, "&");
-       }
-      else
        {
          addr = unpack_pointer (type, valaddr + embedded_offset);
        print_unpacked_pointer:
@@ -250,19 +254,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
        }
       break;
 
-    case TYPE_CODE_MEMBER:
-      error (_("not implemented: member type in c_val_print"));
-      break;
-
     case TYPE_CODE_REF:
       elttype = check_typedef (TYPE_TARGET_TYPE (type));
-      if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
-       {
-         cp_print_class_member (valaddr + embedded_offset,
-                                TYPE_DOMAIN_TYPE (elttype),
-                                stream, "");
-         break;
-       }
       if (addressprint)
        {
          CORE_ADDR addr
@@ -351,6 +344,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
       break;
 
     case TYPE_CODE_FUNC:
+    case TYPE_CODE_METHOD:
       if (format)
        {
          print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
@@ -442,14 +436,6 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
        }
       break;
 
-    case TYPE_CODE_METHOD:
-      {
-       struct value *v = value_at (type, address);
-       cp_print_class_method (value_contents (value_addr (v)),
-                              lookup_pointer_type (type), stream);
-       break;
-      }
-
     case TYPE_CODE_VOID:
       fprintf_filtered (stream, "void");
       break;
index af35dd8896a6794480a4ff566dadc00813c92a8f..7dad2b7cc4c35ea8810a5087ab010ef40824c31d 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic code for supporting multiple C++ ABI's
 
-   Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -95,6 +95,39 @@ value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
   return (*current_cp_abi.rtti_type) (v, full, top, using_enc);
 }
 
+void
+cplus_print_method_ptr (const gdb_byte *contents, struct type *type,
+                       struct ui_file *stream)
+{
+  if (current_cp_abi.print_method_ptr == NULL)
+    error (_("GDB does not support pointers to methods on this target"));
+  (*current_cp_abi.print_method_ptr) (contents, type, stream);
+}
+
+int
+cplus_method_ptr_size (void)
+{
+  if (current_cp_abi.method_ptr_size == NULL)
+    error (_("GDB does not support pointers to methods on this target"));
+  return (*current_cp_abi.method_ptr_size) ();
+}
+
+void
+cplus_make_method_ptr (gdb_byte *contents, CORE_ADDR value, int is_virtual)
+{
+  if (current_cp_abi.make_method_ptr == NULL)
+    error (_("GDB does not support pointers to methods on this target"));
+  (*current_cp_abi.make_method_ptr) (contents, value, is_virtual);
+}
+
+struct value *
+cplus_method_ptr_to_value (struct value **this_p, struct value *method_ptr)
+{
+  if (current_cp_abi.method_ptr_to_value == NULL)
+    error (_("GDB does not support pointers to methods on this target"));
+  return (*current_cp_abi.method_ptr_to_value) (this_p, method_ptr);
+}
+
 /* Set the current C++ ABI to SHORT_NAME.  */
 
 static int
index 6c77824d15f8dbbc7e6c3329ea41defbacb49cc2..1e22dbbfc14766e1f7e377b727015ed3b7729cb7 100644 (file)
@@ -3,7 +3,7 @@
 
    Contributed by Daniel Berlin <dberlin@redhat.com>
 
-   Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -30,6 +30,7 @@
 struct fn_field;
 struct type;
 struct value;
+struct ui_file;
 
 /* The functions here that attempt to determine what sort of thing a
    mangled name refers to may well be revised in the future.  It would
@@ -147,6 +148,28 @@ extern struct type *value_rtti_type (struct value *value,
 extern int baseclass_offset (struct type *type, int index,
                             const bfd_byte *valaddr, CORE_ADDR address);
                   
+/* Describe the target of a pointer to method.  CONTENTS is the byte
+   pattern representing the pointer to method.  TYPE is the pointer to
+   method type.  STREAM is the stream to print it to.  */
+void cplus_print_method_ptr (const gdb_byte *contents, struct type *type,
+                            struct ui_file *stream);
+
+/* Return the size of a pointer to member function for the current
+   architecture.  */
+int cplus_method_ptr_size (void);
+
+/* Return the method which should be called by applying METHOD_PTR
+   to *THIS_P, and adjust *THIS_P if necessary.  */
+struct value *cplus_method_ptr_to_value (struct value **this_p,
+                                        struct value *method_ptr);
+
+/* Create the byte pattern in CONTENTS representing a pointer to
+   member function at ADDRESS (if IS_VIRTUAL is 0) or with virtual
+   table offset ADDRESS (if IS_VIRTUAL is 1).  This is the opposite
+   of cplus_method_ptr_to_value.  */
+void cplus_make_method_ptr (gdb_byte *CONTENTS, CORE_ADDR address,
+                           int is_virtual);
+
 struct cp_abi_ops
 {
   const char *shortname;
@@ -164,6 +187,11 @@ struct cp_abi_ops
                             int *using_enc);
   int (*baseclass_offset) (struct type *type, int index,
                           const bfd_byte *valaddr, CORE_ADDR address);
+  void (*print_method_ptr) (const gdb_byte *contents, struct type *type,
+                           struct ui_file *stream);
+  int (*method_ptr_size) (void);
+  void (*make_method_ptr) (gdb_byte *, CORE_ADDR, int);
+  struct value * (*method_ptr_to_value) (struct value **, struct value *);
 };
 
 
index 84b66fe7a81b7f4d9d6f53185b6cb33e84364fce..911c924f3155403a3a2d537df8bc439fef39d6d9 100644 (file)
@@ -1,7 +1,8 @@
 /* Support for printing C++ values for GDB, the GNU debugger.
 
    Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+   1997, 2000, 2001, 2002, 2003, 2005, 2006
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -92,104 +93,6 @@ static void cp_print_hpacc_virtual_table_entries (struct type *, int *,
                                                  enum val_prettyprint);
 
 
-void
-cp_print_class_method (const gdb_byte *valaddr,
-                      struct type *type,
-                      struct ui_file *stream)
-{
-  struct type *domain;
-  struct fn_field *f = NULL;
-  int j = 0;
-  int len2;
-  int offset;
-  char *kind = "";
-  CORE_ADDR addr;
-  struct symbol *sym;
-  unsigned len;
-  unsigned int i;
-  struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
-
-  domain = TYPE_DOMAIN_TYPE (target_type);
-  if (domain == (struct type *) NULL)
-    {
-      fprintf_filtered (stream, "<unknown>");
-      return;
-    }
-  addr = unpack_pointer (type, valaddr);
-  if (METHOD_PTR_IS_VIRTUAL (addr))
-    {
-      offset = METHOD_PTR_TO_VOFFSET (addr);
-      len = TYPE_NFN_FIELDS (domain);
-      for (i = 0; i < len; i++)
-       {
-         f = TYPE_FN_FIELDLIST1 (domain, i);
-         len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
-
-         check_stub_method_group (domain, i);
-         for (j = 0; j < len2; j++)
-           {
-             if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
-               {
-                 kind = "virtual ";
-                 goto common;
-               }
-           }
-       }
-    }
-  else
-    {
-      sym = find_pc_function (addr);
-      if (sym == 0)
-       {
-         /* 1997-08-01 Currently unsupported with HP aCC */
-         if (deprecated_hp_som_som_object_present)
-           {
-             fputs_filtered ("?? <not supported with HP aCC>", stream);
-             return;
-           }
-         error (_("invalid pointer to member function"));
-       }
-      len = TYPE_NFN_FIELDS (domain);
-      for (i = 0; i < len; i++)
-       {
-         f = TYPE_FN_FIELDLIST1 (domain, i);
-         len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
-
-         check_stub_method_group (domain, i);
-         for (j = 0; j < len2; j++)
-           {
-             if (strcmp (DEPRECATED_SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))
-                 == 0)
-               goto common;
-           }
-       }
-    }
- common:
-  if (i < len)
-    {
-      char *demangled_name;
-
-      fprintf_filtered (stream, "&");
-      fputs_filtered (kind, stream);
-      demangled_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (f, j),
-                                      DMGL_ANSI | DMGL_PARAMS);
-      if (demangled_name == NULL)
-       fprintf_filtered (stream, "<badly mangled name %s>",
-                         TYPE_FN_FIELD_PHYSNAME (f, j));
-      else
-       {
-         fputs_filtered (demangled_name, stream);
-         xfree (demangled_name);
-       }
-    }
-  else
-    {
-      fprintf_filtered (stream, "(");
-      type_print (type, "", stream, -1);
-      fprintf_filtered (stream, ") %d", (int) addr >> 3);
-    }
-}
-
 /* GCC versions after 2.4.5 use this.  */
 const char vtbl_ptr_name[] = "__vtbl_ptr_type";
 
@@ -703,48 +606,82 @@ cp_print_static_field (struct type *type,
             stream, format, 0, recurse, pretty);
 }
 
+
+/* Find the field in *DOMAIN, or its non-virtual base classes, with bit offset
+   OFFSET.  Set *DOMAIN to the containing type and *FIELDNO to the containing
+   field number.  If OFFSET is not exactly at the start of some field, set
+   *DOMAIN to NULL.  */
+
+void
+cp_find_class_member (struct type **domain_p, int *fieldno,
+                     LONGEST offset)
+{
+  struct type *domain;
+  unsigned int i;
+  unsigned len;
+
+  *domain_p = check_typedef (*domain_p);
+  domain = *domain_p;
+  len = TYPE_NFIELDS (domain);
+
+  for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
+    {
+      LONGEST bitpos = TYPE_FIELD_BITPOS (domain, i);
+
+      QUIT;
+      if (offset == bitpos)
+       {
+         *fieldno = i;
+         return;
+       }
+    }
+
+  for (i = 0; i < TYPE_N_BASECLASSES (domain); i++)
+    {
+      LONGEST bitpos = TYPE_FIELD_BITPOS (domain, i);
+      LONGEST bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (domain, i));
+
+      if (offset >= bitpos && offset < bitpos + bitsize)
+       {
+         *domain_p = TYPE_FIELD_TYPE (domain, i);
+         cp_find_class_member (domain_p, fieldno, offset - bitpos);
+         return;
+       }
+    }
+
+  *domain_p = NULL;
+}
+
 void
 cp_print_class_member (const gdb_byte *valaddr, struct type *domain,
                       struct ui_file *stream, char *prefix)
 {
-
   /* VAL is a byte offset into the structure type DOMAIN.
      Find the name of the field for that offset and
      print it.  */
-  int extra = 0;
-  int bits = 0;
-  unsigned int i;
-  unsigned len = TYPE_NFIELDS (domain);
+  unsigned int fieldno;
 
-  /* @@ Make VAL into bit offset */
+  LONGEST val = unpack_long (builtin_type_long, valaddr);
 
-  /* Note: HP aCC generates offsets that are the real byte offsets added
-     to a constant bias 0x20000000 (1 << 29).  This constant bias gets
-     shifted out in the code below -- joyous happenstance! */
+  /* Pointers to data members are usually byte offsets into an object.
+     Because a data member can have offset zero, and a NULL pointer to
+     member must be distinct from any valid non-NULL pointer to
+     member, either the value is biased or the NULL value has a
+     special representation; both are permitted by ISO C++.  HP aCC
+     used a bias of 0x20000000; HP cfront used a bias of 1; g++ 3.x
+     and other compilers which use the Itanium ABI use -1 as the NULL
+     value.  GDB only supports that last form; to add support for
+     another form, make this into a cp-abi hook.  */
 
-  /* Note: HP cfront uses a constant bias of 1; if we support this
-     compiler ever, we will have to adjust the computation below */
-
-  LONGEST val = unpack_long (builtin_type_int, valaddr) << 3;
-  for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
+  if (val == -1)
     {
-      int bitpos = TYPE_FIELD_BITPOS (domain, i);
-      QUIT;
-      if (val == bitpos)
-       break;
-      if (val < bitpos && i != 0)
-       {
-         /* Somehow pointing into a field.  */
-         i -= 1;
-         extra = (val - TYPE_FIELD_BITPOS (domain, i));
-         if (extra & 0x7)
-           bits = 1;
-         else
-           extra >>= 3;
-         break;
-       }
+      fprintf_filtered (stream, "NULL");
+      return;
     }
-  if (i < len)
+
+  cp_find_class_member (&domain, &fieldno, val << 3);
+
+  if (domain != NULL)
     {
       char *name;
       fputs_filtered (prefix, stream);
@@ -754,14 +691,10 @@ cp_print_class_member (const gdb_byte *valaddr, struct type *domain,
       else
        c_type_print_base (domain, stream, 0, 0);
       fprintf_filtered (stream, "::");
-      fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
-      if (extra)
-       fprintf_filtered (stream, " + %d bytes", extra);
-      if (bits)
-       fprintf_filtered (stream, " (offset in bits)");
+      fputs_filtered (TYPE_FIELD_NAME (domain, fieldno), stream);
     }
   else
-    fprintf_filtered (stream, "%ld", (long) (val >> 3));
+    fprintf_filtered (stream, "%ld", (long) val);
 }
 
 
index 19c51d6073541052f688dbf850811c72888fb2e7..3dcf436210d0f1a14bbcebee55804ba34bfbc7d3 100644 (file)
@@ -3699,7 +3699,6 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
   TYPE_NFN_FIELDS_TOTAL (type) = total_length;
 }
 
-
 /* Returns non-zero if NAME is the name of a vtable member in CU's
    language, zero otherwise.  */
 static int
@@ -3779,7 +3778,7 @@ quirk_gcc_member_function_pointer (struct die_info *die, struct dwarf2_cu *cu)
   smash_to_method_type (type, domain_type, TYPE_TARGET_TYPE (pfn_type),
                        TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type),
                        TYPE_VARARGS (pfn_type));
-  type = lookup_pointer_type (type);
+  type = lookup_methodptr_type (type);
   set_die_type (die, type, cu);
 
   return 1;
@@ -4561,10 +4560,13 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
       return;
     }
 
-  type = alloc_type (objfile);
   to_type = die_type (die, cu);
   domain = die_containing_type (die, cu);
-  smash_to_member_type (type, domain, to_type);
+
+  if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD)
+    type = lookup_methodptr_type (to_type);
+  else
+    type = lookup_memberptr_type (to_type, domain);
 
   set_die_type (die, type, cu);
 }
index e1076e1efd43f2e29a2276f785a274721d10f184..1a3d72a547834021172a9043a2e40990f3dd6515 100644 (file)
@@ -1,8 +1,8 @@
 /* Evaluate expressions for GDB.
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free
-   Software Foundation, Inc.
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -38,6 +38,8 @@
 #include "parser-defs.h"
 #include "cp-support.h"
 
+#include "gdb_assert.h"
+
 /* This is defined in valops.c */
 extern int overload_resolution;
 
@@ -434,9 +436,11 @@ evaluate_subexp_standard (struct type *expect_type,
     case OP_SCOPE:
       tem = longest_to_int (exp->elts[pc + 2].longconst);
       (*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
       arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
                                  &exp->elts[pc + 3].string,
-                                 noside);
+                                 0, noside);
       if (arg1 == NULL)
        error (_("There is no field named %s"), &exp->elts[pc + 3].string);
       return arg1;
@@ -993,8 +997,6 @@ evaluate_subexp_standard (struct type *expect_type,
       argvec = (struct value **) alloca (sizeof (struct value *) * (nargs + 3));
       if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
        {
-         LONGEST fnptr;
-
          /* 1997-08-01 Currently we do not support function invocation
             via pointers-to-methods with HP aCC. Pointer does not point
             to the function, but possibly to some thunk. */
@@ -1027,41 +1029,18 @@ evaluate_subexp_standard (struct type *expect_type,
 
          arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
 
-         fnptr = value_as_long (arg1);
+         if (TYPE_CODE (check_typedef (value_type (arg1)))
+             != TYPE_CODE_METHODPTR)
+           error (_("Non-pointer-to-member value used in pointer-to-member "
+                    "construct"));
 
-         if (METHOD_PTR_IS_VIRTUAL (fnptr))
+         if (noside == EVAL_AVOID_SIDE_EFFECTS)
            {
-             int fnoffset = METHOD_PTR_TO_VOFFSET (fnptr);
-             struct type *basetype;
-             struct type *domain_type =
-             TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (value_type (arg1)));
-             int i, j;
-             basetype = TYPE_TARGET_TYPE (value_type (arg2));
-             if (domain_type != basetype)
-               arg2 = value_cast (lookup_pointer_type (domain_type), arg2);
-             basetype = TYPE_VPTR_BASETYPE (domain_type);
-             for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
-               {
-                 struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
-                 /* If one is virtual, then all are virtual.  */
-                 if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
-                   for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
-                     if ((int) TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset)
-                       {
-                         struct value *temp = value_ind (arg2);
-                         arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0);
-                         arg2 = value_addr (temp);
-                         goto got_it;
-                       }
-               }
-             if (i < 0)
-               error (_("virtual function at index %d not found"), fnoffset);
+             struct type *method_type = check_typedef (value_type (arg1));
+             arg1 = value_zero (method_type, not_lval);
            }
          else
-           {
-             deprecated_set_value_type (arg1, lookup_pointer_type (TYPE_TARGET_TYPE (value_type (arg1))));
-           }
-       got_it:
+           arg1 = cplus_method_ptr_to_value (&arg2, arg1);
 
          /* Now, say which argument to start evaluating from */
          tem = 2;
@@ -1396,57 +1375,60 @@ evaluate_subexp_standard (struct type *expect_type,
        }
 
     case STRUCTOP_MEMBER:
-      arg1 = evaluate_subexp_for_address (exp, pos, noside);
+    case STRUCTOP_MPTR:
+      if (op == STRUCTOP_MEMBER)
+       arg1 = evaluate_subexp_for_address (exp, pos, noside);
+      else
+       arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
       arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
 
-      /* With HP aCC, pointers to methods do not point to the function code */
-      if (deprecated_hp_som_som_object_present &&
-         (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR) &&
-      (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg2))) == TYPE_CODE_METHOD))
-       error (_("Pointers to methods not supported with HP aCC"));     /* 1997-08-19 */
+      if (noside == EVAL_SKIP)
+       goto nosideret;
 
-      mem_offset = value_as_long (arg2);
-      goto handle_pointer_to_member;
+      type = check_typedef (value_type (arg2));
+      switch (TYPE_CODE (type))
+       {
+       case TYPE_CODE_METHODPTR:
+         if (deprecated_hp_som_som_object_present)
+           {
+             /* With HP aCC, pointers to methods do not point to the
+                function code.  */
+             /* 1997-08-19 */
+             error (_("Pointers to methods not supported with HP aCC"));
+           }
 
-    case STRUCTOP_MPTR:
-      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
-      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return value_zero (TYPE_TARGET_TYPE (type), not_lval);
+         else
+           {
+             arg2 = cplus_method_ptr_to_value (&arg1, arg2);
+             gdb_assert (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR);
+             return value_ind (arg2);
+           }
 
-      /* With HP aCC, pointers to methods do not point to the function code */
-      if (deprecated_hp_som_som_object_present &&
-         (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR) &&
-      (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg2))) == TYPE_CODE_METHOD))
-       error (_("Pointers to methods not supported with HP aCC"));     /* 1997-08-19 */
+       case TYPE_CODE_MEMBERPTR:
+         /* Now, convert these values to an address.  */
+         arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
+                            arg1);
 
-      mem_offset = value_as_long (arg2);
+         mem_offset = value_as_long (arg2);
+         if (deprecated_hp_som_som_object_present)
+           {
+             /* HP aCC generates offsets that have bit #29 set; turn it off to get
+                a real offset to the member. */
+             if (!mem_offset)  /* no bias -> really null */
+               error (_("Attempted dereference of null pointer-to-member"));
+             mem_offset &= ~0x20000000;
+           }
 
-    handle_pointer_to_member:
-      /* HP aCC generates offsets that have bit #29 set; turn it off to get
-         a real offset to the member. */
-      if (deprecated_hp_som_som_object_present)
-       {
-         if (!mem_offset)      /* no bias -> really null */
-           error (_("Attempted dereference of null pointer-to-member"));
-         mem_offset &= ~0x20000000;
+         arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+                                    value_as_long (arg1) + mem_offset);
+         return value_ind (arg3);
+
+       default:
+         error (_("non-pointer-to-member value used in pointer-to-member construct"));
        }
-      if (noside == EVAL_SKIP)
-       goto nosideret;
-      type = check_typedef (value_type (arg2));
-      if (TYPE_CODE (type) != TYPE_CODE_PTR)
-       goto bad_pointer_to_member;
-      type = check_typedef (TYPE_TARGET_TYPE (type));
-      if (TYPE_CODE (type) == TYPE_CODE_METHOD)
-       error (_("not implemented: pointer-to-method in pointer-to-member construct"));
-      if (TYPE_CODE (type) != TYPE_CODE_MEMBER)
-       goto bad_pointer_to_member;
-      /* Now, convert these values to an address.  */
-      arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
-                        arg1);
-      arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
-                                value_as_long (arg1) + mem_offset);
-      return value_ind (arg3);
-    bad_pointer_to_member:
-      error (_("non-pointer-to-member value used in pointer-to-member construct"));
 
     case BINOP_CONCAT:
       arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -1469,13 +1451,11 @@ evaluate_subexp_standard (struct type *expect_type,
             the implementation yet; but the pointer appears to point to a code
             sequence (thunk) in memory -- in any case it is *not* the address
             of the function as it would be in a naive implementation. */
-         if ((TYPE_CODE (value_type (arg1)) == TYPE_CODE_PTR) &&
-             (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_METHOD))
+         if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_METHODPTR)
            error (_("Assignment to pointers to methods not implemented with HP aCC"));
 
-         /* HP aCC pointers to data members require a constant bias */
-         if ((TYPE_CODE (value_type (arg1)) == TYPE_CODE_PTR) &&
-             (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_MEMBER))
+         /* HP aCC pointers to data members require a constant bias.  */
+         if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_MEMBERPTR)
            {
              unsigned int *ptr = (unsigned int *) value_contents (arg2);       /* forces evaluation */
              *ptr |= 0x20000000;       /* set 29th bit */
@@ -1934,9 +1914,9 @@ evaluate_subexp_standard (struct type *expect_type,
       if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
        expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
       arg1 = evaluate_subexp (expect_type, exp, pos, noside);
-      if ((TYPE_TARGET_TYPE (value_type (arg1))) &&
-         ((TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_METHOD) ||
-          (TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_MEMBER)))
+      type = check_typedef (value_type (arg1));
+      if (TYPE_CODE (type) == TYPE_CODE_METHODPTR
+         || TYPE_CODE (type) == TYPE_CODE_MEMBERPTR)
        error (_("Attempt to dereference pointer to member without an object"));
       if (noside == EVAL_SKIP)
        goto nosideret;
@@ -1967,22 +1947,15 @@ evaluate_subexp_standard (struct type *expect_type,
 
       if (noside == EVAL_SKIP)
        {
-         if (op == OP_SCOPE)
-           {
-             int temm = longest_to_int (exp->elts[pc + 3].longconst);
-             (*pos) += 3 + BYTES_TO_EXP_ELEM (temm + 1);
-           }
-         else
-           evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+         evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
          goto nosideret;
        }
       else
        {
          struct value *retvalp = evaluate_subexp_for_address (exp, pos, noside);
          /* If HP aCC object, use bias for pointers to members */
-         if (deprecated_hp_som_som_object_present &&
-             (TYPE_CODE (value_type (retvalp)) == TYPE_CODE_PTR) &&
-             (TYPE_CODE (TYPE_TARGET_TYPE (value_type (retvalp))) == TYPE_CODE_MEMBER))
+         if (deprecated_hp_som_som_object_present
+             && TYPE_CODE (value_type (retvalp)) == TYPE_CODE_MEMBERPTR)
            {
              unsigned int *ptr = (unsigned int *) value_contents (retvalp);    /* forces evaluation */
              *ptr |= 0x20000000;       /* set 29th bit */
@@ -2148,6 +2121,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
   int pc;
   struct symbol *var;
   struct value *x;
+  int tem;
 
   pc = (*pos);
   op = exp->elts[pc].opcode;
@@ -2162,15 +2136,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
       if (unop_user_defined_p (op, x))
        {
          x = value_x_unop (x, op, noside);
-         if (noside == EVAL_AVOID_SIDE_EFFECTS)
-           {
-             if (VALUE_LVAL (x) == lval_memory)
-               return value_zero (lookup_pointer_type (value_type (x)),
-                                  not_lval);
-             else
-               error (_("Attempt to take address of non-lval"));
-           }
-         return value_addr (x);
+         goto default_case_after_eval;
        }
 
       return x;
@@ -2210,14 +2176,30 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
          (var,
           block_innermost_frame (exp->elts[pc + 1].block));
 
+    case OP_SCOPE:
+      tem = longest_to_int (exp->elts[pc + 2].longconst);
+      (*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1);
+      x = value_aggregate_elt (exp->elts[pc + 1].type,
+                              &exp->elts[pc + 3].string,
+                              1, noside);
+      if (x == NULL)
+       error (_("There is no field named %s"), &exp->elts[pc + 3].string);
+      return x;
+
     default:
     default_case:
       x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+    default_case_after_eval:
       if (noside == EVAL_AVOID_SIDE_EFFECTS)
        {
+         struct type *type = check_typedef (value_type (x));
+
          if (VALUE_LVAL (x) == lval_memory)
            return value_zero (lookup_pointer_type (value_type (x)),
                               not_lval);
+         else if (TYPE_CODE (type) == TYPE_CODE_REF)
+           return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+                              not_lval);
          else
            error (_("Attempt to take address of non-lval"));
        }
index 31b96a371f1bf3648fab02aed1ea57d6245e637e..9c157dade76e08bba058a1f8134708b15f716eba 100644 (file)
@@ -73,7 +73,6 @@ f_print_type (struct type *type, char *varstring, struct ui_file *stream,
        (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
        || code == TYPE_CODE_METHOD
        || code == TYPE_CODE_ARRAY
-       || code == TYPE_CODE_MEMBER
        || code == TYPE_CODE_REF)))
     fputs_filtered (" ", stream);
   f_type_print_varspec_prefix (type, stream, show, 0);
@@ -138,7 +137,6 @@ f_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
     case TYPE_CODE_STRING:
     case TYPE_CODE_BITSTRING:
     case TYPE_CODE_METHOD:
-    case TYPE_CODE_MEMBER:
     case TYPE_CODE_REF:
     case TYPE_CODE_COMPLEX:
     case TYPE_CODE_TYPEDEF:
@@ -250,7 +248,6 @@ f_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
     case TYPE_CODE_STRING:
     case TYPE_CODE_BITSTRING:
     case TYPE_CODE_METHOD:
-    case TYPE_CODE_MEMBER:
     case TYPE_CODE_COMPLEX:
     case TYPE_CODE_TYPEDEF:
       /* These types do not need a suffix.  They are listed so that
index 6939312d83394278e9e2ab7f2197caa9f9182538..3ef1bd3a45a219a44fd88d003f903f45acf4d1c8 100644 (file)
@@ -235,6 +235,8 @@ struct gdbarch
   gdbarch_register_reggroup_p_ftype *register_reggroup_p;
   gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument;
   gdbarch_regset_from_core_section_ftype *regset_from_core_section;
+  int vtable_function_descriptors;
+  int vbit_in_delta;
 };
 
 
@@ -361,6 +363,8 @@ struct gdbarch startup_gdbarch =
   default_register_reggroup_p,  /* register_reggroup_p */
   0,  /* fetch_pointer_argument */
   0,  /* regset_from_core_section */
+  0,  /* vtable_function_descriptors */
+  0,  /* vbit_in_delta */
   /* startup_gdbarch() */
 };
 
@@ -615,6 +619,8 @@ verify_gdbarch (struct gdbarch *current_gdbarch)
   /* Skip verify of register_reggroup_p, invalid_p == 0 */
   /* Skip verify of fetch_pointer_argument, has predicate */
   /* Skip verify of regset_from_core_section, has predicate */
+  /* Skip verify of vtable_function_descriptors, invalid_p == 0 */
+  /* Skip verify of vbit_in_delta, invalid_p == 0 */
   buf = ui_file_xstrdup (log, &dummy);
   make_cleanup (xfree, buf);
   if (strlen (buf) > 0)
@@ -1595,6 +1601,9 @@ gdbarch_dump (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: value_to_register = <0x%lx>\n",
                       (long) current_gdbarch->value_to_register);
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: vbit_in_delta = %s\n",
+                      paddr_d (current_gdbarch->vbit_in_delta));
 #ifdef TARGET_VIRTUAL_FRAME_POINTER
   fprintf_unfiltered (file,
                       "gdbarch_dump: %s # %s\n",
@@ -1604,6 +1613,9 @@ gdbarch_dump (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: virtual_frame_pointer = <0x%lx>\n",
                       (long) current_gdbarch->virtual_frame_pointer);
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: vtable_function_descriptors = %s\n",
+                      paddr_d (current_gdbarch->vtable_function_descriptors));
 #ifdef TARGET_WRITE_PC
   fprintf_unfiltered (file,
                       "gdbarch_dump: %s # %s\n",
@@ -3653,6 +3665,40 @@ set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch,
   gdbarch->regset_from_core_section = regset_from_core_section;
 }
 
+int
+gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  /* Skip verify of vtable_function_descriptors, invalid_p == 0 */
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_vtable_function_descriptors called\n");
+  return gdbarch->vtable_function_descriptors;
+}
+
+void
+set_gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch,
+                                         int vtable_function_descriptors)
+{
+  gdbarch->vtable_function_descriptors = vtable_function_descriptors;
+}
+
+int
+gdbarch_vbit_in_delta (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  /* Skip verify of vbit_in_delta, invalid_p == 0 */
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_vbit_in_delta called\n");
+  return gdbarch->vbit_in_delta;
+}
+
+void
+set_gdbarch_vbit_in_delta (struct gdbarch *gdbarch,
+                           int vbit_in_delta)
+{
+  gdbarch->vbit_in_delta = vbit_in_delta;
+}
+
 
 /* Keep a registry of per-architecture data-pointers required by GDB
    modules. */
index 30ae3d0164c40becb69adcdb3922fa1d284b24a1..81761f8c1b9466aa33694bf5190488f9e27496c6 100644 (file)
@@ -1383,6 +1383,19 @@ typedef const struct regset * (gdbarch_regset_from_core_section_ftype) (struct g
 extern const struct regset * gdbarch_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size);
 extern void set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch_regset_from_core_section_ftype *regset_from_core_section);
 
+/* If the elements of C++ vtables are in-place function descriptors rather
+   than normal function pointers (which may point to code or a descriptor),
+   set this to one. */
+
+extern int gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch);
+extern void set_gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch, int vtable_function_descriptors);
+
+/* Set if the least significant bit of the delta is used instead of the least
+   significant bit of the pfn for pointers to virtual member functions. */
+
+extern int gdbarch_vbit_in_delta (struct gdbarch *gdbarch);
+extern void set_gdbarch_vbit_in_delta (struct gdbarch *gdbarch, int vbit_in_delta);
+
 extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
 
 
index a3142ff33bbd378df8334901998c9755e1e9c15d..f1549062f9515ccdbf693127f6401df3548026f9 100755 (executable)
@@ -663,6 +663,15 @@ F:=:CORE_ADDR:fetch_pointer_argument:struct frame_info *frame, int argi, struct
 # Return the appropriate register set for a core file section with
 # name SECT_NAME and size SECT_SIZE.
 M::const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size
+
+# If the elements of C++ vtables are in-place function descriptors rather
+# than normal function pointers (which may point to code or a descriptor),
+# set this to one.
+v::int:vtable_function_descriptors:::0:0::0
+
+# Set if the least significant bit of the delta is used instead of the least
+# significant bit of the pfn for pointers to virtual member functions.
+v::int:vbit_in_delta:::0:0::0
 EOF
 }
 
index 8a57678c19cc264e396d61ac9712668962a77236..308e6c21a748409211338e5b90a2919ec5972728 100644 (file)
@@ -621,15 +621,30 @@ replace_type (struct type *ntype, struct type *type)
    of the aggregate that the member belongs to.  */
 
 struct type *
-lookup_member_type (struct type *type, struct type *domain)
+lookup_memberptr_type (struct type *type, struct type *domain)
 {
   struct type *mtype;
 
   mtype = alloc_type (TYPE_OBJFILE (type));
-  smash_to_member_type (mtype, domain, type);
+  smash_to_memberptr_type (mtype, domain, type);
   return (mtype);
 }
 
+/* Return a pointer-to-method type, for a method of type TO_TYPE.  */
+
+struct type *
+lookup_methodptr_type (struct type *to_type)
+{
+  struct type *mtype;
+
+  mtype = alloc_type (TYPE_OBJFILE (to_type));
+  TYPE_TARGET_TYPE (mtype) = to_type;
+  TYPE_DOMAIN_TYPE (mtype) = TYPE_DOMAIN_TYPE (to_type);
+  TYPE_LENGTH (mtype) = cplus_method_ptr_size ();
+  TYPE_CODE (mtype) = TYPE_CODE_METHODPTR;
+  return mtype;
+}
+
 /* Allocate a stub method whose return type is TYPE.  
    This apparently happens for speed of symbol reading, since parsing
    out the arguments to the method is cpu-intensive, the way we are doing
@@ -981,19 +996,20 @@ build_builtin_type_vec128 (void)
   return t;
 }
 
-/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. 
-   A MEMBER is a wierd thing -- it amounts to a typed offset into
-   a struct, e.g. "an int at offset 8".  A MEMBER TYPE doesn't
-   include the offset (that's the value of the MEMBER itself), but does
-   include the structure type into which it points (for some reason).
+/* Smash TYPE to be a type of pointers to members of DOMAIN with type
+   TO_TYPE.  A member pointer is a wierd thing -- it amounts to a
+   typed offset into a struct, e.g. "an int at offset 8".  A MEMBER
+   TYPE doesn't include the offset (that's the value of the MEMBER
+   itself), but does include the structure type into which it points
+   (for some reason).
 
    When "smashing" the type, we preserve the objfile that the
    old type pointed to, since we aren't changing where the type is actually
    allocated.  */
 
 void
-smash_to_member_type (struct type *type, struct type *domain,
-                     struct type *to_type)
+smash_to_memberptr_type (struct type *type, struct type *domain,
+                        struct type *to_type)
 {
   struct objfile *objfile;
 
@@ -1003,8 +1019,10 @@ smash_to_member_type (struct type *type, struct type *domain,
   TYPE_OBJFILE (type) = objfile;
   TYPE_TARGET_TYPE (type) = to_type;
   TYPE_DOMAIN_TYPE (type) = domain;
-  TYPE_LENGTH (type) = 1;      /* In practice, this is never needed.  */
-  TYPE_CODE (type) = TYPE_CODE_MEMBER;
+  /* Assume that a data member pointer is the same size as a normal
+     pointer.  */
+  TYPE_LENGTH (type) = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+  TYPE_CODE (type) = TYPE_CODE_MEMBERPTR;
 }
 
 /* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE.
@@ -2643,7 +2661,7 @@ rank_one_type (struct type *parm, struct type *arg)
          return INCOMPATIBLE_TYPE_BADNESS;
        }
       break;
-    case TYPE_CODE_MEMBER:
+    case TYPE_CODE_MEMBERPTR:
       switch (TYPE_CODE (arg))
        {
        default:
@@ -2957,8 +2975,11 @@ recursive_dump_type (struct type *type, int spaces)
     case TYPE_CODE_ERROR:
       printf_filtered ("(TYPE_CODE_ERROR)");
       break;
-    case TYPE_CODE_MEMBER:
-      printf_filtered ("(TYPE_CODE_MEMBER)");
+    case TYPE_CODE_MEMBERPTR:
+      printf_filtered ("(TYPE_CODE_MEMBERPTR)");
+      break;
+    case TYPE_CODE_METHODPTR:
+      printf_filtered ("(TYPE_CODE_METHODPTR)");
       break;
     case TYPE_CODE_METHOD:
       printf_filtered ("(TYPE_CODE_METHOD)");
index 944e5f12bed78dc54e60f8be8f7472c7fd71de9e..91207372f3684ae081bbd05a1fa816b35283acac 100644 (file)
@@ -142,8 +142,20 @@ enum type_code
     TYPE_CODE_ERROR,
 
     /* C++ */
-    TYPE_CODE_MEMBER,          /* Member type */
     TYPE_CODE_METHOD,          /* Method type */
+
+    /* Pointer-to-member-function type.  This describes how to access a
+       particular member function of a class (possibly a virtual
+       member function).  The representation may vary between different
+       C++ ABIs.  */
+    TYPE_CODE_METHODPTR,
+
+    /* Pointer-to-member type.  This is the offset within a class to some
+       particular data member.  The only currently supported representation
+       uses an unbiased offset, with -1 representing NULL; this is used
+       by the Itanium C++ ABI (used by GCC on all platforms).  */
+    TYPE_CODE_MEMBERPTR,
+
     TYPE_CODE_REF,             /* C++ Reference types */
 
     TYPE_CODE_CHAR,            /* *real* character type */
@@ -464,8 +476,9 @@ struct main_type
   /* For types with virtual functions (TYPE_CODE_STRUCT), VPTR_BASETYPE
      is the base class which defined the virtual function table pointer.  
 
-     For types that are pointer to member types (TYPE_CODE_MEMBER),
-     VPTR_BASETYPE is the type that this pointer is a member of.
+     For types that are pointer to member types (TYPE_CODE_METHODPTR,
+     TYPE_CODE_MEMBERPTR), VPTR_BASETYPE is the type that this pointer
+     is a member of.
 
      For method types (TYPE_CODE_METHOD), VPTR_BASETYPE is the aggregate
      type that contains the method.
@@ -1220,14 +1233,16 @@ extern const char *address_space_int_to_name (int);
 extern struct type *make_type_with_address_space (struct type *type, 
                                                  int space_identifier);
 
-extern struct type *lookup_member_type (struct type *, struct type *);
+extern struct type *lookup_memberptr_type (struct type *, struct type *);
+
+extern struct type *lookup_methodptr_type (struct type *);
 
-extern void
-smash_to_method_type (struct type *type, struct type *domain,
-                     struct type *to_type, struct field *args,
-                     int nargs, int varargs);
+extern void smash_to_method_type (struct type *type, struct type *domain,
+                                 struct type *to_type, struct field *args,
+                                 int nargs, int varargs);
 
-extern void smash_to_member_type (struct type *, struct type *, struct type *);
+extern void smash_to_memberptr_type (struct type *, struct type *,
+                                    struct type *);
 
 extern struct type *allocate_stub_method (struct type *);
 
index 383b475f1b171c5f12a8975ca6c3e7142044993c..c3a3913a2a1ce166a4c31f34a071a5a14545dec0 100644 (file)
@@ -1,7 +1,8 @@
 /* Abstraction of GNU v3 abi.
    Contributed by Jim Blandy <jimb@redhat.com>
 
-   Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2005, 2006
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -25,6 +26,8 @@
 #include "cp-abi.h"
 #include "cp-support.h"
 #include "demangle.h"
+#include "valprint.h"
+
 #include "gdb_assert.h"
 #include "gdb_string.h"
 
@@ -274,79 +277,94 @@ gnuv3_rtti_type (struct value *value,
   return run_time_type;
 }
 
+/* Find the vtable for CONTAINER and return a value of the correct
+   vtable type for this architecture.  */
 
 static struct value *
-gnuv3_virtual_fn_field (struct value **value_p,
-                        struct fn_field *f, int j,
-                       struct type *type, int offset)
+gnuv3_get_vtable (struct value *container)
 {
   struct type *vtable_type = gdbarch_data (current_gdbarch,
                                           vtable_type_gdbarch_data);
-  struct value *value = *value_p;
-  struct type *values_type = check_typedef (value_type (value));
-  struct type *vfn_base;
-  CORE_ADDR vtable_address;
-  struct value *vtable;
-  struct value *vfn;
+  struct type *vtable_pointer_type;
+  struct value *vtable_pointer;
+  CORE_ADDR vtable_pointer_address, vtable_address;
+
+  /* We do not consult the debug information to find the virtual table.
+     The ABI specifies that it is always at offset zero in any class,
+     and debug information may not represent it.  We won't issue an
+     error if there's a class with virtual functions but no virtual table
+     pointer, but something's already gone seriously wrong if that
+     happens.
+
+     We avoid using value_contents on principle, because the object might
+     be large.  */
+
+  /* Find the type "pointer to virtual table".  */
+  vtable_pointer_type = lookup_pointer_type (vtable_type);
+
+  /* Load it from the start of the class.  */
+  vtable_pointer_address = value_as_address (value_addr (container));
+  vtable_pointer = value_at (vtable_pointer_type, vtable_pointer_address);
+  vtable_address = value_as_address (vtable_pointer);
+
+  /* Correct it to point at the start of the virtual table, rather
+     than the address point.  */
+  return value_at_lazy (vtable_type,
+                       vtable_address - vtable_address_point_offset ());
+}
 
-  /* Some simple sanity checks.  */
-  if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
-    error (_("Only classes can have virtual functions."));
+/* Return a function pointer for CONTAINER's VTABLE_INDEX'th virtual
+   function, of type FNTYPE.  */
 
-  /* Find the base class that defines this virtual function.  */
-  vfn_base = TYPE_FN_FIELD_FCONTEXT (f, j);
-  if (! vfn_base)
-    /* In programs compiled with G++ version 1, the debug info doesn't
-       say which base class defined the virtual function.  We'll guess
-       it's the same base class that has our vtable; this is wrong for
-       multiple inheritance, but it's better than nothing.  */
-    vfn_base = TYPE_VPTR_BASETYPE (type);
-
-  /* This type may have been defined before its virtual function table
-     was.  If so, fill in the virtual function table entry for the
-     type now.  */
-  if (TYPE_VPTR_FIELDNO (vfn_base) < 0)
-    fill_in_vptr_fieldno (vfn_base);
-  if (TYPE_VPTR_FIELDNO (vfn_base) < 0)
-    error (_("Could not find virtual table pointer for class \"%s\"."),
-          TYPE_TAG_NAME (vfn_base) ? TYPE_TAG_NAME (vfn_base) : "<unknown>");
-
-  /* Now that we know which base class is defining our virtual
-     function, cast our value to that baseclass.  This takes care of
-     any necessary `this' adjustments.  */
-  if (vfn_base != values_type)
-    value = value_cast (vfn_base, value);
-
-  /* Now value is an object of the appropriate base type.  Fetch its
-     virtual table.  */
-  /* It might be possible to do this cast at the same time as the above.
-     Does multiple inheritance affect this?
-     Can this even trigger, or is TYPE_VPTR_BASETYPE idempotent?
-  */
-  if (TYPE_VPTR_BASETYPE (vfn_base) != vfn_base)
-    value = value_cast (TYPE_VPTR_BASETYPE (vfn_base), value);
-  vtable_address
-    = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (vfn_base)));
-
-  vtable = value_at_lazy (vtable_type,
-                          vtable_address - vtable_address_point_offset ());
+static struct value *
+gnuv3_get_virtual_fn (struct value *container, struct type *fntype,
+                     int vtable_index)
+{
+  struct value *vtable = gnuv3_get_vtable (container);
+  struct value *vfn;
 
   /* Fetch the appropriate function pointer from the vtable.  */
   vfn = value_subscript (value_field (vtable, vtable_field_virtual_functions),
-                         value_from_longest (builtin_type_int,
-                                             TYPE_FN_FIELD_VOFFSET (f, j)));
+                         value_from_longest (builtin_type_int, vtable_index));
 
-  /* Cast the function pointer to the appropriate type.  */
-  vfn = value_cast (lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)),
-                    vfn);
+  /* If this architecture uses function descriptors directly in the vtable,
+     then the address of the vtable entry is actually a "function pointer"
+     (i.e. points to the descriptor).  We don't need to scale the index
+     by the size of a function descriptor; GCC does that before outputing
+     debug information.  */
+  if (gdbarch_vtable_function_descriptors (current_gdbarch))
+    vfn = value_addr (vfn);
 
-  /* Is (type)value always numerically the same as (vfn_base)value?
-     If so we can spare this cast and use one of the ones above.  */
-  *value_p = value_addr (value_cast (type, *value_p));
+  /* Cast the function pointer to the appropriate type.  */
+  vfn = value_cast (lookup_pointer_type (fntype), vfn);
 
   return vfn;
 }
 
+/* GNU v3 implementation of value_virtual_fn_field.  See cp-abi.h
+   for a description of the arguments.  */
+
+static struct value *
+gnuv3_virtual_fn_field (struct value **value_p,
+                        struct fn_field *f, int j,
+                       struct type *vfn_base, int offset)
+{
+  struct type *values_type = check_typedef (value_type (*value_p));
+
+  /* Some simple sanity checks.  */
+  if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
+    error (_("Only classes can have virtual functions."));
+
+  /* Cast our value to the base class which defines this virtual
+     function.  This takes care of any necessary `this'
+     adjustments.  */
+  if (vfn_base != values_type)
+    *value_p = value_cast (vfn_base, *value_p);
+
+  return gnuv3_get_virtual_fn (*value_p, TYPE_FN_FIELD_TYPE (f, j),
+                              TYPE_FN_FIELD_VOFFSET (f, j));
+}
+
 /* Compute the offset of the baseclass which is
    the INDEXth baseclass of class TYPE,
    for value at VALADDR (in host) at ADDRESS (in target).
@@ -416,6 +434,245 @@ gnuv3_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr,
   return base_offset;
 }
 
+/* Locate a virtual method in DOMAIN or its non-virtual base classes
+   which has virtual table index VOFFSET.  The method has an associated
+   "this" adjustment of ADJUSTMENT bytes.  */
+
+const char *
+gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset,
+                     LONGEST adjustment)
+{
+  int i;
+  const char *physname;
+
+  /* Search this class first.  */
+  physname = NULL;
+  if (adjustment == 0)
+    {
+      int len;
+
+      len = TYPE_NFN_FIELDS (domain);
+      for (i = 0; i < len; i++)
+       {
+         int len2, j;
+         struct fn_field *f;
+
+         f = TYPE_FN_FIELDLIST1 (domain, i);
+         len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+         check_stub_method_group (domain, i);
+         for (j = 0; j < len2; j++)
+           if (TYPE_FN_FIELD_VOFFSET (f, j) == voffset)
+             return TYPE_FN_FIELD_PHYSNAME (f, j);
+       }
+    }
+
+  /* Next search non-virtual bases.  If it's in a virtual base,
+     we're out of luck.  */
+  for (i = 0; i < TYPE_N_BASECLASSES (domain); i++)
+    {
+      int pos;
+      struct type *basetype;
+
+      if (BASETYPE_VIA_VIRTUAL (domain, i))
+       continue;
+
+      pos = TYPE_BASECLASS_BITPOS (domain, i) / 8;
+      basetype = TYPE_FIELD_TYPE (domain, i);
+      /* Recurse with a modified adjustment.  We don't need to adjust
+        voffset.  */
+      if (adjustment >= pos && adjustment < pos + TYPE_LENGTH (basetype))
+       return gnuv3_find_method_in (basetype, voffset, adjustment - pos);
+    }
+
+  return NULL;
+}
+
+/* GNU v3 implementation of cplus_print_method_ptr.  */
+
+static void
+gnuv3_print_method_ptr (const gdb_byte *contents,
+                       struct type *type,
+                       struct ui_file *stream)
+{
+  CORE_ADDR ptr_value;
+  LONGEST adjustment;
+  struct type *domain;
+  int vbit;
+
+  domain = TYPE_DOMAIN_TYPE (type);
+
+  /* Extract the pointer to member.  */
+  ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
+  contents += TYPE_LENGTH (builtin_type_void_func_ptr);
+  adjustment = extract_signed_integer (contents,
+                                      TYPE_LENGTH (builtin_type_long));
+
+  if (!gdbarch_vbit_in_delta (current_gdbarch))
+    {
+      vbit = ptr_value & 1;
+      ptr_value = ptr_value ^ vbit;
+    }
+  else
+    {
+      vbit = adjustment & 1;
+      adjustment = adjustment >> 1;
+    }
+
+  /* Check for NULL.  */
+  if (ptr_value == 0 && vbit == 0)
+    {
+      fprintf_filtered (stream, "NULL");
+      return;
+    }
+
+  /* Search for a virtual method.  */
+  if (vbit)
+    {
+      CORE_ADDR voffset;
+      const char *physname;
+
+      /* It's a virtual table offset, maybe in this class.  Search
+        for a field with the correct vtable offset.  First convert it
+        to an index, as used in TYPE_FN_FIELD_VOFFSET.  */
+      voffset = ptr_value / TYPE_LENGTH (builtin_type_long);
+
+      physname = gnuv3_find_method_in (domain, voffset, adjustment);
+
+      /* If we found a method, print that.  We don't bother to disambiguate
+        possible paths to the method based on the adjustment.  */
+      if (physname)
+       {
+         char *demangled_name = cplus_demangle (physname,
+                                                DMGL_ANSI | DMGL_PARAMS);
+         if (demangled_name != NULL)
+           {
+             fprintf_filtered (stream, "&virtual ");
+             fputs_filtered (demangled_name, stream);
+             xfree (demangled_name);
+             return;
+           }
+       }
+    }
+
+  /* We didn't find it; print the raw data.  */
+  if (vbit)
+    {
+      fprintf_filtered (stream, "&virtual table offset ");
+      print_longest (stream, 'd', 1, ptr_value);
+    }
+  else
+    print_address_demangle (ptr_value, stream, demangle);
+
+  if (adjustment)
+    {
+      fprintf_filtered (stream, ", this adjustment ");
+      print_longest (stream, 'd', 1, adjustment);
+    }
+}
+
+/* GNU v3 implementation of cplus_method_ptr_size.  */
+
+static int
+gnuv3_method_ptr_size (void)
+{
+  return 2 * TYPE_LENGTH (builtin_type_void_data_ptr);
+}
+
+/* GNU v3 implementation of cplus_make_method_ptr.  */
+
+static void
+gnuv3_make_method_ptr (gdb_byte *contents, CORE_ADDR value, int is_virtual)
+{
+  int size = TYPE_LENGTH (builtin_type_void_data_ptr);
+
+  /* FIXME drow/2006-12-24: The adjustment of "this" is currently
+     always zero, since the method pointer is of the correct type.
+     But if the method pointer came from a base class, this is
+     incorrect - it should be the offset to the base.  The best
+     fix might be to create the pointer to member pointing at the
+     base class and cast it to the derived class, but that requires
+     support for adjusting pointers to members when casting them -
+     not currently supported by GDB.  */
+
+  if (!gdbarch_vbit_in_delta (current_gdbarch))
+    {
+      store_unsigned_integer (contents, size, value | is_virtual);
+      store_unsigned_integer (contents + size, size, 0);
+    }
+  else
+    {
+      store_unsigned_integer (contents, size, value);
+      store_unsigned_integer (contents + size, size, is_virtual);
+    }
+}
+
+/* GNU v3 implementation of cplus_method_ptr_to_value.  */
+
+static struct value *
+gnuv3_method_ptr_to_value (struct value **this_p, struct value *method_ptr)
+{
+  const gdb_byte *contents = value_contents (method_ptr);
+  CORE_ADDR ptr_value;
+  struct type *final_type, *method_type;
+  LONGEST adjustment;
+  struct value *adjval;
+  int vbit;
+
+  final_type = TYPE_DOMAIN_TYPE (check_typedef (value_type (method_ptr)));
+  final_type = lookup_pointer_type (final_type);
+
+  method_type = TYPE_TARGET_TYPE (check_typedef (value_type (method_ptr)));
+
+  ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
+  contents += TYPE_LENGTH (builtin_type_void_func_ptr);
+  adjustment = extract_signed_integer (contents,
+                                      TYPE_LENGTH (builtin_type_long));
+
+  if (!gdbarch_vbit_in_delta (current_gdbarch))
+    {
+      vbit = ptr_value & 1;
+      ptr_value = ptr_value ^ vbit;
+    }
+  else
+    {
+      vbit = adjustment & 1;
+      adjustment = adjustment >> 1;
+    }
+
+  /* First convert THIS to match the containing type of the pointer to
+     member.  This cast may adjust the value of THIS.  */
+  *this_p = value_cast (final_type, *this_p);
+
+  /* Then apply whatever adjustment is necessary.  This creates a somewhat
+     strange pointer: it claims to have type FINAL_TYPE, but in fact it
+     might not be a valid FINAL_TYPE.  For instance, it might be a
+     base class of FINAL_TYPE.  And if it's not the primary base class,
+     then printing it out as a FINAL_TYPE object would produce some pretty
+     garbage.
+
+     But we don't really know the type of the first argument in
+     METHOD_TYPE either, which is why this happens.  We can't
+     dereference this later as a FINAL_TYPE, but once we arrive in the
+     called method we'll have debugging information for the type of
+     "this" - and that'll match the value we produce here.
+
+     You can provoke this case by casting a Base::* to a Derived::*, for
+     instance.  */
+  *this_p = value_cast (builtin_type_void_data_ptr, *this_p);
+  adjval = value_from_longest (builtin_type_long, adjustment);
+  *this_p = value_add (*this_p, adjval);
+  *this_p = value_cast (final_type, *this_p);
+
+  if (vbit)
+    {
+      LONGEST voffset = ptr_value / TYPE_LENGTH (builtin_type_long);
+      return gnuv3_get_virtual_fn (value_ind (*this_p), method_type, voffset);
+    }
+  else
+    return value_from_pointer (lookup_pointer_type (method_type), ptr_value);
+}
+
 static void
 init_gnuv3_ops (void)
 {
@@ -433,6 +690,10 @@ 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.print_method_ptr = gnuv3_print_method_ptr;
+  gnu_v3_abi_ops.method_ptr_size = gnuv3_method_ptr_size;
+  gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr;
+  gnu_v3_abi_ops.method_ptr_to_value = gnuv3_method_ptr_to_value;
 }
 
 extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */
index cb617783ce3a2f4118450791fbcfa3b48c7d5832..16a445bfead492870d7828bd4b57dcf180f8ed35 100644 (file)
@@ -1,6 +1,6 @@
 /* Read hp debug symbols and convert to internal format, for GDB.
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -4875,9 +4875,7 @@ hpread_type_lookup (dnttpointer hp_type, struct objfile *objfile)
                                      objfile),
          class_type = hpread_type_lookup (dn_bufp->dptrmem.pointsto,
                                           objfile),
-         ptrmemtype = alloc_type (objfile);
-       smash_to_member_type (ptrmemtype, class_type, memtype);
-       return make_pointer_type (ptrmemtype, NULL);
+       return lookup_memberptr_type (memtype, class_type);
       }
       break;
 
@@ -4905,7 +4903,7 @@ hpread_type_lookup (dnttpointer hp_type, struct objfile *objfile)
                              TYPE_FIELDS (functype),
                              TYPE_NFIELDS (functype),
                              0);
-       return make_pointer_type (ptrmemtype, NULL);
+       return lookup_methodptr_type (ptrmemtype);
       }
       break;
 
index f815f6c92a446cbc34015765b1d5844cd4ed912a..00faa3b106bb72e11755e9f2b297363cac1e61df 100644 (file)
@@ -40,6 +40,7 @@
 #include "infcall.h"
 #include "osabi.h"
 #include "ia64-tdep.h"
+#include "cp-abi.h"
 
 #ifdef HAVE_LIBUNWIND_IA64_H
 #include "elf/ia64.h"           /* for PT_IA_64_UNWIND value */
@@ -3306,6 +3307,17 @@ ia64_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
   if (s && strcmp (s->the_bfd_section->name, ".opd") == 0)
     return read_memory_unsigned_integer (addr, 8);
 
+  /* There are also descriptors embedded in vtables.  */
+  if (s)
+    {
+      struct minimal_symbol *minsym;
+
+      minsym = lookup_minimal_symbol_by_pc (addr);
+
+      if (minsym && is_vtable_name (SYMBOL_LINKAGE_NAME (minsym)))
+       return read_memory_unsigned_integer (addr, 8);
+    }
+
   return addr;
 }
 
@@ -3640,6 +3652,10 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_print_insn (gdbarch, ia64_print_insn);
   set_gdbarch_convert_from_func_ptr_addr (gdbarch, ia64_convert_from_func_ptr_addr);
 
+  /* The virtual table contains 16-byte descriptors, not pointers to
+     descriptors.  */
+  set_gdbarch_vtable_function_descriptors (gdbarch, 1);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
index 9f12896102c0aa8f5577d8e4ce2a17b4d24ee0a2..64772d7590fdcdf61d5600eab1dc2fd1d0ac32c9 100644 (file)
@@ -1,7 +1,7 @@
 /* Perform an inferior function call, for GDB, the GNU debugger.
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -169,7 +169,8 @@ value_arg_coerce (struct value *arg, struct type *param_type,
     case TYPE_CODE_STRING:
     case TYPE_CODE_BITSTRING:
     case TYPE_CODE_ERROR:
-    case TYPE_CODE_MEMBER:
+    case TYPE_CODE_MEMBERPTR:
+    case TYPE_CODE_METHODPTR:
     case TYPE_CODE_METHOD:
     case TYPE_CODE_COMPLEX:
     default:
index e057b65ce3c7b075e6598a83cf25ad4ef011769e..cda9189e023d705c2b7a76cd291d03725a0532be 100644 (file)
@@ -112,10 +112,6 @@ m2_print_type (struct type *type, char *varstring, struct ui_file *stream,
       m2_ref (type, stream, show, level);
       break;
 
-    case TYPE_CODE_MEMBER:
-      m2_unknown (_("member"), type, stream, show, level);
-      break;
-
     case TYPE_CODE_METHOD:
       m2_unknown (_("method"), type, stream, show, level);
       break;
index 579ea8b8054f95663da42776eb9f9c7a61969473..7ce653338a783b7c1d6f18afcf00487b82d58b51 100644 (file)
@@ -327,10 +327,6 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
        }
       break;
 
-    case TYPE_CODE_MEMBER:
-      error (_("not implemented: member type in m2_val_print"));
-      break;
-
     case TYPE_CODE_REF:
       elttype = check_typedef (TYPE_TARGET_TYPE (type));
       if (addressprint)
index 8b3ddb8870a4e012d5fb850789b308d1dceb25a7..228422f624bb587cd3e30966b11405f079f55000 100644 (file)
@@ -5231,6 +5231,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
 
+  /* Virtual tables.  */
+  set_gdbarch_vbit_in_delta (gdbarch, 1);
+
   mips_register_g_packet_guesses (gdbarch);
 
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
index 507ff20042895f7d33566eeca44eca24dc7989fa..380d8acf997fb866ec147a3ac2e9235914a3a3ed 100644 (file)
@@ -1,6 +1,6 @@
 /* Pascal language support definitions for GDB, the GNU debugger.
 
-   Copyright (C) 2000, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -67,12 +67,6 @@ extern int vtblprint;                /* Controls printing of vtbl's */
 
 extern int static_field_print;
 
-extern void pascal_object_print_class_member (const gdb_byte *, struct type *,
-                                             struct ui_file *, char *);
-
-extern void pascal_object_print_class_method (const gdb_byte *, struct type *,
-                                             struct ui_file *);
-
 extern void pascal_object_print_value_fields (struct type *, const gdb_byte *,
                                              CORE_ADDR, struct ui_file *,
                                              int, int, enum val_prettyprint,
index 697a2b9ec4ec76f530d546c232f794a536f15700..d6f6b4ba13a38ef553e3e57b6536d95a51778705 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for printing Pascal types for GDB, the GNU debugger.
-   Copyright (C) 2000, 2001, 2002
+   Copyright (C) 2000, 2001, 2002, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -208,19 +208,6 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
       pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
       break;                   /* pointer should be handled normally in pascal */
 
-    case TYPE_CODE_MEMBER:
-      if (passed_a_ptr)
-       fprintf_filtered (stream, "(");
-      pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
-      fprintf_filtered (stream, " ");
-      name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
-      if (name)
-       fputs_filtered (name, stream);
-      else
-       pascal_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
-      fprintf_filtered (stream, "::");
-      break;
-
     case TYPE_CODE_METHOD:
       if (passed_a_ptr)
        fprintf_filtered (stream, "(");
@@ -353,12 +340,6 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
        fprintf_filtered (stream, ")");
       break;
 
-    case TYPE_CODE_MEMBER:
-      if (passed_a_ptr)
-       fprintf_filtered (stream, ")");
-      pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
-      break;
-
     case TYPE_CODE_METHOD:
       if (passed_a_ptr)
        fprintf_filtered (stream, ")");
@@ -481,7 +462,6 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show,
     {
     case TYPE_CODE_TYPEDEF:
     case TYPE_CODE_PTR:
-    case TYPE_CODE_MEMBER:
     case TYPE_CODE_REF:
       /* case TYPE_CODE_FUNC:
          case TYPE_CODE_METHOD: */
index 33b797451ecdd49c7e063323916a02d7925b9357..8304196f1f62ddf7e144fd560815b835b0274e4a 100644 (file)
@@ -151,17 +151,6 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
          break;
        }
       elttype = check_typedef (TYPE_TARGET_TYPE (type));
-      if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
-       {
-         pascal_object_print_class_method (valaddr + embedded_offset, type, stream);
-       }
-      else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
-       {
-         pascal_object_print_class_member (valaddr + embedded_offset,
-                                TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
-                                           stream, "&");
-       }
-      else
        {
          addr = unpack_pointer (type, valaddr + embedded_offset);
        print_unpacked_pointer:
@@ -259,19 +248,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
        }
       break;
 
-    case TYPE_CODE_MEMBER:
-      error (_("not implemented: member type in pascal_val_print"));
-      break;
-
     case TYPE_CODE_REF:
       elttype = check_typedef (TYPE_TARGET_TYPE (type));
-      if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
-       {
-         pascal_object_print_class_member (valaddr + embedded_offset,
-                                           TYPE_DOMAIN_TYPE (elttype),
-                                           stream, "");
-         break;
-       }
       if (addressprint)
        {
          fprintf_filtered (stream, "@");
@@ -604,96 +582,6 @@ static void pascal_object_print_value (struct type *, const gdb_byte *,
                                       int, int, enum val_prettyprint,
                                       struct type **);
 
-void
-pascal_object_print_class_method (const gdb_byte *valaddr, struct type *type,
-                                 struct ui_file *stream)
-{
-  struct type *domain;
-  struct fn_field *f = NULL;
-  int j = 0;
-  int len2;
-  int offset;
-  char *kind = "";
-  CORE_ADDR addr;
-  struct symbol *sym;
-  unsigned len;
-  unsigned int i;
-  struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
-
-  domain = TYPE_DOMAIN_TYPE (target_type);
-  if (domain == (struct type *) NULL)
-    {
-      fprintf_filtered (stream, "<unknown>");
-      return;
-    }
-  addr = unpack_pointer (lookup_pointer_type (builtin_type_void), valaddr);
-  if (METHOD_PTR_IS_VIRTUAL (addr))
-    {
-      offset = METHOD_PTR_TO_VOFFSET (addr);
-      len = TYPE_NFN_FIELDS (domain);
-      for (i = 0; i < len; i++)
-       {
-         f = TYPE_FN_FIELDLIST1 (domain, i);
-         len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
-
-         check_stub_method_group (domain, i);
-         for (j = 0; j < len2; j++)
-           {
-             if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
-               {
-                 kind = "virtual ";
-                 goto common;
-               }
-           }
-       }
-    }
-  else
-    {
-      sym = find_pc_function (addr);
-      if (sym == 0)
-       {
-         error (_("invalid pointer to member function"));
-       }
-      len = TYPE_NFN_FIELDS (domain);
-      for (i = 0; i < len; i++)
-       {
-         f = TYPE_FN_FIELDLIST1 (domain, i);
-         len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
-
-         check_stub_method_group (domain, i);
-         for (j = 0; j < len2; j++)
-           {
-             if (DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
-               goto common;
-           }
-       }
-    }
-common:
-  if (i < len)
-    {
-      char *demangled_name;
-
-      fprintf_filtered (stream, "&");
-      fputs_filtered (kind, stream);
-      demangled_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (f, j),
-                                      DMGL_ANSI | DMGL_PARAMS);
-      if (demangled_name == NULL)
-       fprintf_filtered (stream, "<badly mangled name %s>",
-                         TYPE_FN_FIELD_PHYSNAME (f, j));
-      else
-       {
-         fputs_filtered (demangled_name, stream);
-         xfree (demangled_name);
-       }
-    }
-  else
-    {
-      fprintf_filtered (stream, "(");
-      type_print (type, "", stream, -1);
-      fprintf_filtered (stream, ") %d", (int) addr >> 3);
-    }
-}
-
 /* It was changed to this after 2.4.5.  */
 const char pascal_vtbl_ptr_name[] =
 {'_', '_', 'v', 't', 'b', 'l', '_', 'p', 't', 'r', '_', 't', 'y', 'p', 'e', 0};
@@ -1060,58 +948,6 @@ pascal_object_print_static_field (struct value *val,
   common_val_print (val, stream, format, 0, recurse, pretty);
 }
 
-void
-pascal_object_print_class_member (const gdb_byte *valaddr, struct type *domain,
-                                 struct ui_file *stream, char *prefix)
-{
-
-  /* VAL is a byte offset into the structure type DOMAIN.
-     Find the name of the field for that offset and
-     print it.  */
-  int extra = 0;
-  int bits = 0;
-  unsigned int i;
-  unsigned len = TYPE_NFIELDS (domain);
-  /* @@ Make VAL into bit offset */
-  LONGEST val = unpack_long (builtin_type_int, valaddr) << 3;
-  for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
-    {
-      int bitpos = TYPE_FIELD_BITPOS (domain, i);
-      QUIT;
-      if (val == bitpos)
-       break;
-      if (val < bitpos && i != 0)
-       {
-         /* Somehow pointing into a field.  */
-         i -= 1;
-         extra = (val - TYPE_FIELD_BITPOS (domain, i));
-         if (extra & 0x7)
-           bits = 1;
-         else
-           extra >>= 3;
-         break;
-       }
-    }
-  if (i < len)
-    {
-      char *name;
-      fputs_filtered (prefix, stream);
-      name = type_name_no_tag (domain);
-      if (name)
-       fputs_filtered (name, stream);
-      else
-       pascal_type_print_base (domain, stream, 0, 0);
-      fprintf_filtered (stream, "::");
-      fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
-      if (extra)
-       fprintf_filtered (stream, " + %d bytes", extra);
-      if (bits)
-       fprintf_filtered (stream, " (offset in bits)");
-    }
-  else
-    fprintf_filtered (stream, "%ld", (long int) (val >> 3));
-}
-
 extern initialize_file_ftype _initialize_pascal_valprint; /* -Wmissing-prototypes */
 
 void
index 428cbc2e8bfb0516a43fa00529e9bd66a2cc67a1..a27ee536c95c274fe5f42b4541769ed1f77b8c66 100644 (file)
@@ -1,7 +1,7 @@
 /* Support routines for decoding "stabs" debugging information format.
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -1731,7 +1731,7 @@ again:
 
          memtype = read_type (pp, objfile);
          type = dbx_alloc_type (typenums, objfile);
-         smash_to_member_type (type, domain, memtype);
+         smash_to_memberptr_type (type, domain, memtype);
        }
       else
        /* type attribute */
index dd8c387fe10cbbf772c13df684f6426e9ec008d5..57f8aa6989ca2fa6af5ce3c220e4f0f92d92b28b 100644 (file)
@@ -1,3 +1,21 @@
+2007-01-03  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.cp/classes.exp (test_pointers_to_class_members): Update expected
+       output.  Test the types of members and member pointers.
+       * gdb.cp/inherit.exp (test_print_mi_member_types): Remove KFAILs for
+       gdb/2092.
+       * gdb.cp/member-ptr.exp: Search for a comment instead of a
+       statement.  Enable for GCC.  Update expected output for some tests
+       and add new tests.  Remove obsolete GCC KFAILs.  Allow GCC's class
+       layout.
+       * gdb.cp/member-ptr.cc (Padding, Padding::vspacer, Base, Base::get_x)
+       (Base::vget_base, Left, Left::vget, Right, Right::vget, Diamond)
+       (Diamond::vget_base): New.
+       (main): Add new tests.
+       * gdb.cp/printmethod.exp: Update expected output for member functions.
+       * gdb.cp/virtfunc.exp (test_virtual_calls): Add a KFAIL for
+       print pEe->D::vg().
+
 2007-01-03  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * gdb.threads/tls.exp: Allow stops in sem_post.
index e072667c03a2673554f9ba473e354eefeb0d1b0b..0f8592d5a6d27d135feb3a66874115c23e2474c5 100644 (file)
@@ -1,5 +1,5 @@
 # Copyright 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004 Free Software Foundation, Inc.
+# 2003, 2004, 2006 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
@@ -498,11 +498,14 @@ proc test_enums {} {
 # Pointers to class members
 
 proc test_pointers_to_class_members {} {
-    gdb_test "print Bar::z" "\\$\[0-9\]+ = \\(int ?\\( ?Bar::& ?\\) ?\\) ?Bar::z"
-    gdb_test "print &Foo::x" "\\$\[0-9\]+ = \\(int ?\\( ?Foo::\\* ?\\) ?\\) ?&Foo::x"
+    gdb_test "print Bar::z" "Cannot reference non-static field \"z\""
+    gdb_test "print &Foo::x" "\\$\[0-9\]+ = &Foo::x"
     gdb_test "print (int)&Foo::x" "\\$\[0-9\]+ = 0"
     gdb_test "print (int)&Bar::y == 2*sizeof(int)" "\\$\[0-9\]+ = true"
 
+    gdb_test "ptype Bar::z" "type = int"
+    gdb_test "ptype &Bar::z" "type = int Bar::\\*"
+
     # TODO: this is a bogus test.  It's looking at a variable that
     # has not even been declared yet, so it's accessing random junk
     # on the stack and comparing that it's NOT equal to a specific
index 47a08ae3c2b4b3edb8057945173933b6bb594170..40433deedc6e9fdd025fc64686b8099f5f398503 100644 (file)
@@ -389,29 +389,19 @@ proc test_print_mi_member_types {} {
     # Print the types of qualified members; none of these tests pass today.
 
     # Print all members of g_A.
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_A.A::a" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_A.A::x" "type = int"
 
     # Print all members of g_B.
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_B.A::a" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_B.A::x" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_B.B::b" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_B.B::x" "type = int"
 
     # Print all members of g_C.
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_C.A::a" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_C.A::x" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_C.C::c" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_C.C::x" "type = int"
 
     # Print all members of g_D.
@@ -423,9 +413,6 @@ proc test_print_mi_member_types {} {
 
     set name "ptype g_D.A::a"
     gdb_test_multiple "ptype g_D.A::a" $name {
-       -re "Attempt to take address of non-lval$nl$gdb_prompt $" {
-           kfail "gdb/2092" "$name"
-       }
        -re "type = int$nl$gdb_prompt $" {
            kfail "gdb/68" "ptype g_D.A::a"
        }
@@ -433,25 +420,16 @@ proc test_print_mi_member_types {} {
 
     set name "ptype g_D.A::x"
     gdb_test_multiple "ptype g_D.A::x" $name {
-       -re "Attempt to take address of non-lval$nl$gdb_prompt $" {
-           kfail "gdb/2092" "$name"
-       }
        -re "type = int$nl$gdb_prompt $" {
            kfail "gdb/68" "ptype g_D.A::x"
        }
     }
 
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_D.B::b" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_D.B::x" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_D.C::c" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_D.C::x" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_D.D::d" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_D.D::x" "type = int"
 
     # Print all members of g_E.
@@ -459,9 +437,6 @@ proc test_print_mi_member_types {} {
 
     set name "ptype g_E.A::a"
     gdb_test_multiple "ptype g_E.A::a" $name {
-       -re "Attempt to take address of non-lval$nl$gdb_prompt $" {
-           kfail "gdb/2092" "$name"
-       }
        -re "type = int$nl$gdb_prompt $" {
            kfail "gdb/68" "ptype g_E.A::a"
        }
@@ -469,29 +444,18 @@ proc test_print_mi_member_types {} {
 
     set name "ptype g_E.A::x"
     gdb_test_multiple "ptype g_E.A::x" $name {
-       -re "Attempt to take address of non-lval$nl$gdb_prompt $" {
-           kfail "gdb/2092" "$name"
-       }
        -re "type = int$nl$gdb_prompt $" {
            kfail "gdb/68" "ptype g_E.A::x"
        }
     }
 
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.B::b" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.B::x" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.C::c" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.C::x" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.D::d" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.D::x" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.E::e" "type = int"
-    setup_kfail "gdb/2092" "*-*-*"
     gdb_test "ptype g_E.E::x" "type = int"
 }
 
index e668c4623c1b5de913782dc0f1258c0dc47add44..d93875bd87d39aebfac0b455003a72b1de83adcc 100644 (file)
@@ -1,6 +1,6 @@
 /* This testcase is part of GDB, the GNU debugger.
 
-   Copyright 1998, 1999, 2004 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2004, 2006 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
@@ -81,6 +81,69 @@ typedef int (A::*PMF)(int);
 
 typedef int A::*PMI;
 
+/* This class is in front of the other base classes of Diamond, so
+   that we can detect if the offset for Left or the first Base is
+   added twice - otherwise it would be 2 * 0 == 0.  */
+class Padding
+{
+  int spacer;
+  virtual int vspacer();
+};
+
+int Padding::vspacer()
+{
+  return this->spacer;
+}
+
+class Base
+{
+public:
+  int x;
+  int get_x();
+  virtual int vget_base ();
+};
+
+int Base::get_x ()
+{
+  return this->x;
+}
+
+int Base::vget_base ()
+{
+  return this->x + 1000;
+}
+
+class Left : public Base {
+public:
+  virtual int vget ();
+};
+
+int Left::vget ()
+{
+  return this->x + 100;
+}
+
+class Right : public Base {
+public:
+  virtual int vget ();
+};
+
+int Right::vget ()
+{
+  return this->x + 200;
+}
+
+class Diamond : public Padding, public Left, public Right
+{
+public:
+  virtual int vget_base ();
+};
+
+int Diamond::vget_base ()
+{
+  return this->Left::x + 2000;
+}
+
 int main ()
 {
   A a;
@@ -90,6 +153,18 @@ int main ()
   PMF * pmf_p;
   PMI pmi;
 
+  Diamond diamond;
+  int (Diamond::*left_pmf) ();
+  int (Diamond::*right_pmf) ();
+  int (Diamond::*left_vpmf) ();
+  int (Diamond::*left_base_vpmf) ();
+  int (Diamond::*right_vpmf) ();
+  int (Base::*base_vpmf) ();
+  int Diamond::*diamond_pmi;
+
+  PMI null_pmi;
+  PMF null_pmf;
+
   a.j = 121;
   a.jj = 1331;
   
@@ -101,8 +176,27 @@ int main ()
   pmf = &A::bar;
   pmf_p = &pmf;
 
-  pmi = NULL;
-  
+  diamond.Left::x = 77;
+  diamond.Right::x = 88;
+
+  /* Some valid pointer to members from a base class.  */
+  left_pmf = (int (Diamond::*) ()) (int (Left::*) ()) (&Base::get_x);
+  right_pmf = (int (Diamond::*) ()) (int (Right::*) ()) (&Base::get_x);
+  left_vpmf = &Left::vget;
+  left_base_vpmf = (int (Diamond::*) ()) (int (Left::*) ()) (&Base::vget_base);
+  right_vpmf = &Right::vget;
+
+  /* An unspecified, value preserving pointer to member cast.  */
+  base_vpmf = (int (Base::*) ()) (int (Left::*) ()) &Diamond::vget_base;
+
+  /* A pointer to data member from a base class.  */
+  diamond_pmi = (int Diamond::*) (int Left::*) &Base::x;
+
+  null_pmi = NULL;
+  null_pmf = NULL;
+
+  pmi = NULL; /* Breakpoint 1 here.  */
+
   k = (a.*pmf)(3);
 
   pmi = &A::jj;
index ee1d1abe27d9dad856e75b5c0d0080b1d61d1410..07a9767c59df87ab6478b6fa2d8b6ac2eca223bc 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 1998, 1999, 2003, 2004 Free Software Foundation, Inc.
+# Copyright 1998, 1999, 2003, 2004, 2006 Free Software Foundation, Inc.
 
 # This file is part of the gdb testsuite
 
@@ -20,8 +20,6 @@
 # Written by Satish Pai <pai@apollo.hp.com> 1997-08-19
 # Rewritten by Michael Chastain <mec.gnu@mindspring.com> 2004-01-11
 
-# TODO: copyright notice for member-ptr.cc
-
 set vhn "\\$\[0-9\]+"
 
 if $tracelevel then {
@@ -56,16 +54,9 @@ if ![runto_main] then {
     continue
 }
 
-gdb_breakpoint [gdb_get_line_number "pmi = NULL"]
+gdb_breakpoint [gdb_get_line_number "Breakpoint 1 here"]
 gdb_continue_to_breakpoint "continue to pmi = NULL"
 
-# gcc is not ready for production
-# -- chastain 2004-01-12
-
-if { [test_compiler_info "gcc-*"] } {
-    continue
-}
-
 # ======================
 # pointer to member data
 # ======================
@@ -74,14 +65,9 @@ if { [test_compiler_info "gcc-*"] } {
 
 set name "ptype pmi (A::j)"
 gdb_test_multiple "ptype pmi" $name {
-    -re "type = int *\\( ?A::\\*\\)\r\n$gdb_prompt $" {
+    -re "type = int A::\\*\r\n$gdb_prompt $" {
        pass $name
     }
-    -re "type = int *A::\r\n$gdb_prompt $" {
-       # gcc HEAD 2004-01-10 -gdwarf-2
-       # gcc HEAD 2004-01-10 -gstabs+
-       kfail "gdb/NNNN" $name
-    }
 }
 
 # print pointer to data member
@@ -390,7 +376,7 @@ gdb_test_multiple "ptype *pmi" $name {
 
 set name "print (int) pmi"
 gdb_test_multiple "print (int) pmi" $name {
-    -re "$vhn = (4|8)\r\n$gdb_prompt" {
+    -re "$vhn = (4|8|12)\r\n$gdb_prompt" {
        pass $name
     }
 }
@@ -412,7 +398,7 @@ gdb_test_multiple "print ((int) pmi) == ((char *) &a.j - (char *) & a)" $name {
 
 set name "ptype pmf"
 gdb_test_multiple "ptype pmf" $name {
-    -re "type = int \\( ?A::\\*\\)\\(int\\)\r\n$gdb_prompt $" {
+    -re "type = int \\( ?A::\\*\\)\\(A \\*, int\\)\r\n$gdb_prompt $" {
        pass $name
     }
     -re "type = int \\( ?A::\\*\\)\\(void\\)\r\n$gdb_prompt $" {
@@ -434,7 +420,7 @@ gdb_test_multiple "ptype pmf" $name {
 
 set name "print pmf"
 gdb_test_multiple "print pmf" $name {
-    -re "$vhn = &A::bar\r\n$gdb_prompt $" {
+    -re "$vhn = $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
        pass $name
     }
     -re "$vhn = .*not supported with HP aCC.*\r\n$gdb_prompt $" {
@@ -456,7 +442,7 @@ gdb_test_multiple "print pmf" $name {
 
 set name "ptype pmf_p"
 gdb_test_multiple "ptype pmf_p" $name {
-    -re "type = int \\( ?A::\\*\\*\\)\\(int\\)\r\n$gdb_prompt $" {
+    -re "type = int \\( ?A::\\*\\*\\)\\(A \\*, int\\)\r\n$gdb_prompt $" {
        pass $name
     }
     -re "type = int \\( ?A::\\*\\*\\)\\(void\\)\r\n$gdb_prompt $" {
@@ -498,7 +484,7 @@ gdb_test_multiple "print pmf_p" $name {
 
 set name "print a.*pmf"
 gdb_test_multiple "print a.*pmf" $name {
-    -re "$vhn = \\(int \\(\\*\\)\\(int\\)\\) $hex <A::bar\\(int\\)>\r\n$gdb_prompt$ " {
+    -re "$vhn = {int \\(A \\*, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
        pass $name
     }
     -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" {
@@ -520,7 +506,7 @@ gdb_test_multiple "print a.*pmf" $name {
 
 set name "print a_p->*pmf"
 gdb_test_multiple "print a_p->*pmf" $name {
-    -re "$vhn = \\(int \\(\\*\\)\\(int\\)\\) $hex <A::bar\\(int\\)>\r\n$gdb_prompt$ " {
+    -re "$vhn = {int \\(A \\*, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
        pass $name
     }
     -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" {
@@ -621,3 +607,56 @@ gdb_test_multiple "print (a.*pmf)(3)" $name {
        kfail "gdb/NNNN" $name
     }
 }
+
+# Print out a pointer to data member which requires looking into
+# a base class.
+gdb_test "print diamond_pmi" "$vhn = &Base::x"
+gdb_test "print diamond.*diamond_pmi" "$vhn = 77"
+
+# Examine some more complicated pmfs, which require adjusting "this"
+# and looking through virtual tables.
+
+# These two have a different object adjustment, but call the same method.
+gdb_test "print diamond.*left_pmf" \
+    "$vhn = {int \\(Diamond \\*\\)} $hex <Base::get_x\\((void|)\\)>"
+gdb_test "print diamond.*right_pmf" \
+    "$vhn = {int \\(Diamond \\*\\)} $hex <Base::get_x\\((void|)\\)>"
+
+gdb_test "print (diamond.*left_pmf) ()" "$vhn = 77"
+gdb_test "print (diamond.*right_pmf) ()" "$vhn = 88"
+
+# These two point to different methods, although they have the same
+# virtual table offsets.
+gdb_test "print diamond.*left_vpmf" \
+    "$vhn = {int \\(Diamond \\*\\)} $hex <Left::vget\\((void|)\\)>"
+gdb_test "print diamond.*right_vpmf" \
+    "$vhn = {int \\(Diamond \\*\\)} $hex <Right::vget\\((void|)\\)>"
+
+gdb_test "print (diamond.*left_vpmf) ()" "$vhn = 177"
+gdb_test "print (diamond.*left_base_vpmf) ()" "$vhn = 2077"
+gdb_test "print (diamond.*right_vpmf) ()" "$vhn = 288"
+
+# We should be able to figure out left_vpmf even without an object,
+# because it comes from a non-virtual base.  The same for right_vpmf.
+gdb_test "print left_vpmf" "$vhn = &virtual Left::vget\\(\\)"
+gdb_test "print right_vpmf" "$vhn = &virtual Right::vget\\(\\)"
+
+# But we should gracefully fail to figure out base_vpmf, because
+# its runtime type is more derived than its static type.  This
+# is a valid but unspecified cast (it is value preserving, i.e.
+# can be casted back to the correct type and used).
+gdb_test "print base_vpmf" \
+    "$vhn = &virtual table offset \[0-9\]*, this adjustment -\[0-9\]*"
+
+# Make sure we parse this correctly; it's invalid.
+gdb_test "print diamond.*left_vpmf ()" \
+    "Invalid data type for function to be called\\."
+
+# NULL pointer to member tests.
+gdb_test "print null_pmi" "$vhn = NULL"
+gdb_test "print null_pmi = &A::j" "$vhn = &A::j"
+gdb_test "print null_pmi = 0" "$vhn = NULL"
+
+gdb_test "print null_pmf" "$vhn = NULL"
+gdb_test "print null_pmf = &A::foo" "$vhn = $hex <A::foo ?\\(int\\)>"
+gdb_test "print null_pmf = 0" "$vhn = NULL"
index 8c7a9c0e8e30299b205ac04cc39a0e4ff915f00e..072695611cd1ceaf7abbc3d24df4b7695816aadd 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2002, 2003, 2005 Free Software Foundation, Inc.
+# Copyright 2002, 2003, 2005, 2006 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
@@ -63,8 +63,12 @@ gdb_continue_to_breakpoint "end of constructors"
 
 # The first of these is for PR gdb/653.
 
-gdb_test "print theA->virt" "\\$\[0-9\]* = &A::virt\\((void|)\\)" "print virtual method."
-gdb_test "print theA->nonvirt" "\\$\[0-9\]* = &A::nonvirt\\((void|)\\)" "print nonvirtual method."
+gdb_test "print theA->virt" \
+    "\\$\[0-9\]* = {void \\(A \\*\\)} $hex <A::virt\\((void|)\\)>" \
+    "print virtual method."
+gdb_test "print theA->nonvirt" \
+    "\\$\[0-9\]* = {void \\(A \\*\\)} $hex <A::nonvirt\\((void|)\\)>" \
+    "print nonvirtual method."
 
 gdb_exit
 return 0
index 2da076381254c2fff91faf19e946322e4b1a2bdb..a9c9c7bf08eb037492ab48741ca77ed66aa920bc 100644 (file)
@@ -1,4 +1,5 @@
-# Copyright 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004
+# Copyright 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004,
+# 2006
 # Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
@@ -217,6 +218,14 @@ proc test_virtual_calls {} {
        -re "\\$\[0-9]+ = 102$nl$gdb_prompt $" {
            pass "print pEe->D::vg()"
        }
+       -re "\\$\[0-9]+ = 202$nl$gdb_prompt $" {
+           # To get this result, we have called pEe->*(&D::vg) ().
+           # That's how GDB interprets this, but it's wrong; in fact
+           # the explicit D:: means to bypass virtual function lookup,
+           # and call D::vg as if it were non-virtual.  We still have
+           # to e.g. adjust "this", though.
+           kfail "gdb/1064" "print pEe->D::vg()"
+       }
        -re "Attempt to take address of value not located in memory.$nl$gdb_prompt $" {
            kfail "gdb/1064" "print pEe->D::vg()"
        }
index d31d521bf8f1512f3a5e5b46f531b83f7888fdaa..fb8280814788b5d1aea9d2ac86148d422165deda 100644 (file)
@@ -1,7 +1,7 @@
 /* Language independent support for printing types for GDB, the GNU debugger.
 
    Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998,
-   1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2003, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -257,7 +257,8 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream)
     case TYPE_CODE_SET:
     case TYPE_CODE_STRING:
     case TYPE_CODE_ERROR:
-    case TYPE_CODE_MEMBER:
+    case TYPE_CODE_MEMBERPTR:
+    case TYPE_CODE_METHODPTR:
     case TYPE_CODE_METHOD:
     case TYPE_CODE_REF:
     case TYPE_CODE_NAMESPACE:
index 15c407c0af264e9995a5f284a522dae2e9c65cec..b6a0ad76f9183da88ebef57cf26a5a3593b189b5 100644 (file)
@@ -1,7 +1,8 @@
 /* Perform non-arithmetic operations on values, for GDB.
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -97,14 +98,15 @@ static struct value *value_struct_elt_for_reference (struct type *domain,
                                                     struct type *curtype,
                                                     char *name,
                                                     struct type *intype,
+                                                    int want_address,
                                                     enum noside noside);
 
 static struct value *value_namespace_elt (const struct type *curtype,
-                                         char *name,
+                                         char *name, int want_address,
                                          enum noside noside);
 
 static struct value *value_maybe_namespace_elt (const struct type *curtype,
-                                               char *name,
+                                               char *name, int want_address,
                                                enum noside noside);
 
 static CORE_ADDR allocate_space_in_inferior (int);
@@ -259,6 +261,7 @@ value_cast_pointers (struct type *type, struct value *arg2)
     }
 
   /* No superclass found, just change the pointer type.  */
+  arg2 = value_copy (arg2);
   deprecated_set_value_type (arg2, type);
   arg2 = value_change_enclosing_type (arg2, type);
   set_value_pointed_to_offset (arg2, 0);       /* pai: chk_val */
@@ -366,33 +369,24 @@ value_cast (struct type *type, struct value *arg2)
     return value_from_double (type, value_as_double (arg2));
   else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM
            || code1 == TYPE_CODE_RANGE)
-          && (scalar || code2 == TYPE_CODE_PTR))
+          && (scalar || code2 == TYPE_CODE_PTR
+              || code2 == TYPE_CODE_MEMBERPTR))
     {
       LONGEST longest;
 
-      if (deprecated_hp_som_som_object_present /* if target compiled by HP aCC */
-         && (code2 == TYPE_CODE_PTR))
+      /* If target compiled by HP aCC.  */
+      if (deprecated_hp_som_som_object_present
+         && code2 == TYPE_CODE_MEMBERPTR)
        {
          unsigned int *ptr;
          struct value *retvalp;
 
-         switch (TYPE_CODE (TYPE_TARGET_TYPE (type2)))
-           {
-             /* With HP aCC, pointers to data members have a bias */
-           case TYPE_CODE_MEMBER:
-             retvalp = value_from_longest (type, value_as_long (arg2));
-             /* force evaluation */
-             ptr = (unsigned int *) value_contents (retvalp);
-             *ptr &= ~0x20000000;      /* zap 29th bit to remove bias */
-             return retvalp;
-
-             /* While pointers to methods don't really point to a function */
-           case TYPE_CODE_METHOD:
-             error (_("Pointers to methods not supported with HP aCC"));
-
-           default:
-             break;            /* fall out and go to normal handling */
-           }
+         /* With HP aCC, pointers to data members have a bias.  */
+         retvalp = value_from_longest (type, value_as_long (arg2));
+         /* force evaluation */
+         ptr = (unsigned int *) value_contents (retvalp);
+         *ptr &= ~0x20000000;  /* zap 29th bit to remove bias */
+         return retvalp;
        }
 
       /* When we cast pointers to integers, we mustn't use
@@ -434,11 +428,26 @@ value_cast (struct type *type, struct value *arg2)
        }
       return value_from_longest (type, longest);
     }
+  else if (code1 == TYPE_CODE_METHODPTR && code2 == TYPE_CODE_INT
+          && value_as_long (arg2) == 0)
+    {
+      struct value *result = allocate_value (type);
+      cplus_make_method_ptr (value_contents_writeable (result), 0, 0);
+      return result;
+    }
+  else if (code1 == TYPE_CODE_MEMBERPTR && code2 == TYPE_CODE_INT
+          && value_as_long (arg2) == 0)
+    {
+      /* The Itanium C++ ABI represents NULL pointers to members as
+        minus one, instead of biasing the normal case.  */
+      return value_from_longest (type, -1);
+    }
   else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
     {
       if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
        return value_cast_pointers (type, arg2);
 
+      arg2 = value_copy (arg2);
       deprecated_set_value_type (arg2, type);
       arg2 = value_change_enclosing_type (arg2, type);
       set_value_pointed_to_offset (arg2, 0);   /* pai: chk_val */
@@ -940,9 +949,6 @@ value_ind (struct value *arg1)
 
   base_type = check_typedef (value_type (arg1));
 
-  if (TYPE_CODE (base_type) == TYPE_CODE_MEMBER)
-    error (_("not implemented: member types in value_ind"));
-
   /* Allow * on an integer so we can cast it to whatever we want.
      This returns an int, which seems like the most C-like thing
      to do.  "long long" variables are rare enough that
@@ -957,9 +963,17 @@ value_ind (struct value *arg1)
       /* Get the real type of the enclosing object */
       enc_type = check_typedef (value_enclosing_type (arg1));
       enc_type = TYPE_TARGET_TYPE (enc_type);
-      /* Retrieve the enclosing object pointed to */
-      arg2 = value_at_lazy (enc_type, (value_as_address (arg1)
-                                      - value_pointed_to_offset (arg1)));
+
+      if (TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_FUNC
+         || TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_METHOD)
+       /* For functions, go through find_function_addr, which knows
+          how to handle function descriptors.  */
+       arg2 = value_at_lazy (enc_type, find_function_addr (arg1, NULL));
+      else
+       /* Retrieve the enclosing object pointed to */
+       arg2 = value_at_lazy (enc_type, (value_as_address (arg1)
+                                        - value_pointed_to_offset (arg1)));
+
       /* Re-adjust type */
       deprecated_set_value_type (arg2, TYPE_TARGET_TYPE (base_type));
       /* Add embedding info */
@@ -1599,9 +1613,6 @@ value_struct_elt (struct value **argp, struct value **args,
       t = check_typedef (value_type (*argp));
     }
 
-  if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
-    error (_("not implemented: member type in value_struct_elt"));
-
   if (TYPE_CODE (t) != TYPE_CODE_STRUCT
       && TYPE_CODE (t) != TYPE_CODE_UNION)
     error (_("Attempt to extract a component of a value that is not a %s."), err);
@@ -1798,9 +1809,6 @@ value_find_oload_method_list (struct value **argp, char *method, int offset,
       t = check_typedef (value_type (*argp));
     }
 
-  if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
-    error (_("Not implemented: member type in value_find_oload_lis"));
-
   if (TYPE_CODE (t) != TYPE_CODE_STRUCT
       && TYPE_CODE (t) != TYPE_CODE_UNION)
     error (_("Attempt to extract a component of a value that is not a struct or union"));
@@ -2334,9 +2342,6 @@ check_field (struct value *arg1, const char *name)
       t = TYPE_TARGET_TYPE (t);
     }
 
-  if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
-    error (_("not implemented: member type in check_field"));
-
   if (TYPE_CODE (t) != TYPE_CODE_STRUCT
       && TYPE_CODE (t) != TYPE_CODE_UNION)
     error (_("Internal error: `this' is not an aggregate"));
@@ -2345,14 +2350,14 @@ check_field (struct value *arg1, const char *name)
 }
 
 /* C++: Given an aggregate type CURTYPE, and a member name NAME,
-   return the appropriate member.  This function is used to resolve
-   user expressions of the form "DOMAIN::NAME".  For more details on
-   what happens, see the comment before
-   value_struct_elt_for_reference.  */
+   return the appropriate member (or the address of the member, if
+   WANT_ADDRESS).  This function is used to resolve user expressions
+   of the form "DOMAIN::NAME".  For more details on what happens, see
+   the comment before value_struct_elt_for_reference.  */
 
 struct value *
 value_aggregate_elt (struct type *curtype,
-                    char *name,
+                    char *name, int want_address,
                     enum noside noside)
 {
   switch (TYPE_CODE (curtype))
@@ -2360,9 +2365,9 @@ value_aggregate_elt (struct type *curtype,
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
       return value_struct_elt_for_reference (curtype, 0, curtype, name, NULL,
-                                            noside);
+                                            want_address, noside);
     case TYPE_CODE_NAMESPACE:
-      return value_namespace_elt (curtype, name, noside);
+      return value_namespace_elt (curtype, name, want_address, noside);
     default:
       internal_error (__FILE__, __LINE__,
                      _("non-aggregate type in value_aggregate_elt"));
@@ -2379,12 +2384,12 @@ value_aggregate_elt (struct type *curtype,
 static struct value *
 value_struct_elt_for_reference (struct type *domain, int offset,
                                struct type *curtype, char *name,
-                               struct type *intype,
+                               struct type *intype, int want_address,
                                enum noside noside)
 {
   struct type *t = curtype;
   int i;
-  struct value *v;
+  struct value *v, *result;
 
   if (TYPE_CODE (t) != TYPE_CODE_STRUCT
       && TYPE_CODE (t) != TYPE_CODE_UNION)
@@ -2402,15 +2407,21 @@ value_struct_elt_for_reference (struct type *domain, int offset,
              if (v == NULL)
                error (_("static field %s has been optimized out"),
                       name);
+             if (want_address)
+               v = value_addr (v);
              return v;
            }
          if (TYPE_FIELD_PACKED (t, i))
            error (_("pointers to bitfield members not allowed"));
 
-         return value_from_longest
-           (lookup_reference_type (lookup_member_type (TYPE_FIELD_TYPE (t, i),
-                                                       domain)),
-            offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
+         if (want_address)
+           return value_from_longest
+             (lookup_memberptr_type (TYPE_FIELD_TYPE (t, i), domain),
+              offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
+         else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return allocate_value (TYPE_FIELD_TYPE (t, i));
+         else
+           error (_("Cannot reference non-static field \"%s\""), name);
        }
     }
 
@@ -2461,33 +2472,52 @@ value_struct_elt_for_reference (struct type *domain, int offset,
          else
            j = 0;
 
+         if (TYPE_FN_FIELD_STATIC_P (f, j))
+           {
+             struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
+                                               0, VAR_DOMAIN, 0, NULL);
+             if (s == NULL)
+               return NULL;
+
+             if (want_address)
+               return value_addr (read_var_value (s, 0));
+             else
+               return read_var_value (s, 0);
+           }
+
          if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
            {
-             return value_from_longest
-               (lookup_reference_type
-                (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
-                                     domain)),
-                (LONGEST) METHOD_PTR_FROM_VOFFSET (TYPE_FN_FIELD_VOFFSET (f, j)));
+             if (want_address)
+               {
+                 result = allocate_value
+                   (lookup_methodptr_type (TYPE_FN_FIELD_TYPE (f, j)));
+                 cplus_make_method_ptr (value_contents_writeable (result),
+                                        TYPE_FN_FIELD_VOFFSET (f, j), 1);
+               }
+             else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+               return allocate_value (TYPE_FN_FIELD_TYPE (f, j));
+             else
+               error (_("Cannot reference virtual member function \"%s\""),
+                      name);
            }
          else
            {
              struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
                                                0, VAR_DOMAIN, 0, NULL);
              if (s == NULL)
-               {
-                 v = 0;
-               }
+               return NULL;
+
+             v = read_var_value (s, 0);
+             if (!want_address)
+               result = v;
              else
                {
-                 v = read_var_value (s, 0);
-#if 0
-                 VALUE_TYPE (v) = lookup_reference_type
-                   (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
-                                        domain));
-#endif
+                 result = allocate_value (lookup_methodptr_type (TYPE_FN_FIELD_TYPE (f, j)));
+                 cplus_make_method_ptr (value_contents_writeable (result),
+                                        VALUE_ADDRESS (v), 0);
                }
-             return v;
            }
+         return result;
        }
     }
   for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--)
@@ -2503,7 +2533,7 @@ value_struct_elt_for_reference (struct type *domain, int offset,
                                          offset + base_offset,
                                          TYPE_BASECLASS (t, i),
                                          name,
-                                         intype,
+                                         intype, want_address,
                                          noside);
       if (v)
        return v;
@@ -2513,7 +2543,7 @@ value_struct_elt_for_reference (struct type *domain, int offset,
      it up that way; this (frequently) works for types nested inside
      classes.  */
 
-  return value_maybe_namespace_elt (curtype, name, noside);
+  return value_maybe_namespace_elt (curtype, name, want_address, noside);
 }
 
 /* C++: Return the member NAME of the namespace given by the type
@@ -2521,11 +2551,11 @@ value_struct_elt_for_reference (struct type *domain, int offset,
 
 static struct value *
 value_namespace_elt (const struct type *curtype,
-                    char *name,
+                    char *name, int want_address,
                     enum noside noside)
 {
   struct value *retval = value_maybe_namespace_elt (curtype, name,
-                                                   noside);
+                                                   want_address, noside);
 
   if (retval == NULL)
     error (_("No symbol \"%s\" in namespace \"%s\"."), name,
@@ -2542,11 +2572,12 @@ value_namespace_elt (const struct type *curtype,
 
 static struct value *
 value_maybe_namespace_elt (const struct type *curtype,
-                          char *name,
+                          char *name, int want_address,
                           enum noside noside)
 {
   const char *namespace_name = TYPE_TAG_NAME (curtype);
   struct symbol *sym;
+  struct value *result;
 
   sym = cp_lookup_symbol_namespace (namespace_name, name, NULL,
                                    get_selected_block (0), VAR_DOMAIN,
@@ -2556,9 +2587,14 @@ value_maybe_namespace_elt (const struct type *curtype,
     return NULL;
   else if ((noside == EVAL_AVOID_SIDE_EFFECTS)
           && (SYMBOL_CLASS (sym) == LOC_TYPEDEF))
-    return allocate_value (SYMBOL_TYPE (sym));
+    result = allocate_value (SYMBOL_TYPE (sym));
   else
-    return value_of_variable (sym, get_selected_block (0));
+    result = value_of_variable (sym, get_selected_block (0));
+
+  if (result && want_address)
+    result = value_addr (result);
+
+  return result;
 }
 
 /* Given a pointer value V, find the real (RTTI) type
index c01444a4e9fc54493390cb68c14f1bd9202d8190..e1869acd57c7b0ce8957a5eab40760b505bcef1a 100644 (file)
@@ -1090,6 +1090,7 @@ unpack_long (struct type *type, const gdb_byte *valaddr)
     case TYPE_CODE_INT:
     case TYPE_CODE_CHAR:
     case TYPE_CODE_RANGE:
+    case TYPE_CODE_MEMBERPTR:
       if (nosign)
        return extract_unsigned_integer (valaddr, len);
       else
@@ -1104,9 +1105,6 @@ unpack_long (struct type *type, const gdb_byte *valaddr)
          whether we want this to be true eventually.  */
       return extract_typed_address (valaddr, type);
 
-    case TYPE_CODE_MEMBER:
-      error (_("not implemented: member types in unpack_long"));
-
     default:
       error (_("Value can't be converted to integer."));
     }
@@ -1537,6 +1535,7 @@ retry:
     case TYPE_CODE_FLAGS:
     case TYPE_CODE_BOOL:
     case TYPE_CODE_RANGE:
+    case TYPE_CODE_MEMBERPTR:
       store_signed_integer (value_contents_raw (val), len, num);
       break;
 
index 001761a83c6229302bc2220c4e9bc112ad4a3578..4c7990035edb0ea743e1f9f56014fb023d559489 100644 (file)
@@ -1,7 +1,8 @@
 /* Definitions for values of C expressions, for GDB.
 
    Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -345,7 +346,9 @@ extern struct value *value_struct_elt (struct value **argp,
                                       char *err);
 
 extern struct value *value_aggregate_elt (struct type *curtype,
-                                         char *name, enum noside noside);
+                                         char *name,
+                                         int want_address,
+                                         enum noside noside);
 
 extern struct value *value_static_field (struct type *type, int fieldno);
 
index 92d43cba94a8d2708ed5cd80981d1745fa882476..25860cbd502cf63b7dd554e6dd06fee7e1abfef2 100644 (file)
@@ -2106,7 +2106,6 @@ c_variable_editable (struct varobj *var)
     case TYPE_CODE_UNION:
     case TYPE_CODE_ARRAY:
     case TYPE_CODE_FUNC:
-    case TYPE_CODE_MEMBER:
     case TYPE_CODE_METHOD:
       return 0;
       break;