* [c++] Pointer to member overhaul
@ 2006-12-29 2:55 Daniel Jacobowitz
2006-12-29 19:06 ` Jim Blandy
2007-01-03 18:15 ` Daniel Jacobowitz
0 siblings, 2 replies; 9+ messages in thread
From: Daniel Jacobowitz @ 2006-12-29 2:55 UTC (permalink / raw)
To: gdb-patches
A bit of history: before I got sidetracked onto this patch, I was
working on support for ARM's compiler. This produces generally good
DWARF, but without several GNU extensions to DWARF that GCC generates
to make life easier for GDB's generally stabs-centric data structures.
So I was going through uses of various type information that aren't
available with that compiler. Among them: DW_AT_MIPS_linkage_name,
VPTR_FIELDNO, and FIELD_FCONTEXT. The first usage I picked turned
out to have a heavyweight mess under it.
GDB handles pointers to members in a way which only worked for some
older compilers (depending which bits of the code you're looking at,
I think it's either early GCC 2.x, or HP aCC, or both). Part of the
problem was the concept of a "reference to member" type, which doesn't
exist in C++.
Another problem was representational; some parts of GDB assumed
that TYPE_CODE_MEMBER was a pointer to member, and other bits assumed
that TYPE_CODE_PTR to a TYPE_CODE_MEMBER was.
Pointers to members, if you aren't familiar with them, describe some
data or function member of a class in terms of its signature. You can
write something like this:
int (A::*a_pmf) (int) = &A::func;
Later you can call it by applying it to an object. You can't do
anything with one without an object except cast them around; g++
lets you convert a pointer to data member (represented as an
offset) into the offset via a cast. GDB supports decoding the
pointer to member into a generally readable form; I've improved
that ability to handle a lot more cases.
Pointers to data members, pointers to function members, and pointers
to normal variables are essentially three different things. I decided
that representing them using TYPE_CODE_PTR was a mistake; they aren't
much like pointers. So this class replaces the confused
TYPE_CODE_MEMBER with TYPE_CODE_MEMBERPTR and TYPE_CODE_METHODPTR.
Then I moved the ABI specific bits for function member pointers to
cp-abi.h and implemented them for G++, and corrected everything I could
think of to test along the way. Lots of new testcases.
I know a great deal more about member pointers than I did when I
started, including several more things we don't get right, but I don't
think I'm going to take it much farther than this. Extensive
conversations with Mark Mitchell, my official C++ guru, have convinced
me that unless we link GDB with G++ there's no practical way we're
going to get expression evaluation, and in particular overload
resolution, 100% right. But we can do a heck of a lot better than we
do now.
So here's what that gave me, after six months. I separated out the
separable parts of this patch back in August, so I'm left with a big
lump. I've tested the final version on ia64-linux and x86_64-linux.
Near-final versions were also tested on arm-eabi, i686-linux, and
powerpc64-linux.
This patch is limited to C++ support and the surrounding value / type
machinery. I suspect it's too big for anyone to review usefully, but
in case anyone is willing to look at it, I will wait until 2007 to
commit it. I'm confident that it is strictly an improvement.
--
Daniel Jacobowitz
CodeSourcery
2006-12-28 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.
2006-12-28 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().
Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.861
diff -u -p -r1.861 Makefile.in
--- gdb/Makefile.in 17 Dec 2006 13:30:43 -0000 1.861
+++ gdb/Makefile.in 29 Dec 2006 00:13:20 -0000
@@ -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
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) $(g
$(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) $(inf
$(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: gdb/ada-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/ada-valprint.c,v
retrieving revision 1.28
diff -u -p -r1.28 ada-valprint.c
--- gdb/ada-valprint.c 18 Jan 2006 21:24:19 -0000 1.28
+++ gdb/ada-valprint.c 29 Dec 2006 00:13:20 -0000
@@ -420,7 +420,8 @@ ada_print_scalar (struct type *type, LON
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: gdb/arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.217
diff -u -p -r1.217 arm-tdep.c
--- gdb/arm-tdep.c 22 Nov 2006 18:51:58 -0000 1.217
+++ gdb/arm-tdep.c 29 Dec 2006 00:13:21 -0000
@@ -2816,6 +2816,9 @@ arm_gdbarch_init (struct gdbarch_info in
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: gdb/c-lang.h
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.h,v
retrieving revision 1.13
diff -u -p -r1.13 c-lang.h
--- gdb/c-lang.h 17 Dec 2005 22:33:59 -0000 1.13
+++ gdb/c-lang.h 29 Dec 2006 00:13:21 -0000
@@ -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: gdb/c-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-typeprint.c,v
retrieving revision 1.33
diff -u -p -r1.33 c-typeprint.c
--- gdb/c-typeprint.c 17 Dec 2005 22:33:59 -0000 1.33
+++ gdb/c-typeprint.c 29 Dec 2006 00:13:21 -0000
@@ -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 *v
(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
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
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
}
-
+/* 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
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
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, st
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: gdb/c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.39
diff -u -p -r1.39 c-valprint.c
--- gdb/c-valprint.c 18 Jan 2006 21:24:19 -0000 1.39
+++ gdb/c-valprint.c 29 Dec 2006 00:13:21 -0000
@@ -142,6 +142,21 @@ c_val_print (struct type *type, const gd
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 gd
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 gd
}
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 gd
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 gd
}
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: gdb/cp-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-abi.c,v
retrieving revision 1.13
diff -u -p -r1.13 cp-abi.c
--- gdb/cp-abi.c 17 Dec 2005 22:33:59 -0000 1.13
+++ gdb/cp-abi.c 29 Dec 2006 00:13:21 -0000
@@ -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 *f
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: gdb/cp-abi.h
===================================================================
RCS file: /cvs/src/src/gdb/cp-abi.h,v
retrieving revision 1.9
diff -u -p -r1.9 cp-abi.h
--- gdb/cp-abi.h 17 Dec 2005 22:33:59 -0000 1.9
+++ gdb/cp-abi.h 29 Dec 2006 00:13:21 -0000
@@ -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 (str
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
+ bytes forming 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_target. */
+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: gdb/cp-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-valprint.c,v
retrieving revision 1.45
diff -u -p -r1.45 cp-valprint.c
--- gdb/cp-valprint.c 5 Dec 2006 23:57:53 -0000 1.45
+++ gdb/cp-valprint.c 29 Dec 2006 00:13:21 -0000
@@ -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
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);
-
- /* @@ Make VAL into bit offset */
+ unsigned int fieldno;
- /* 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! */
+ LONGEST val = unpack_long (builtin_type_long, valaddr);
- /* Note: HP cfront uses a constant bias of 1; if we support this
- compiler ever, we will have to adjust the computation below */
+ /* 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. */
- 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 *v
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: gdb/dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.207
diff -u -p -r1.207 dwarf2read.c
--- gdb/dwarf2read.c 27 Dec 2006 22:38:57 -0000 1.207
+++ gdb/dwarf2read.c 29 Dec 2006 00:13:22 -0000
@@ -3699,7 +3699,6 @@ dwarf2_attach_fn_fields_to_type (struct
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 (struc
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_
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: gdb/eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.64
diff -u -p -r1.64 eval.c
--- gdb/eval.c 10 Oct 2006 03:17:53 -0000 1.64
+++ gdb/eval.c 29 Dec 2006 00:13:22 -0000
@@ -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 *e
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 *e
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 *e
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 *e
}
case STRUCTOP_MEMBER:
- arg1 = evaluate_subexp_for_address (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 */
-
- mem_offset = value_as_long (arg2);
- goto handle_pointer_to_member;
-
case STRUCTOP_MPTR:
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ 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 */
-
- mem_offset = value_as_long (arg2);
-
- 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;
- }
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"));
+ 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"));
+ }
+
+ 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);
+ }
+
+ 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);
+ 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;
+ }
+
+ 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"));
+ }
case BINOP_CONCAT:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -1469,13 +1451,11 @@ evaluate_subexp_standard (struct type *e
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 *e
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 *e
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 expr
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 expr
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 expr
(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: gdb/f-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/f-typeprint.c,v
retrieving revision 1.16
diff -u -p -r1.16 f-typeprint.c
--- gdb/f-typeprint.c 1 Mar 2006 01:37:26 -0000 1.16
+++ gdb/f-typeprint.c 29 Dec 2006 00:13:22 -0000
@@ -73,7 +73,6 @@ f_print_type (struct type *type, char *v
(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
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
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: gdb/gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.332
diff -u -p -r1.332 gdbarch.c
--- gdb/gdbarch.c 28 Nov 2006 22:10:26 -0000 1.332
+++ gdb/gdbarch.c 29 Dec 2006 00:13:22 -0000
@@ -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_
/* 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_gd
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_gd
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 (st
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: gdb/gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.288
diff -u -p -r1.288 gdbarch.h
--- gdb/gdbarch.h 28 Nov 2006 22:10:26 -0000 1.288
+++ gdb/gdbarch.h 29 Dec 2006 00:13:23 -0000
@@ -1383,6 +1383,19 @@ typedef const struct regset * (gdbarch_r
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: gdb/gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.368
diff -u -p -r1.368 gdbarch.sh
--- gdb/gdbarch.sh 28 Nov 2006 22:10:26 -0000 1.368
+++ gdb/gdbarch.sh 29 Dec 2006 00:13:23 -0000
@@ -663,6 +663,15 @@ F:=:CORE_ADDR:fetch_pointer_argument:str
# 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: gdb/gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.108
diff -u -p -r1.108 gdbtypes.c
--- gdb/gdbtypes.c 6 Dec 2006 20:15:19 -0000 1.108
+++ gdb/gdbtypes.c 29 Dec 2006 00:13:23 -0000
@@ -621,15 +621,30 @@ replace_type (struct type *ntype, struct
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,
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
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,
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: gdb/gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.65
diff -u -p -r1.65 gdbtypes.h
--- gdb/gdbtypes.h 1 Feb 2006 23:14:10 -0000 1.65
+++ gdb/gdbtypes.h 29 Dec 2006 00:13:23 -0000
@@ -142,8 +142,16 @@ 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 virtual). */
+ TYPE_CODE_METHODPTR,
+
+ /* Pointer-to-member type. This is the offset within a class to some
+ particular data member. */
+ TYPE_CODE_MEMBERPTR,
+
TYPE_CODE_REF, /* C++ Reference types */
TYPE_CODE_CHAR, /* *real* character type */
@@ -464,8 +472,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 +1229,16 @@ extern const char *address_space_int_to_
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: gdb/gnu-v3-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v
retrieving revision 1.29
diff -u -p -r1.29 gnu-v3-abi.c
--- gdb/gnu-v3-abi.c 17 Dec 2005 22:34:00 -0000 1.29
+++ gdb/gnu-v3-abi.c 29 Dec 2006 00:13:23 -0000
@@ -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;
-
- /* Some simple sanity checks. */
- if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
- error (_("Only classes can have virtual functions."));
-
- /* 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);
+ 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 ());
+}
- /* 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)));
+/* Return a function pointer for CONTAINER's VTABLE_INDEX'th virtual
+ function, of type FNTYPE. */
- 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 *typ
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: gdb/hpread.c
===================================================================
RCS file: /cvs/src/src/gdb/hpread.c,v
retrieving revision 1.58
diff -u -p -r1.58 hpread.c
--- gdb/hpread.c 17 Dec 2005 22:34:01 -0000 1.58
+++ gdb/hpread.c 29 Dec 2006 00:13:24 -0000
@@ -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,
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,
TYPE_FIELDS (functype),
TYPE_NFIELDS (functype),
0);
- return make_pointer_type (ptrmemtype, NULL);
+ return lookup_methodptr_type (ptrmemtype);
}
break;
Index: gdb/ia64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ia64-tdep.c,v
retrieving revision 1.141
diff -u -p -r1.141 ia64-tdep.c
--- gdb/ia64-tdep.c 28 Dec 2006 23:48:51 -0000 1.141
+++ gdb/ia64-tdep.c 29 Dec 2006 00:13:25 -0000
@@ -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
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 i
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: gdb/infcall.c
===================================================================
RCS file: /cvs/src/src/gdb/infcall.c,v
retrieving revision 1.76
diff -u -p -r1.76 infcall.c
--- gdb/infcall.c 10 Sep 2006 15:44:36 -0000 1.76
+++ gdb/infcall.c 29 Dec 2006 00:13:25 -0000
@@ -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, str
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: gdb/m2-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/m2-typeprint.c,v
retrieving revision 1.8
diff -u -p -r1.8 m2-typeprint.c
--- gdb/m2-typeprint.c 27 May 2006 17:39:28 -0000 1.8
+++ gdb/m2-typeprint.c 29 Dec 2006 00:13:25 -0000
@@ -112,10 +112,6 @@ m2_print_type (struct type *type, char *
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: gdb/m2-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/m2-valprint.c,v
retrieving revision 1.10
diff -u -p -r1.10 m2-valprint.c
--- gdb/m2-valprint.c 13 May 2006 15:46:38 -0000 1.10
+++ gdb/m2-valprint.c 29 Dec 2006 00:13:25 -0000
@@ -327,10 +327,6 @@ m2_val_print (struct type *type, const g
}
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: gdb/mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.399
diff -u -p -r1.399 mips-tdep.c
--- gdb/mips-tdep.c 28 Nov 2006 22:14:31 -0000 1.399
+++ gdb/mips-tdep.c 29 Dec 2006 00:13:25 -0000
@@ -5231,6 +5231,9 @@ mips_gdbarch_init (struct gdbarch_info i
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: gdb/p-lang.h
===================================================================
RCS file: /cvs/src/src/gdb/p-lang.h,v
retrieving revision 1.9
diff -u -p -r1.9 p-lang.h
--- gdb/p-lang.h 17 Dec 2005 22:34:01 -0000 1.9
+++ gdb/p-lang.h 29 Dec 2006 00:13:25 -0000
@@ -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 print
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: gdb/p-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/p-typeprint.c,v
retrieving revision 1.15
diff -u -p -r1.15 p-typeprint.c
--- gdb/p-typeprint.c 17 Dec 2005 22:34:01 -0000 1.15
+++ gdb/p-typeprint.c 29 Dec 2006 00:13:26 -0000
@@ -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
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
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 *typ
{
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: gdb/p-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/p-valprint.c,v
retrieving revision 1.44
diff -u -p -r1.44 p-valprint.c
--- gdb/p-valprint.c 5 Dec 2006 23:57:53 -0000 1.44
+++ gdb/p-valprint.c 29 Dec 2006 00:13:26 -0000
@@ -151,17 +151,6 @@ pascal_val_print (struct type *type, con
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, con
}
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 (s
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
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: gdb/stabsread.c
===================================================================
RCS file: /cvs/src/src/gdb/stabsread.c,v
retrieving revision 1.84
diff -u -p -r1.84 stabsread.c
--- gdb/stabsread.c 17 Jan 2006 22:30:29 -0000 1.84
+++ gdb/stabsread.c 29 Dec 2006 00:13:26 -0000
@@ -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: gdb/typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/typeprint.c,v
retrieving revision 1.26
diff -u -p -r1.26 typeprint.c
--- gdb/typeprint.c 18 Feb 2006 20:47:54 -0000 1.26
+++ gdb/typeprint.c 29 Dec 2006 00:13:26 -0000
@@ -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, LO
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: gdb/valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.165
diff -u -p -r1.165 valops.c
--- gdb/valops.c 9 Oct 2006 19:28:14 -0000 1.165
+++ gdb/valops.c 29 Dec 2006 00:13:26 -0000
@@ -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_fo
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,
}
/* 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 va
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 va
}
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, s
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 val
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 c
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 c
}
/* 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 *curtyp
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 *curtyp
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 t
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 t
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 t
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 t
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 t
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 *
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
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: gdb/value.c
===================================================================
RCS file: /cvs/src/src/gdb/value.c,v
retrieving revision 1.37
diff -u -p -r1.37 value.c
--- gdb/value.c 13 Dec 2006 22:36:48 -0000 1.37
+++ gdb/value.c 29 Dec 2006 00:13:27 -0000
@@ -1090,6 +1090,7 @@ unpack_long (struct type *type, const gd
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 gd
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: gdb/value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.93
diff -u -p -r1.93 value.h
--- gdb/value.h 22 Nov 2006 13:44:45 -0000 1.93
+++ gdb/value.h 29 Dec 2006 00:13:27 -0000
@@ -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 (s
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: gdb/varobj.c
===================================================================
RCS file: /cvs/src/src/gdb/varobj.c,v
retrieving revision 1.65
diff -u -p -r1.65 varobj.c
--- gdb/varobj.c 8 Dec 2006 22:06:04 -0000 1.65
+++ gdb/varobj.c 29 Dec 2006 00:13:27 -0000
@@ -2099,7 +2099,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;
Index: gdb/testsuite/gdb.cp/classes.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/classes.exp,v
retrieving revision 1.14
diff -u -p -r1.14 classes.exp
--- gdb/testsuite/gdb.cp/classes.exp 10 Aug 2006 05:27:20 -0000 1.14
+++ gdb/testsuite/gdb.cp/classes.exp 29 Dec 2006 00:13:27 -0000
@@ -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: gdb/testsuite/gdb.cp/inherit.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/inherit.exp,v
retrieving revision 1.9
diff -u -p -r1.9 inherit.exp
--- gdb/testsuite/gdb.cp/inherit.exp 10 Aug 2006 05:27:20 -0000 1.9
+++ gdb/testsuite/gdb.cp/inherit.exp 29 Dec 2006 00:13:27 -0000
@@ -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: gdb/testsuite/gdb.cp/member-ptr.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/member-ptr.cc,v
retrieving revision 1.3
diff -u -p -r1.3 member-ptr.cc
--- gdb/testsuite/gdb.cp/member-ptr.cc 11 Feb 2004 14:01:25 -0000 1.3
+++ gdb/testsuite/gdb.cp/member-ptr.cc 29 Dec 2006 00:13:27 -0000
@@ -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: gdb/testsuite/gdb.cp/member-ptr.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/member-ptr.exp,v
retrieving revision 1.5
diff -u -p -r1.5 member-ptr.exp
--- gdb/testsuite/gdb.cp/member-ptr.exp 10 Aug 2006 05:27:20 -0000 1.5
+++ gdb/testsuite/gdb.cp/member-ptr.exp 29 Dec 2006 00:13:27 -0000
@@ -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) ==
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)" $n
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: gdb/testsuite/gdb.cp/printmethod.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/printmethod.exp,v
retrieving revision 1.3
diff -u -p -r1.3 printmethod.exp
--- gdb/testsuite/gdb.cp/printmethod.exp 10 Aug 2006 05:27:20 -0000 1.3
+++ gdb/testsuite/gdb.cp/printmethod.exp 29 Dec 2006 00:13:27 -0000
@@ -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 const
# 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: gdb/testsuite/gdb.cp/virtfunc.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/virtfunc.exp,v
retrieving revision 1.12
diff -u -p -r1.12 virtfunc.exp
--- gdb/testsuite/gdb.cp/virtfunc.exp 10 Aug 2006 05:27:20 -0000 1.12
+++ gdb/testsuite/gdb.cp/virtfunc.exp 29 Dec 2006 00:13:27 -0000
@@ -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: gdb/NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.206
diff -u -p -r1.206 NEWS
--- gdb/NEWS 15 Dec 2006 23:57:35 -0000 1.206
+++ gdb/NEWS 29 Dec 2006 00:19:32 -0000
@@ -9,6 +9,8 @@ frequency signals (e.g. SIGALRM) via the
* 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
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2006-12-29 2:55 [c++] Pointer to member overhaul Daniel Jacobowitz
@ 2006-12-29 19:06 ` Jim Blandy
2006-12-31 22:40 ` Daniel Jacobowitz
2007-01-03 18:15 ` Daniel Jacobowitz
1 sibling, 1 reply; 9+ messages in thread
From: Jim Blandy @ 2006-12-29 19:06 UTC (permalink / raw)
To: gdb-patches
This is great! I think TYPE_CODE_MEMBERPTR and TYPE_CODE_METHODPTR
are definitely the right approach; data members and member functions
are not merely a different kind of pointer target in the sense that,
say, functions are.
Since the change is so large, I just looked at the changes to the
cp-abi.h and gdbtypes.h interfaces, which I'm assuming pretty much
drive the rest of the stuff.
The comments in cp-abi.h refer to 'cplus_method_ptr_to_target', which
isn't defined anywhere.
The sentence "CONTENTS is the bytes forming the pointer to method"
isn't grammatical.
What is the use of TYPE_CODE_METHOD now? Is it equivalent to
TYPE_CODE_FUNC, except that it expects a 'this' pointer?
Is the representation of a pointer to a data member always simply an
offset from the start of the member pointer's class? It would be nice
if the comment for TYPE_CODE_MEMBERPTR said this; similarly, it would
be nice if the comment for TYPE_CODE_METHODPTR explained that the
representation varies from one ABI to the next, and one should use the
cp-abi.h methods to work with them. Say the word, and I'll write
these for you.
Why are vtable_function_descriptors and vbit_in_delta gdbarch methods
instead of cp-abi.h methods?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2006-12-29 19:06 ` Jim Blandy
@ 2006-12-31 22:40 ` Daniel Jacobowitz
2006-12-31 22:55 ` Eli Zaretskii
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2006-12-31 22:40 UTC (permalink / raw)
To: Jim Blandy; +Cc: gdb-patches
Thanks for looking over it.
On Fri, Dec 29, 2006 at 11:06:21AM -0800, Jim Blandy wrote:
> The comments in cp-abi.h refer to 'cplus_method_ptr_to_target', which
> isn't defined anywhere.
Fixed, thanks.
> The sentence "CONTENTS is the bytes forming the pointer to method"
> isn't grammatical.
Actually I disagree. CONTENTS is a singular noun here, the pointer
whose name is "contents".
> What is the use of TYPE_CODE_METHOD now? Is it equivalent to
> TYPE_CODE_FUNC, except that it expects a 'this' pointer?
It's basically the same as TYPE_CODE_FUNC. I eliminated a number of
cases which treated them differently. dwarf2read uses the distinction
to figure out what's a member pointer, but it could check for
TYPE_CODE_FUNC too. There's some bits in infcall mostly dealing with
argument promotion. It looks like it would be possible to remove
TYPE_CODE_METHOD now - it wouldn't be hard, just require careful
attention to detail.
> Is the representation of a pointer to a data member always simply an
> offset from the start of the member pointer's class? It would be nice
> if the comment for TYPE_CODE_MEMBERPTR said this; similarly, it would
> be nice if the comment for TYPE_CODE_METHODPTR explained that the
> representation varies from one ABI to the next, and one should use the
> cp-abi.h methods to work with them. Say the word, and I'll write
> these for you.
The only supported representation for TYPE_CODE_MEMBERPTR is the GNU v3
one, which is an offset and -1 for NULL. It varies by compiler, but I
did not add support for any other representation, since the only thing
already present was aCC and that support is on its way out. I added
some words.
> Why are vtable_function_descriptors and vbit_in_delta gdbarch methods
> instead of cp-abi.h methods?
Because they don't depend on the ABI, they depend on the architecture.
Itanium sets vtable_function_descriptors but PowerPC64 doesn't. ARM
and MIPS set vbit_in_delta since they need the low bit (for Thumb /
MIPS16).
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2006-12-31 22:40 ` Daniel Jacobowitz
@ 2006-12-31 22:55 ` Eli Zaretskii
2006-12-31 23:49 ` Daniel Jacobowitz
0 siblings, 1 reply; 9+ messages in thread
From: Eli Zaretskii @ 2006-12-31 22:55 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: jimb, gdb-patches
> Date: Sun, 31 Dec 2006 17:40:43 -0500
> From: Daniel Jacobowitz <drow@false.org>
> Cc: gdb-patches@sourceware.org
>
> > The sentence "CONTENTS is the bytes forming the pointer to method"
> > isn't grammatical.
>
> Actually I disagree. CONTENTS is a singular noun here, the pointer
> whose name is "contents".
How about
"CONTENTS is the byte pattern representing the pointer to method."
A similar wording is used a few lines below the one being disputed.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2006-12-31 22:55 ` Eli Zaretskii
@ 2006-12-31 23:49 ` Daniel Jacobowitz
0 siblings, 0 replies; 9+ messages in thread
From: Daniel Jacobowitz @ 2006-12-31 23:49 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: jimb, gdb-patches
On Mon, Jan 01, 2007 at 12:55:33AM +0200, Eli Zaretskii wrote:
> > Date: Sun, 31 Dec 2006 17:40:43 -0500
> > From: Daniel Jacobowitz <drow@false.org>
> > Cc: gdb-patches@sourceware.org
> >
> > > The sentence "CONTENTS is the bytes forming the pointer to method"
> > > isn't grammatical.
> >
> > Actually I disagree. CONTENTS is a singular noun here, the pointer
> > whose name is "contents".
>
> How about
>
> "CONTENTS is the byte pattern representing the pointer to method."
>
> A similar wording is used a few lines below the one being disputed.
Works for me. Thank you.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2006-12-29 2:55 [c++] Pointer to member overhaul Daniel Jacobowitz
2006-12-29 19:06 ` Jim Blandy
@ 2007-01-03 18:15 ` Daniel Jacobowitz
2007-01-08 15:47 ` Ulrich Weigand
1 sibling, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2007-01-03 18:15 UTC (permalink / raw)
To: gdb-patches
On Thu, Dec 28, 2006 at 09:55:09PM -0500, Daniel Jacobowitz wrote:
> This patch is limited to C++ support and the surrounding value / type
> machinery. I suspect it's too big for anyone to review usefully, but
> in case anyone is willing to look at it, I will wait until 2007 to
> commit it. I'm confident that it is strictly an improvement.
I've committed it with Jim's corrections, as below.
A nice bonus: the change to gnuv3_get_virtual_fn fixes two Java tests
that weren't running before my December testsuite patch.
--
Daniel Jacobowitz
CodeSourcery
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-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().
---
gdb/Makefile.in | 14 -
gdb/NEWS | 2
gdb/ada-valprint.c | 3
gdb/arm-tdep.c | 3
gdb/c-lang.h | 7
gdb/c-typeprint.c | 120 ++++-------
gdb/c-valprint.c | 46 +---
gdb/cp-abi.c | 35 +++
gdb/cp-abi.h | 30 ++
gdb/cp-valprint.c | 203 ++++++------------
gdb/dwarf2read.c | 10
gdb/eval.c | 198 ++++++++----------
gdb/f-typeprint.c | 3
gdb/gdbarch.c | 46 ++++
gdb/gdbarch.h | 13 +
gdb/gdbarch.sh | 9
gdb/gdbtypes.c | 49 +++-
gdb/gdbtypes.h | 33 ++-
gdb/gnu-v3-abi.c | 377 +++++++++++++++++++++++++++++------
gdb/hpread.c | 8
gdb/ia64-tdep.c | 16 +
gdb/infcall.c | 5
gdb/m2-typeprint.c | 4
gdb/m2-valprint.c | 4
gdb/mips-tdep.c | 3
gdb/p-lang.h | 8
gdb/p-typeprint.c | 22 --
gdb/p-valprint.c | 164 ---------------
gdb/stabsread.c | 4
gdb/testsuite/gdb.cp/classes.exp | 9
gdb/testsuite/gdb.cp/inherit.exp | 36 ---
gdb/testsuite/gdb.cp/member-ptr.cc | 100 +++++++++
gdb/testsuite/gdb.cp/member-ptr.exp | 85 +++++--
gdb/testsuite/gdb.cp/printmethod.exp | 10
gdb/testsuite/gdb.cp/virtfunc.exp | 11 -
gdb/typeprint.c | 5
gdb/valops.c | 182 ++++++++++------
gdb/value.c | 5
gdb/value.h | 7
gdb/varobj.c | 1
40 files changed, 1082 insertions(+), 808 deletions(-)
Index: gdb/Makefile.in
===================================================================
--- gdb/Makefile.in.orig 2006-12-31 17:29:18.000000000 -0500
+++ gdb/Makefile.in 2006-12-31 17:32:24.000000000 -0500
@@ -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
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) $(g
$(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) $(inf
$(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: gdb/ada-valprint.c
===================================================================
--- gdb/ada-valprint.c.orig 2006-12-19 23:21:48.000000000 -0500
+++ gdb/ada-valprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -420,7 +420,8 @@ ada_print_scalar (struct type *type, LON
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: gdb/arm-tdep.c
===================================================================
--- gdb/arm-tdep.c.orig 2006-12-31 17:29:19.000000000 -0500
+++ gdb/arm-tdep.c 2006-12-31 17:32:24.000000000 -0500
@@ -2816,6 +2816,9 @@ arm_gdbarch_init (struct gdbarch_info in
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: gdb/c-lang.h
===================================================================
--- gdb/c-lang.h.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/c-lang.h 2006-12-31 17:32:24.000000000 -0500
@@ -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: gdb/c-typeprint.c
===================================================================
--- gdb/c-typeprint.c.orig 2006-12-19 23:21:48.000000000 -0500
+++ gdb/c-typeprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -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 *v
(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
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
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
}
-
+/* 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
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
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, st
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: gdb/c-valprint.c
===================================================================
--- gdb/c-valprint.c.orig 2006-12-19 23:21:48.000000000 -0500
+++ gdb/c-valprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -142,6 +142,21 @@ c_val_print (struct type *type, const gd
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 gd
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 gd
}
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 gd
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 gd
}
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: gdb/cp-abi.c
===================================================================
--- gdb/cp-abi.c.orig 2006-12-19 23:21:48.000000000 -0500
+++ gdb/cp-abi.c 2006-12-31 17:32:24.000000000 -0500
@@ -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 *f
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: gdb/cp-abi.h
===================================================================
--- gdb/cp-abi.h.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/cp-abi.h 2006-12-31 18:49:18.000000000 -0500
@@ -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 (str
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: gdb/cp-valprint.c
===================================================================
--- gdb/cp-valprint.c.orig 2006-12-31 17:29:21.000000000 -0500
+++ gdb/cp-valprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -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
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);
-
- /* @@ Make VAL into bit offset */
+ unsigned int fieldno;
- /* 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! */
+ LONGEST val = unpack_long (builtin_type_long, valaddr);
- /* Note: HP cfront uses a constant bias of 1; if we support this
- compiler ever, we will have to adjust the computation below */
+ /* 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. */
- 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 *v
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: gdb/dwarf2read.c
===================================================================
--- gdb/dwarf2read.c.orig 2006-12-31 17:29:22.000000000 -0500
+++ gdb/dwarf2read.c 2006-12-31 17:32:24.000000000 -0500
@@ -3699,7 +3699,6 @@ dwarf2_attach_fn_fields_to_type (struct
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 (struc
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_
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: gdb/eval.c
===================================================================
--- gdb/eval.c.orig 2006-12-31 17:29:22.000000000 -0500
+++ gdb/eval.c 2006-12-31 17:32:24.000000000 -0500
@@ -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 *e
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 *e
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 *e
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 *e
}
case STRUCTOP_MEMBER:
- arg1 = evaluate_subexp_for_address (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 */
-
- mem_offset = value_as_long (arg2);
- goto handle_pointer_to_member;
-
case STRUCTOP_MPTR:
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ 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 */
-
- mem_offset = value_as_long (arg2);
-
- 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;
- }
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"));
+ 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"));
+ }
+
+ 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);
+ }
+
+ 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);
+ 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;
+ }
+
+ 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"));
+ }
case BINOP_CONCAT:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -1469,13 +1451,11 @@ evaluate_subexp_standard (struct type *e
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 *e
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 *e
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 expr
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 expr
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 expr
(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: gdb/f-typeprint.c
===================================================================
--- gdb/f-typeprint.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/f-typeprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -73,7 +73,6 @@ f_print_type (struct type *type, char *v
(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
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
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: gdb/gdbarch.c
===================================================================
--- gdb/gdbarch.c.orig 2006-12-31 17:29:23.000000000 -0500
+++ gdb/gdbarch.c 2006-12-31 17:32:24.000000000 -0500
@@ -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_
/* 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_gd
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_gd
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 (st
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: gdb/gdbarch.h
===================================================================
--- gdb/gdbarch.h.orig 2006-12-31 17:29:23.000000000 -0500
+++ gdb/gdbarch.h 2006-12-31 17:32:24.000000000 -0500
@@ -1383,6 +1383,19 @@ typedef const struct regset * (gdbarch_r
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: gdb/gdbarch.sh
===================================================================
--- gdb/gdbarch.sh.orig 2006-12-31 17:29:24.000000000 -0500
+++ gdb/gdbarch.sh 2006-12-31 17:32:24.000000000 -0500
@@ -663,6 +663,15 @@ F:=:CORE_ADDR:fetch_pointer_argument:str
# 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: gdb/gdbtypes.c
===================================================================
--- gdb/gdbtypes.c.orig 2006-12-31 17:29:24.000000000 -0500
+++ gdb/gdbtypes.c 2006-12-31 17:32:24.000000000 -0500
@@ -621,15 +621,30 @@ replace_type (struct type *ntype, struct
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,
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
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,
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: gdb/gdbtypes.h
===================================================================
--- gdb/gdbtypes.h.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/gdbtypes.h 2006-12-31 17:39:44.000000000 -0500
@@ -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_
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: gdb/gnu-v3-abi.c
===================================================================
--- gdb/gnu-v3-abi.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/gnu-v3-abi.c 2006-12-31 17:32:24.000000000 -0500
@@ -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;
-
- /* Some simple sanity checks. */
- if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
- error (_("Only classes can have virtual functions."));
-
- /* 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);
+ 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 ());
+}
- /* 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)));
+/* Return a function pointer for CONTAINER's VTABLE_INDEX'th virtual
+ function, of type FNTYPE. */
- 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 *typ
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: gdb/hpread.c
===================================================================
--- gdb/hpread.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/hpread.c 2006-12-31 17:32:24.000000000 -0500
@@ -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,
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,
TYPE_FIELDS (functype),
TYPE_NFIELDS (functype),
0);
- return make_pointer_type (ptrmemtype, NULL);
+ return lookup_methodptr_type (ptrmemtype);
}
break;
Index: gdb/ia64-tdep.c
===================================================================
--- gdb/ia64-tdep.c.orig 2006-12-31 17:29:24.000000000 -0500
+++ gdb/ia64-tdep.c 2006-12-31 17:32:24.000000000 -0500
@@ -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
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 i
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: gdb/infcall.c
===================================================================
--- gdb/infcall.c.orig 2006-12-31 17:29:24.000000000 -0500
+++ gdb/infcall.c 2006-12-31 17:32:24.000000000 -0500
@@ -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, str
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: gdb/m2-typeprint.c
===================================================================
--- gdb/m2-typeprint.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/m2-typeprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -112,10 +112,6 @@ m2_print_type (struct type *type, char *
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: gdb/m2-valprint.c
===================================================================
--- gdb/m2-valprint.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/m2-valprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -327,10 +327,6 @@ m2_val_print (struct type *type, const g
}
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: gdb/mips-tdep.c
===================================================================
--- gdb/mips-tdep.c.orig 2006-12-31 17:29:26.000000000 -0500
+++ gdb/mips-tdep.c 2006-12-31 17:32:24.000000000 -0500
@@ -5231,6 +5231,9 @@ mips_gdbarch_init (struct gdbarch_info i
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: gdb/p-lang.h
===================================================================
--- gdb/p-lang.h.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/p-lang.h 2006-12-31 17:32:24.000000000 -0500
@@ -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 print
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: gdb/p-typeprint.c
===================================================================
--- gdb/p-typeprint.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/p-typeprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -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
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
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 *typ
{
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: gdb/p-valprint.c
===================================================================
--- gdb/p-valprint.c.orig 2006-12-31 17:29:26.000000000 -0500
+++ gdb/p-valprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -151,17 +151,6 @@ pascal_val_print (struct type *type, con
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, con
}
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 (s
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
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: gdb/stabsread.c
===================================================================
--- gdb/stabsread.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/stabsread.c 2006-12-31 17:32:24.000000000 -0500
@@ -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: gdb/typeprint.c
===================================================================
--- gdb/typeprint.c.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/typeprint.c 2006-12-31 17:32:24.000000000 -0500
@@ -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, LO
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: gdb/valops.c
===================================================================
--- gdb/valops.c.orig 2006-12-31 17:29:29.000000000 -0500
+++ gdb/valops.c 2006-12-31 17:32:24.000000000 -0500
@@ -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_fo
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,
}
/* 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 va
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 va
}
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, s
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 val
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 c
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 c
}
/* 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 *curtyp
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 *curtyp
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 t
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 t
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 t
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 t
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 t
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 *
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
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: gdb/value.c
===================================================================
--- gdb/value.c.orig 2006-12-31 17:29:30.000000000 -0500
+++ gdb/value.c 2006-12-31 17:32:24.000000000 -0500
@@ -1090,6 +1090,7 @@ unpack_long (struct type *type, const gd
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 gd
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: gdb/value.h
===================================================================
--- gdb/value.h.orig 2006-12-31 17:29:30.000000000 -0500
+++ gdb/value.h 2006-12-31 17:32:24.000000000 -0500
@@ -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 (s
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: gdb/varobj.c
===================================================================
--- gdb/varobj.c.orig 2006-12-31 17:29:30.000000000 -0500
+++ gdb/varobj.c 2006-12-31 17:32:24.000000000 -0500
@@ -2099,7 +2099,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;
Index: gdb/testsuite/gdb.cp/classes.exp
===================================================================
--- gdb/testsuite/gdb.cp/classes.exp.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/testsuite/gdb.cp/classes.exp 2006-12-31 17:32:24.000000000 -0500
@@ -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: gdb/testsuite/gdb.cp/inherit.exp
===================================================================
--- gdb/testsuite/gdb.cp/inherit.exp.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/testsuite/gdb.cp/inherit.exp 2006-12-31 17:32:24.000000000 -0500
@@ -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: gdb/testsuite/gdb.cp/member-ptr.cc
===================================================================
--- gdb/testsuite/gdb.cp/member-ptr.cc.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/testsuite/gdb.cp/member-ptr.cc 2006-12-31 17:32:24.000000000 -0500
@@ -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: gdb/testsuite/gdb.cp/member-ptr.exp
===================================================================
--- gdb/testsuite/gdb.cp/member-ptr.exp.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/testsuite/gdb.cp/member-ptr.exp 2006-12-31 17:32:24.000000000 -0500
@@ -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) ==
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)" $n
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: gdb/testsuite/gdb.cp/printmethod.exp
===================================================================
--- gdb/testsuite/gdb.cp/printmethod.exp.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/testsuite/gdb.cp/printmethod.exp 2006-12-31 17:32:24.000000000 -0500
@@ -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 const
# 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: gdb/testsuite/gdb.cp/virtfunc.exp
===================================================================
--- gdb/testsuite/gdb.cp/virtfunc.exp.orig 2006-12-19 23:21:49.000000000 -0500
+++ gdb/testsuite/gdb.cp/virtfunc.exp 2006-12-31 17:32:24.000000000 -0500
@@ -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: gdb/NEWS
===================================================================
--- gdb/NEWS.orig 2006-12-31 17:29:18.000000000 -0500
+++ gdb/NEWS 2006-12-31 17:32:24.000000000 -0500
@@ -9,6 +9,8 @@ frequency signals (e.g. SIGALRM) via the
* 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
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2007-01-03 18:15 ` Daniel Jacobowitz
@ 2007-01-08 15:47 ` Ulrich Weigand
2007-01-08 15:52 ` Daniel Jacobowitz
0 siblings, 1 reply; 9+ messages in thread
From: Ulrich Weigand @ 2007-01-08 15:47 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
Dan Jacobowitz wrote:
> I've committed it with Jim's corrections, as below.
>
> A nice bonus: the change to gnuv3_get_virtual_fn fixes two Java tests
> that weren't running before my December testsuite patch.
This also fixes three C++ testcases on s390x-ibm-linux
that have been failing forever there!
Many thanks,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2007-01-08 15:47 ` Ulrich Weigand
@ 2007-01-08 15:52 ` Daniel Jacobowitz
2007-01-08 16:02 ` Ulrich Weigand
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2007-01-08 15:52 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches
On Mon, Jan 08, 2007 at 04:47:40PM +0100, Ulrich Weigand wrote:
> Dan Jacobowitz wrote:
>
> > I've committed it with Jim's corrections, as below.
> >
> > A nice bonus: the change to gnuv3_get_virtual_fn fixes two Java tests
> > that weren't running before my December testsuite patch.
>
> This also fixes three C++ testcases on s390x-ibm-linux
> that have been failing forever there!
Interesting - which ones? I didn't expect s390x to be affected
but it might have to do with the old definition of the virtual
function pointer check, which hardcoded the number "0x80000000".
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [c++] Pointer to member overhaul
2007-01-08 15:52 ` Daniel Jacobowitz
@ 2007-01-08 16:02 ` Ulrich Weigand
0 siblings, 0 replies; 9+ messages in thread
From: Ulrich Weigand @ 2007-01-08 16:02 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
Dan Jacobowitz wrote:
> Interesting - which ones?
FAIL: gdb.cp/classes.exp: print Bar::z
FAIL: gdb.cp/printmethod.exp: print virtual method.
FAIL: gdb.cp/printmethod.exp: print nonvirtual method.
> I didn't expect s390x to be affected
> but it might have to do with the old definition of the virtual
> function pointer check, which hardcoded the number "0x80000000".
Exactly. The default load address for the main executable on
s390x happens to be 0x80000000, which caused confusion with
the virtual function pointer encoding.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2007-01-08 16:02 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-29 2:55 [c++] Pointer to member overhaul Daniel Jacobowitz
2006-12-29 19:06 ` Jim Blandy
2006-12-31 22:40 ` Daniel Jacobowitz
2006-12-31 22:55 ` Eli Zaretskii
2006-12-31 23:49 ` Daniel Jacobowitz
2007-01-03 18:15 ` Daniel Jacobowitz
2007-01-08 15:47 ` Ulrich Weigand
2007-01-08 15:52 ` Daniel Jacobowitz
2007-01-08 16:02 ` Ulrich Weigand
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox