* 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.

	* 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().
This commit is contained in:
Daniel Jacobowitz 2007-01-03 18:05:45 +00:00
parent 9d6063994f
commit 0d5de0100f
42 changed files with 1192 additions and 810 deletions

View file

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

View file

@ -1527,13 +1527,6 @@ main.o: main.c
$(CC) -c $(INTERNAL_CFLAGS) $(TARGET_SYSTEM_ROOT_DEFINE) \
-DBINDIR=\"$(bindir)\" $(srcdir)/main.c
# FIXME: cagney/2004-09-16: "gnu-v3-abi.c", with a GCC 3.4 compiler,
# gets a "assignment from incompatible pointer type" warning. The
# return types - "enum gnu_v3_dtor_kinds" vs "enum ctor_kinds" -
# conflict.
gnu-v3-abi.o: $(srcdir)/gnu-v3-abi.c
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(srcdir)/gnu-v3-abi.c
# FIXME: cagney/2003-08-10: "monitor.c" gets -Wformat-nonliteral
# errors. It turns out that that is the least of monitor.c's
# problems. The function print_vsprintf appears to be using
@ -1973,7 +1966,7 @@ environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
$(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
$(parser_defs_h) $(cp_support_h)
$(parser_defs_h) $(cp_support_h) $(gdb_assert_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
@ -2052,7 +2045,7 @@ gnu-v2-abi.o: gnu-v2-abi.c $(defs_h) $(gdb_string_h) $(symtab_h) \
$(gdbtypes_h) $(value_h) $(demangle_h) $(cp_abi_h) $(cp_support_h) \
$(gnu_v2_abi_h)
gnu-v3-abi.o: gnu-v3-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(cp_support_h) \
$(demangle_h) $(gdb_assert_h) $(gdb_string_h)
$(demangle_h) $(valprint_h) $(gdb_assert_h) $(gdb_string_h)
go32-nat.o: go32-nat.c $(defs_h) $(inferior_h) $(gdb_wait_h) $(gdbcore_h) \
$(command_h) $(gdbcmd_h) $(floatformat_h) $(buildsym_h) \
$(i387_tdep_h) $(i386_tdep_h) $(value_h) $(regcache_h) \
@ -2168,7 +2161,8 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(frame_h) $(frame_base_h) $(frame_unwind_h) $(doublest_h) \
$(value_h) $(gdb_assert_h) $(objfiles_h) $(elf_common_h) \
$(elf_bfd_h) $(dis_asm_h) $(infcall_h) $(osabi_h) $(ia64_tdep_h) \
$(elf_ia64_h) $(libunwind_frame_h) $(libunwind_ia64_h)
$(elf_ia64_h) $(libunwind_frame_h) $(libunwind_ia64_h) \
$(cp_abi_h)
infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
$(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
$(objfiles_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h) \

View file

@ -9,6 +9,8 @@ frequency signals (e.g. SIGALRM) via the QPassSignals packet.
* GDB for MIPS targets now autodetects whether a remote target provides
32-bit or 64-bit register values.
* Support for C++ member pointers has been improved.
* New commands
set mem inaccessible-by-default

View file

@ -420,7 +420,8 @@ ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream)
case TYPE_CODE_SET:
case TYPE_CODE_STRING:
case TYPE_CODE_ERROR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_MEMBERPTR:
case TYPE_CODE_METHODPTR:
case TYPE_CODE_METHOD:
case TYPE_CODE_REF:
warning (_("internal error: unhandled type in ada_print_scalar"));

View file

@ -2816,6 +2816,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_coff_make_msymbol_special (gdbarch,
arm_coff_make_msymbol_special);
/* Virtual tables. */
set_gdbarch_vbit_in_delta (gdbarch, 1);
/* Hook in the ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);

View file

@ -1,7 +1,7 @@
/* C language support definitions for GDB, the GNU debugger.
Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2005 Free
Software Foundation, Inc.
Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -79,9 +79,6 @@ extern int static_field_print;
extern void cp_print_class_member (const gdb_byte *, struct type *,
struct ui_file *, char *);
extern void cp_print_class_method (const gdb_byte *, struct type *,
struct ui_file *);
extern void cp_print_value_fields (struct type *, struct type *,
const gdb_byte *, int, CORE_ADDR,
struct ui_file *, int,

View file

@ -1,6 +1,6 @@
/* Support for printing C and C++ types for GDB, the GNU debugger.
Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
1999, 2000, 2001, 2002, 2003
1999, 2000, 2001, 2002, 2003, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -80,7 +80,8 @@ c_print_type (struct type *type, char *varstring, struct ui_file *stream,
(code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
|| code == TYPE_CODE_METHOD
|| code == TYPE_CODE_ARRAY
|| code == TYPE_CODE_MEMBER
|| code == TYPE_CODE_MEMBERPTR
|| code == TYPE_CODE_METHODPTR
|| code == TYPE_CODE_REF)))
fputs_filtered (" ", stream);
need_post_space = (varstring != NULL && strcmp (varstring, "") != 0);
@ -218,29 +219,25 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
c_type_print_modifier (type, stream, 1, need_post_space);
break;
case TYPE_CODE_MEMBER:
if (passed_a_ptr)
fprintf_filtered (stream, "(");
case TYPE_CODE_MEMBERPTR:
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
fprintf_filtered (stream, " ");
name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
if (name)
fputs_filtered (name, stream);
else
c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
fprintf_filtered (stream, "::");
fprintf_filtered (stream, "::*");
break;
case TYPE_CODE_METHOD:
if (passed_a_ptr)
fprintf_filtered (stream, "(");
case TYPE_CODE_METHODPTR:
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
if (passed_a_ptr)
{
fprintf_filtered (stream, " ");
c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
fprintf_filtered (stream, "::");
}
fprintf_filtered (stream, "(");
name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
if (name)
fputs_filtered (name, stream);
else
c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
fprintf_filtered (stream, "::*");
break;
case TYPE_CODE_REF:
@ -249,6 +246,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
c_type_print_modifier (type, stream, 1, need_post_space);
break;
case TYPE_CODE_METHOD:
case TYPE_CODE_FUNC:
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
if (passed_a_ptr)
@ -337,42 +335,49 @@ c_type_print_modifier (struct type *type, struct ui_file *stream,
}
/* Print out the arguments of TYPE, which should have TYPE_CODE_METHOD
or TYPE_CODE_FUNC, to STREAM. Artificial arguments, such as "this"
in non-static methods, are displayed. */
static void
c_type_print_args (struct type *type, struct ui_file *stream)
{
int i;
int i, len;
struct field *args;
int printed_any = 0;
fprintf_filtered (stream, "(");
args = TYPE_FIELDS (type);
if (args != NULL)
len = TYPE_NFIELDS (type);
for (i = 0; i < TYPE_NFIELDS (type); i++)
{
int i;
/* FIXME drow/2002-05-31: Always skips the first argument,
should we be checking for static members? */
for (i = 1; i < TYPE_NFIELDS (type); i++)
if (printed_any)
{
c_print_type (args[i].type, "", stream, -1, 0);
if (i != TYPE_NFIELDS (type))
{
fprintf_filtered (stream, ",");
wrap_here (" ");
}
fprintf_filtered (stream, ", ");
wrap_here (" ");
}
if (TYPE_VARARGS (type))
fprintf_filtered (stream, "...");
else if (i == 1
&& (current_language->la_language == language_cplus))
fprintf_filtered (stream, "void");
c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
printed_any = 1;
}
else if (current_language->la_language == language_cplus)
if (printed_any && TYPE_VARARGS (type))
{
fprintf_filtered (stream, "void");
/* Print out a trailing ellipsis for varargs functions. Ignore
TYPE_VARARGS if the function has no named arguments; that
represents unprototyped (K&R style) C functions. */
if (printed_any && TYPE_VARARGS (type))
{
fprintf_filtered (stream, ", ");
wrap_here (" ");
fprintf_filtered (stream, "...");
}
}
else if (!printed_any
&& (TYPE_PROTOTYPED (type)
|| current_language->la_language == language_cplus))
fprintf_filtered (stream, "void");
fprintf_filtered (stream, ")");
}
@ -548,22 +553,15 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
0, 0);
break;
case TYPE_CODE_MEMBER:
if (passed_a_ptr)
fprintf_filtered (stream, ")");
case TYPE_CODE_MEMBERPTR:
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
0, 0);
break;
case TYPE_CODE_METHOD:
if (passed_a_ptr)
fprintf_filtered (stream, ")");
case TYPE_CODE_METHODPTR:
fprintf_filtered (stream, ")");
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
0, 0);
if (passed_a_ptr)
{
c_type_print_args (type, stream);
}
break;
case TYPE_CODE_PTR:
@ -572,31 +570,12 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
1, 0);
break;
case TYPE_CODE_METHOD:
case TYPE_CODE_FUNC:
if (passed_a_ptr)
fprintf_filtered (stream, ")");
if (!demangled_args)
{
int i, len = TYPE_NFIELDS (type);
fprintf_filtered (stream, "(");
if (len == 0
&& (TYPE_PROTOTYPED (type)
|| current_language->la_language == language_cplus))
{
fprintf_filtered (stream, "void");
}
else
for (i = 0; i < len; i++)
{
if (i > 0)
{
fputs_filtered (", ", stream);
wrap_here (" ");
}
c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
}
fprintf_filtered (stream, ")");
}
c_type_print_args (type, stream);
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
passed_a_ptr, 0);
break;
@ -696,10 +675,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
case TYPE_CODE_TYPEDEF:
case TYPE_CODE_ARRAY:
case TYPE_CODE_PTR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_MEMBERPTR:
case TYPE_CODE_REF:
case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD:
case TYPE_CODE_METHODPTR:
c_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
break;

View file

@ -142,6 +142,21 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
addr = address;
goto print_unpacked_pointer;
case TYPE_CODE_MEMBERPTR:
if (format)
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
break;
}
cp_print_class_member (valaddr + embedded_offset,
TYPE_DOMAIN_TYPE (type),
stream, "&");
break;
case TYPE_CODE_METHODPTR:
cplus_print_method_ptr (valaddr + embedded_offset, type, stream);
break;
case TYPE_CODE_PTR:
if (format && format != 's')
{
@ -159,17 +174,6 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
break;
}
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
{
cp_print_class_method (valaddr + embedded_offset, type, stream);
}
else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
{
cp_print_class_member (valaddr + embedded_offset,
TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
stream, "&");
}
else
{
addr = unpack_pointer (type, valaddr + embedded_offset);
print_unpacked_pointer:
@ -250,19 +254,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
}
break;
case TYPE_CODE_MEMBER:
error (_("not implemented: member type in c_val_print"));
break;
case TYPE_CODE_REF:
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
{
cp_print_class_member (valaddr + embedded_offset,
TYPE_DOMAIN_TYPE (elttype),
stream, "");
break;
}
if (addressprint)
{
CORE_ADDR addr
@ -351,6 +344,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
break;
case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD:
if (format)
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
@ -442,14 +436,6 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
}
break;
case TYPE_CODE_METHOD:
{
struct value *v = value_at (type, address);
cp_print_class_method (value_contents (value_addr (v)),
lookup_pointer_type (type), stream);
break;
}
case TYPE_CODE_VOID:
fprintf_filtered (stream, "void");
break;

View file

@ -1,6 +1,6 @@
/* Generic code for supporting multiple C++ ABI's
Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@ -95,6 +95,39 @@ value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
return (*current_cp_abi.rtti_type) (v, full, top, using_enc);
}
void
cplus_print_method_ptr (const gdb_byte *contents, struct type *type,
struct ui_file *stream)
{
if (current_cp_abi.print_method_ptr == NULL)
error (_("GDB does not support pointers to methods on this target"));
(*current_cp_abi.print_method_ptr) (contents, type, stream);
}
int
cplus_method_ptr_size (void)
{
if (current_cp_abi.method_ptr_size == NULL)
error (_("GDB does not support pointers to methods on this target"));
return (*current_cp_abi.method_ptr_size) ();
}
void
cplus_make_method_ptr (gdb_byte *contents, CORE_ADDR value, int is_virtual)
{
if (current_cp_abi.make_method_ptr == NULL)
error (_("GDB does not support pointers to methods on this target"));
(*current_cp_abi.make_method_ptr) (contents, value, is_virtual);
}
struct value *
cplus_method_ptr_to_value (struct value **this_p, struct value *method_ptr)
{
if (current_cp_abi.method_ptr_to_value == NULL)
error (_("GDB does not support pointers to methods on this target"));
return (*current_cp_abi.method_ptr_to_value) (this_p, method_ptr);
}
/* Set the current C++ ABI to SHORT_NAME. */
static int

View file

@ -3,7 +3,7 @@
Contributed by Daniel Berlin <dberlin@redhat.com>
Copyright (C) 2001, 2005 Free Software Foundation, Inc.
Copyright (C) 2001, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@ -30,6 +30,7 @@
struct fn_field;
struct type;
struct value;
struct ui_file;
/* The functions here that attempt to determine what sort of thing a
mangled name refers to may well be revised in the future. It would
@ -147,6 +148,28 @@ extern struct type *value_rtti_type (struct value *value,
extern int baseclass_offset (struct type *type, int index,
const bfd_byte *valaddr, CORE_ADDR address);
/* Describe the target of a pointer to method. CONTENTS is the byte
pattern representing the pointer to method. TYPE is the pointer to
method type. STREAM is the stream to print it to. */
void cplus_print_method_ptr (const gdb_byte *contents, struct type *type,
struct ui_file *stream);
/* Return the size of a pointer to member function for the current
architecture. */
int cplus_method_ptr_size (void);
/* Return the method which should be called by applying METHOD_PTR
to *THIS_P, and adjust *THIS_P if necessary. */
struct value *cplus_method_ptr_to_value (struct value **this_p,
struct value *method_ptr);
/* Create the byte pattern in CONTENTS representing a pointer to
member function at ADDRESS (if IS_VIRTUAL is 0) or with virtual
table offset ADDRESS (if IS_VIRTUAL is 1). This is the opposite
of cplus_method_ptr_to_value. */
void cplus_make_method_ptr (gdb_byte *CONTENTS, CORE_ADDR address,
int is_virtual);
struct cp_abi_ops
{
const char *shortname;
@ -164,6 +187,11 @@ struct cp_abi_ops
int *using_enc);
int (*baseclass_offset) (struct type *type, int index,
const bfd_byte *valaddr, CORE_ADDR address);
void (*print_method_ptr) (const gdb_byte *contents, struct type *type,
struct ui_file *stream);
int (*method_ptr_size) (void);
void (*make_method_ptr) (gdb_byte *, CORE_ADDR, int);
struct value * (*method_ptr_to_value) (struct value **, struct value *);
};

View file

@ -1,7 +1,8 @@
/* Support for printing C++ values for GDB, the GNU debugger.
Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
1997, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
1997, 2000, 2001, 2002, 2003, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -92,104 +93,6 @@ static void cp_print_hpacc_virtual_table_entries (struct type *, int *,
enum val_prettyprint);
void
cp_print_class_method (const gdb_byte *valaddr,
struct type *type,
struct ui_file *stream)
{
struct type *domain;
struct fn_field *f = NULL;
int j = 0;
int len2;
int offset;
char *kind = "";
CORE_ADDR addr;
struct symbol *sym;
unsigned len;
unsigned int i;
struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
domain = TYPE_DOMAIN_TYPE (target_type);
if (domain == (struct type *) NULL)
{
fprintf_filtered (stream, "<unknown>");
return;
}
addr = unpack_pointer (type, valaddr);
if (METHOD_PTR_IS_VIRTUAL (addr))
{
offset = METHOD_PTR_TO_VOFFSET (addr);
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
f = TYPE_FN_FIELDLIST1 (domain, i);
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
check_stub_method_group (domain, i);
for (j = 0; j < len2; j++)
{
if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
{
kind = "virtual ";
goto common;
}
}
}
}
else
{
sym = find_pc_function (addr);
if (sym == 0)
{
/* 1997-08-01 Currently unsupported with HP aCC */
if (deprecated_hp_som_som_object_present)
{
fputs_filtered ("?? <not supported with HP aCC>", stream);
return;
}
error (_("invalid pointer to member function"));
}
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
f = TYPE_FN_FIELDLIST1 (domain, i);
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
check_stub_method_group (domain, i);
for (j = 0; j < len2; j++)
{
if (strcmp (DEPRECATED_SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))
== 0)
goto common;
}
}
}
common:
if (i < len)
{
char *demangled_name;
fprintf_filtered (stream, "&");
fputs_filtered (kind, stream);
demangled_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (f, j),
DMGL_ANSI | DMGL_PARAMS);
if (demangled_name == NULL)
fprintf_filtered (stream, "<badly mangled name %s>",
TYPE_FN_FIELD_PHYSNAME (f, j));
else
{
fputs_filtered (demangled_name, stream);
xfree (demangled_name);
}
}
else
{
fprintf_filtered (stream, "(");
type_print (type, "", stream, -1);
fprintf_filtered (stream, ") %d", (int) addr >> 3);
}
}
/* GCC versions after 2.4.5 use this. */
const char vtbl_ptr_name[] = "__vtbl_ptr_type";
@ -703,48 +606,82 @@ cp_print_static_field (struct type *type,
stream, format, 0, recurse, pretty);
}
/* Find the field in *DOMAIN, or its non-virtual base classes, with bit offset
OFFSET. Set *DOMAIN to the containing type and *FIELDNO to the containing
field number. If OFFSET is not exactly at the start of some field, set
*DOMAIN to NULL. */
void
cp_find_class_member (struct type **domain_p, int *fieldno,
LONGEST offset)
{
struct type *domain;
unsigned int i;
unsigned len;
*domain_p = check_typedef (*domain_p);
domain = *domain_p;
len = TYPE_NFIELDS (domain);
for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
{
LONGEST bitpos = TYPE_FIELD_BITPOS (domain, i);
QUIT;
if (offset == bitpos)
{
*fieldno = i;
return;
}
}
for (i = 0; i < TYPE_N_BASECLASSES (domain); i++)
{
LONGEST bitpos = TYPE_FIELD_BITPOS (domain, i);
LONGEST bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (domain, i));
if (offset >= bitpos && offset < bitpos + bitsize)
{
*domain_p = TYPE_FIELD_TYPE (domain, i);
cp_find_class_member (domain_p, fieldno, offset - bitpos);
return;
}
}
*domain_p = NULL;
}
void
cp_print_class_member (const gdb_byte *valaddr, struct type *domain,
struct ui_file *stream, char *prefix)
{
/* VAL is a byte offset into the structure type DOMAIN.
Find the name of the field for that offset and
print it. */
int extra = 0;
int bits = 0;
unsigned int i;
unsigned len = TYPE_NFIELDS (domain);
unsigned int fieldno;
/* @@ Make VAL into bit offset */
LONGEST val = unpack_long (builtin_type_long, valaddr);
/* Note: HP aCC generates offsets that are the real byte offsets added
to a constant bias 0x20000000 (1 << 29). This constant bias gets
shifted out in the code below -- joyous happenstance! */
/* Pointers to data members are usually byte offsets into an object.
Because a data member can have offset zero, and a NULL pointer to
member must be distinct from any valid non-NULL pointer to
member, either the value is biased or the NULL value has a
special representation; both are permitted by ISO C++. HP aCC
used a bias of 0x20000000; HP cfront used a bias of 1; g++ 3.x
and other compilers which use the Itanium ABI use -1 as the NULL
value. GDB only supports that last form; to add support for
another form, make this into a cp-abi hook. */
/* Note: HP cfront uses a constant bias of 1; if we support this
compiler ever, we will have to adjust the computation below */
LONGEST val = unpack_long (builtin_type_int, valaddr) << 3;
for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
if (val == -1)
{
int bitpos = TYPE_FIELD_BITPOS (domain, i);
QUIT;
if (val == bitpos)
break;
if (val < bitpos && i != 0)
{
/* Somehow pointing into a field. */
i -= 1;
extra = (val - TYPE_FIELD_BITPOS (domain, i));
if (extra & 0x7)
bits = 1;
else
extra >>= 3;
break;
}
fprintf_filtered (stream, "NULL");
return;
}
if (i < len)
cp_find_class_member (&domain, &fieldno, val << 3);
if (domain != NULL)
{
char *name;
fputs_filtered (prefix, stream);
@ -754,14 +691,10 @@ cp_print_class_member (const gdb_byte *valaddr, struct type *domain,
else
c_type_print_base (domain, stream, 0, 0);
fprintf_filtered (stream, "::");
fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
if (extra)
fprintf_filtered (stream, " + %d bytes", extra);
if (bits)
fprintf_filtered (stream, " (offset in bits)");
fputs_filtered (TYPE_FIELD_NAME (domain, fieldno), stream);
}
else
fprintf_filtered (stream, "%ld", (long) (val >> 3));
fprintf_filtered (stream, "%ld", (long) val);
}

View file

@ -3699,7 +3699,6 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
/* Returns non-zero if NAME is the name of a vtable member in CU's
language, zero otherwise. */
static int
@ -3779,7 +3778,7 @@ quirk_gcc_member_function_pointer (struct die_info *die, struct dwarf2_cu *cu)
smash_to_method_type (type, domain_type, TYPE_TARGET_TYPE (pfn_type),
TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type),
TYPE_VARARGS (pfn_type));
type = lookup_pointer_type (type);
type = lookup_methodptr_type (type);
set_die_type (die, type, cu);
return 1;
@ -4561,10 +4560,13 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
return;
}
type = alloc_type (objfile);
to_type = die_type (die, cu);
domain = die_containing_type (die, cu);
smash_to_member_type (type, domain, to_type);
if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD)
type = lookup_methodptr_type (to_type);
else
type = lookup_memberptr_type (to_type, domain);
set_die_type (die, type, cu);
}

View file

@ -1,8 +1,8 @@
/* Evaluate expressions for GDB.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free
Software Foundation, Inc.
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -38,6 +38,8 @@
#include "parser-defs.h"
#include "cp-support.h"
#include "gdb_assert.h"
/* This is defined in valops.c */
extern int overload_resolution;
@ -434,9 +436,11 @@ evaluate_subexp_standard (struct type *expect_type,
case OP_SCOPE:
tem = longest_to_int (exp->elts[pc + 2].longconst);
(*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
if (noside == EVAL_SKIP)
goto nosideret;
arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
&exp->elts[pc + 3].string,
noside);
0, noside);
if (arg1 == NULL)
error (_("There is no field named %s"), &exp->elts[pc + 3].string);
return arg1;
@ -993,8 +997,6 @@ evaluate_subexp_standard (struct type *expect_type,
argvec = (struct value **) alloca (sizeof (struct value *) * (nargs + 3));
if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
{
LONGEST fnptr;
/* 1997-08-01 Currently we do not support function invocation
via pointers-to-methods with HP aCC. Pointer does not point
to the function, but possibly to some thunk. */
@ -1027,41 +1029,18 @@ evaluate_subexp_standard (struct type *expect_type,
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
fnptr = value_as_long (arg1);
if (TYPE_CODE (check_typedef (value_type (arg1)))
!= TYPE_CODE_METHODPTR)
error (_("Non-pointer-to-member value used in pointer-to-member "
"construct"));
if (METHOD_PTR_IS_VIRTUAL (fnptr))
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
int fnoffset = METHOD_PTR_TO_VOFFSET (fnptr);
struct type *basetype;
struct type *domain_type =
TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (value_type (arg1)));
int i, j;
basetype = TYPE_TARGET_TYPE (value_type (arg2));
if (domain_type != basetype)
arg2 = value_cast (lookup_pointer_type (domain_type), arg2);
basetype = TYPE_VPTR_BASETYPE (domain_type);
for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
{
struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
/* If one is virtual, then all are virtual. */
if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
if ((int) TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset)
{
struct value *temp = value_ind (arg2);
arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0);
arg2 = value_addr (temp);
goto got_it;
}
}
if (i < 0)
error (_("virtual function at index %d not found"), fnoffset);
struct type *method_type = check_typedef (value_type (arg1));
arg1 = value_zero (method_type, not_lval);
}
else
{
deprecated_set_value_type (arg1, lookup_pointer_type (TYPE_TARGET_TYPE (value_type (arg1))));
}
got_it:
arg1 = cplus_method_ptr_to_value (&arg2, arg1);
/* Now, say which argument to start evaluating from */
tem = 2;
@ -1396,57 +1375,60 @@ evaluate_subexp_standard (struct type *expect_type,
}
case STRUCTOP_MEMBER:
arg1 = evaluate_subexp_for_address (exp, pos, noside);
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 *expect_type,
the implementation yet; but the pointer appears to point to a code
sequence (thunk) in memory -- in any case it is *not* the address
of the function as it would be in a naive implementation. */
if ((TYPE_CODE (value_type (arg1)) == TYPE_CODE_PTR) &&
(TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_METHOD))
if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_METHODPTR)
error (_("Assignment to pointers to methods not implemented with HP aCC"));
/* HP aCC pointers to data members require a constant bias */
if ((TYPE_CODE (value_type (arg1)) == TYPE_CODE_PTR) &&
(TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_MEMBER))
/* HP aCC pointers to data members require a constant bias. */
if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_MEMBERPTR)
{
unsigned int *ptr = (unsigned int *) value_contents (arg2); /* forces evaluation */
*ptr |= 0x20000000; /* set 29th bit */
@ -1934,9 +1914,9 @@ evaluate_subexp_standard (struct type *expect_type,
if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
if ((TYPE_TARGET_TYPE (value_type (arg1))) &&
((TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_METHOD) ||
(TYPE_CODE (TYPE_TARGET_TYPE (value_type (arg1))) == TYPE_CODE_MEMBER)))
type = check_typedef (value_type (arg1));
if (TYPE_CODE (type) == TYPE_CODE_METHODPTR
|| TYPE_CODE (type) == TYPE_CODE_MEMBERPTR)
error (_("Attempt to dereference pointer to member without an object"));
if (noside == EVAL_SKIP)
goto nosideret;
@ -1967,22 +1947,15 @@ evaluate_subexp_standard (struct type *expect_type,
if (noside == EVAL_SKIP)
{
if (op == OP_SCOPE)
{
int temm = longest_to_int (exp->elts[pc + 3].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (temm + 1);
}
else
evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
goto nosideret;
}
else
{
struct value *retvalp = evaluate_subexp_for_address (exp, pos, noside);
/* If HP aCC object, use bias for pointers to members */
if (deprecated_hp_som_som_object_present &&
(TYPE_CODE (value_type (retvalp)) == TYPE_CODE_PTR) &&
(TYPE_CODE (TYPE_TARGET_TYPE (value_type (retvalp))) == TYPE_CODE_MEMBER))
if (deprecated_hp_som_som_object_present
&& TYPE_CODE (value_type (retvalp)) == TYPE_CODE_MEMBERPTR)
{
unsigned int *ptr = (unsigned int *) value_contents (retvalp); /* forces evaluation */
*ptr |= 0x20000000; /* set 29th bit */
@ -2148,6 +2121,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
int pc;
struct symbol *var;
struct value *x;
int tem;
pc = (*pos);
op = exp->elts[pc].opcode;
@ -2162,15 +2136,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
if (unop_user_defined_p (op, x))
{
x = value_x_unop (x, op, noside);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
if (VALUE_LVAL (x) == lval_memory)
return value_zero (lookup_pointer_type (value_type (x)),
not_lval);
else
error (_("Attempt to take address of non-lval"));
}
return value_addr (x);
goto default_case_after_eval;
}
return x;
@ -2210,14 +2176,30 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
(var,
block_innermost_frame (exp->elts[pc + 1].block));
case OP_SCOPE:
tem = longest_to_int (exp->elts[pc + 2].longconst);
(*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1);
x = value_aggregate_elt (exp->elts[pc + 1].type,
&exp->elts[pc + 3].string,
1, noside);
if (x == NULL)
error (_("There is no field named %s"), &exp->elts[pc + 3].string);
return x;
default:
default_case:
x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
default_case_after_eval:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type = check_typedef (value_type (x));
if (VALUE_LVAL (x) == lval_memory)
return value_zero (lookup_pointer_type (value_type (x)),
not_lval);
else if (TYPE_CODE (type) == TYPE_CODE_REF)
return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
not_lval);
else
error (_("Attempt to take address of non-lval"));
}

View file

@ -73,7 +73,6 @@ f_print_type (struct type *type, char *varstring, struct ui_file *stream,
(code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
|| code == TYPE_CODE_METHOD
|| code == TYPE_CODE_ARRAY
|| code == TYPE_CODE_MEMBER
|| code == TYPE_CODE_REF)))
fputs_filtered (" ", stream);
f_type_print_varspec_prefix (type, stream, show, 0);
@ -138,7 +137,6 @@ f_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
case TYPE_CODE_STRING:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_METHOD:
case TYPE_CODE_MEMBER:
case TYPE_CODE_REF:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TYPEDEF:
@ -250,7 +248,6 @@ f_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
case TYPE_CODE_STRING:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_METHOD:
case TYPE_CODE_MEMBER:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TYPEDEF:
/* These types do not need a suffix. They are listed so that

View file

@ -235,6 +235,8 @@ struct gdbarch
gdbarch_register_reggroup_p_ftype *register_reggroup_p;
gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument;
gdbarch_regset_from_core_section_ftype *regset_from_core_section;
int vtable_function_descriptors;
int vbit_in_delta;
};
@ -361,6 +363,8 @@ struct gdbarch startup_gdbarch =
default_register_reggroup_p, /* register_reggroup_p */
0, /* fetch_pointer_argument */
0, /* regset_from_core_section */
0, /* vtable_function_descriptors */
0, /* vbit_in_delta */
/* startup_gdbarch() */
};
@ -615,6 +619,8 @@ verify_gdbarch (struct gdbarch *current_gdbarch)
/* Skip verify of register_reggroup_p, invalid_p == 0 */
/* Skip verify of fetch_pointer_argument, has predicate */
/* Skip verify of regset_from_core_section, has predicate */
/* Skip verify of vtable_function_descriptors, invalid_p == 0 */
/* Skip verify of vbit_in_delta, invalid_p == 0 */
buf = ui_file_xstrdup (log, &dummy);
make_cleanup (xfree, buf);
if (strlen (buf) > 0)
@ -1595,6 +1601,9 @@ gdbarch_dump (struct gdbarch *current_gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"gdbarch_dump: value_to_register = <0x%lx>\n",
(long) current_gdbarch->value_to_register);
fprintf_unfiltered (file,
"gdbarch_dump: vbit_in_delta = %s\n",
paddr_d (current_gdbarch->vbit_in_delta));
#ifdef TARGET_VIRTUAL_FRAME_POINTER
fprintf_unfiltered (file,
"gdbarch_dump: %s # %s\n",
@ -1604,6 +1613,9 @@ gdbarch_dump (struct gdbarch *current_gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"gdbarch_dump: virtual_frame_pointer = <0x%lx>\n",
(long) current_gdbarch->virtual_frame_pointer);
fprintf_unfiltered (file,
"gdbarch_dump: vtable_function_descriptors = %s\n",
paddr_d (current_gdbarch->vtable_function_descriptors));
#ifdef TARGET_WRITE_PC
fprintf_unfiltered (file,
"gdbarch_dump: %s # %s\n",
@ -3653,6 +3665,40 @@ set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch,
gdbarch->regset_from_core_section = regset_from_core_section;
}
int
gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
/* Skip verify of vtable_function_descriptors, invalid_p == 0 */
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_vtable_function_descriptors called\n");
return gdbarch->vtable_function_descriptors;
}
void
set_gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch,
int vtable_function_descriptors)
{
gdbarch->vtable_function_descriptors = vtable_function_descriptors;
}
int
gdbarch_vbit_in_delta (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
/* Skip verify of vbit_in_delta, invalid_p == 0 */
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_vbit_in_delta called\n");
return gdbarch->vbit_in_delta;
}
void
set_gdbarch_vbit_in_delta (struct gdbarch *gdbarch,
int vbit_in_delta)
{
gdbarch->vbit_in_delta = vbit_in_delta;
}
/* Keep a registry of per-architecture data-pointers required by GDB
modules. */

View file

@ -1383,6 +1383,19 @@ typedef const struct regset * (gdbarch_regset_from_core_section_ftype) (struct g
extern const struct regset * gdbarch_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size);
extern void set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch_regset_from_core_section_ftype *regset_from_core_section);
/* If the elements of C++ vtables are in-place function descriptors rather
than normal function pointers (which may point to code or a descriptor),
set this to one. */
extern int gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch);
extern void set_gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch, int vtable_function_descriptors);
/* Set if the least significant bit of the delta is used instead of the least
significant bit of the pfn for pointers to virtual member functions. */
extern int gdbarch_vbit_in_delta (struct gdbarch *gdbarch);
extern void set_gdbarch_vbit_in_delta (struct gdbarch *gdbarch, int vbit_in_delta);
extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);

View file

@ -663,6 +663,15 @@ F:=:CORE_ADDR:fetch_pointer_argument:struct frame_info *frame, int argi, struct
# Return the appropriate register set for a core file section with
# name SECT_NAME and size SECT_SIZE.
M::const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size
# If the elements of C++ vtables are in-place function descriptors rather
# than normal function pointers (which may point to code or a descriptor),
# set this to one.
v::int:vtable_function_descriptors:::0:0::0
# Set if the least significant bit of the delta is used instead of the least
# significant bit of the pfn for pointers to virtual member functions.
v::int:vbit_in_delta:::0:0::0
EOF
}

View file

@ -621,15 +621,30 @@ replace_type (struct type *ntype, struct type *type)
of the aggregate that the member belongs to. */
struct type *
lookup_member_type (struct type *type, struct type *domain)
lookup_memberptr_type (struct type *type, struct type *domain)
{
struct type *mtype;
mtype = alloc_type (TYPE_OBJFILE (type));
smash_to_member_type (mtype, domain, type);
smash_to_memberptr_type (mtype, domain, type);
return (mtype);
}
/* Return a pointer-to-method type, for a method of type TO_TYPE. */
struct type *
lookup_methodptr_type (struct type *to_type)
{
struct type *mtype;
mtype = alloc_type (TYPE_OBJFILE (to_type));
TYPE_TARGET_TYPE (mtype) = to_type;
TYPE_DOMAIN_TYPE (mtype) = TYPE_DOMAIN_TYPE (to_type);
TYPE_LENGTH (mtype) = cplus_method_ptr_size ();
TYPE_CODE (mtype) = TYPE_CODE_METHODPTR;
return mtype;
}
/* Allocate a stub method whose return type is TYPE.
This apparently happens for speed of symbol reading, since parsing
out the arguments to the method is cpu-intensive, the way we are doing
@ -981,19 +996,20 @@ build_builtin_type_vec128 (void)
return t;
}
/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE.
A MEMBER is a wierd thing -- it amounts to a typed offset into
a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't
include the offset (that's the value of the MEMBER itself), but does
include the structure type into which it points (for some reason).
/* Smash TYPE to be a type of pointers to members of DOMAIN with type
TO_TYPE. A member pointer is a wierd thing -- it amounts to a
typed offset into a struct, e.g. "an int at offset 8". A MEMBER
TYPE doesn't include the offset (that's the value of the MEMBER
itself), but does include the structure type into which it points
(for some reason).
When "smashing" the type, we preserve the objfile that the
old type pointed to, since we aren't changing where the type is actually
allocated. */
void
smash_to_member_type (struct type *type, struct type *domain,
struct type *to_type)
smash_to_memberptr_type (struct type *type, struct type *domain,
struct type *to_type)
{
struct objfile *objfile;
@ -1003,8 +1019,10 @@ smash_to_member_type (struct type *type, struct type *domain,
TYPE_OBJFILE (type) = objfile;
TYPE_TARGET_TYPE (type) = to_type;
TYPE_DOMAIN_TYPE (type) = domain;
TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
TYPE_CODE (type) = TYPE_CODE_MEMBER;
/* Assume that a data member pointer is the same size as a normal
pointer. */
TYPE_LENGTH (type) = TARGET_PTR_BIT / TARGET_CHAR_BIT;
TYPE_CODE (type) = TYPE_CODE_MEMBERPTR;
}
/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE.
@ -2643,7 +2661,7 @@ rank_one_type (struct type *parm, struct type *arg)
return INCOMPATIBLE_TYPE_BADNESS;
}
break;
case TYPE_CODE_MEMBER:
case TYPE_CODE_MEMBERPTR:
switch (TYPE_CODE (arg))
{
default:
@ -2957,8 +2975,11 @@ recursive_dump_type (struct type *type, int spaces)
case TYPE_CODE_ERROR:
printf_filtered ("(TYPE_CODE_ERROR)");
break;
case TYPE_CODE_MEMBER:
printf_filtered ("(TYPE_CODE_MEMBER)");
case TYPE_CODE_MEMBERPTR:
printf_filtered ("(TYPE_CODE_MEMBERPTR)");
break;
case TYPE_CODE_METHODPTR:
printf_filtered ("(TYPE_CODE_METHODPTR)");
break;
case TYPE_CODE_METHOD:
printf_filtered ("(TYPE_CODE_METHOD)");

View file

@ -142,8 +142,20 @@ enum type_code
TYPE_CODE_ERROR,
/* C++ */
TYPE_CODE_MEMBER, /* Member type */
TYPE_CODE_METHOD, /* Method type */
/* Pointer-to-member-function type. This describes how to access a
particular member function of a class (possibly a virtual
member function). The representation may vary between different
C++ ABIs. */
TYPE_CODE_METHODPTR,
/* Pointer-to-member type. This is the offset within a class to some
particular data member. The only currently supported representation
uses an unbiased offset, with -1 representing NULL; this is used
by the Itanium C++ ABI (used by GCC on all platforms). */
TYPE_CODE_MEMBERPTR,
TYPE_CODE_REF, /* C++ Reference types */
TYPE_CODE_CHAR, /* *real* character type */
@ -464,8 +476,9 @@ struct main_type
/* For types with virtual functions (TYPE_CODE_STRUCT), VPTR_BASETYPE
is the base class which defined the virtual function table pointer.
For types that are pointer to member types (TYPE_CODE_MEMBER),
VPTR_BASETYPE is the type that this pointer is a member of.
For types that are pointer to member types (TYPE_CODE_METHODPTR,
TYPE_CODE_MEMBERPTR), VPTR_BASETYPE is the type that this pointer
is a member of.
For method types (TYPE_CODE_METHOD), VPTR_BASETYPE is the aggregate
type that contains the method.
@ -1220,14 +1233,16 @@ extern const char *address_space_int_to_name (int);
extern struct type *make_type_with_address_space (struct type *type,
int space_identifier);
extern struct type *lookup_member_type (struct type *, struct type *);
extern struct type *lookup_memberptr_type (struct type *, struct type *);
extern void
smash_to_method_type (struct type *type, struct type *domain,
struct type *to_type, struct field *args,
int nargs, int varargs);
extern struct type *lookup_methodptr_type (struct type *);
extern void smash_to_member_type (struct type *, struct 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_memberptr_type (struct type *, struct type *,
struct type *);
extern struct type *allocate_stub_method (struct type *);

View file

@ -1,7 +1,8 @@
/* Abstraction of GNU v3 abi.
Contributed by Jim Blandy <jimb@redhat.com>
Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
Copyright (C) 2001, 2002, 2003, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -25,6 +26,8 @@
#include "cp-abi.h"
#include "cp-support.h"
#include "demangle.h"
#include "valprint.h"
#include "gdb_assert.h"
#include "gdb_string.h"
@ -274,77 +277,92 @@ 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_get_vtable (struct value *container)
{
struct type *vtable_type = gdbarch_data (current_gdbarch,
vtable_type_gdbarch_data);
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 ());
}
/* Return a function pointer for CONTAINER's VTABLE_INDEX'th virtual
function, of type FNTYPE. */
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, vtable_index));
/* 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);
/* 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 *type, int offset)
struct type *vfn_base, int offset)
{
struct type *vtable_type = gdbarch_data (current_gdbarch,
vtable_type_gdbarch_data);
struct value *value = *value_p;
struct type *values_type = check_typedef (value_type (value));
struct type *vfn_base;
CORE_ADDR vtable_address;
struct value *vtable;
struct value *vfn;
struct type *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."));
/* 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. */
/* 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 = value_cast (vfn_base, value);
*value_p = value_cast (vfn_base, *value_p);
/* Now value is an object of the appropriate base type. Fetch its
virtual table. */
/* It might be possible to do this cast at the same time as the above.
Does multiple inheritance affect this?
Can this even trigger, or is TYPE_VPTR_BASETYPE idempotent?
*/
if (TYPE_VPTR_BASETYPE (vfn_base) != vfn_base)
value = value_cast (TYPE_VPTR_BASETYPE (vfn_base), value);
vtable_address
= value_as_address (value_field (value, TYPE_VPTR_FIELDNO (vfn_base)));
vtable = value_at_lazy (vtable_type,
vtable_address - vtable_address_point_offset ());
/* 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)));
/* Cast the function pointer to the appropriate type. */
vfn = value_cast (lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)),
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));
return vfn;
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
@ -416,6 +434,245 @@ gnuv3_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr,
return base_offset;
}
/* Locate a virtual method in DOMAIN or its non-virtual base classes
which has virtual table index VOFFSET. The method has an associated
"this" adjustment of ADJUSTMENT bytes. */
const char *
gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset,
LONGEST adjustment)
{
int i;
const char *physname;
/* Search this class first. */
physname = NULL;
if (adjustment == 0)
{
int len;
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
int len2, j;
struct fn_field *f;
f = TYPE_FN_FIELDLIST1 (domain, i);
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
check_stub_method_group (domain, i);
for (j = 0; j < len2; j++)
if (TYPE_FN_FIELD_VOFFSET (f, j) == voffset)
return TYPE_FN_FIELD_PHYSNAME (f, j);
}
}
/* Next search non-virtual bases. If it's in a virtual base,
we're out of luck. */
for (i = 0; i < TYPE_N_BASECLASSES (domain); i++)
{
int pos;
struct type *basetype;
if (BASETYPE_VIA_VIRTUAL (domain, i))
continue;
pos = TYPE_BASECLASS_BITPOS (domain, i) / 8;
basetype = TYPE_FIELD_TYPE (domain, i);
/* Recurse with a modified adjustment. We don't need to adjust
voffset. */
if (adjustment >= pos && adjustment < pos + TYPE_LENGTH (basetype))
return gnuv3_find_method_in (basetype, voffset, adjustment - pos);
}
return NULL;
}
/* GNU v3 implementation of cplus_print_method_ptr. */
static void
gnuv3_print_method_ptr (const gdb_byte *contents,
struct type *type,
struct ui_file *stream)
{
CORE_ADDR ptr_value;
LONGEST adjustment;
struct type *domain;
int vbit;
domain = TYPE_DOMAIN_TYPE (type);
/* Extract the pointer to member. */
ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
contents += TYPE_LENGTH (builtin_type_void_func_ptr);
adjustment = extract_signed_integer (contents,
TYPE_LENGTH (builtin_type_long));
if (!gdbarch_vbit_in_delta (current_gdbarch))
{
vbit = ptr_value & 1;
ptr_value = ptr_value ^ vbit;
}
else
{
vbit = adjustment & 1;
adjustment = adjustment >> 1;
}
/* Check for NULL. */
if (ptr_value == 0 && vbit == 0)
{
fprintf_filtered (stream, "NULL");
return;
}
/* Search for a virtual method. */
if (vbit)
{
CORE_ADDR voffset;
const char *physname;
/* It's a virtual table offset, maybe in this class. Search
for a field with the correct vtable offset. First convert it
to an index, as used in TYPE_FN_FIELD_VOFFSET. */
voffset = ptr_value / TYPE_LENGTH (builtin_type_long);
physname = gnuv3_find_method_in (domain, voffset, adjustment);
/* If we found a method, print that. We don't bother to disambiguate
possible paths to the method based on the adjustment. */
if (physname)
{
char *demangled_name = cplus_demangle (physname,
DMGL_ANSI | DMGL_PARAMS);
if (demangled_name != NULL)
{
fprintf_filtered (stream, "&virtual ");
fputs_filtered (demangled_name, stream);
xfree (demangled_name);
return;
}
}
}
/* We didn't find it; print the raw data. */
if (vbit)
{
fprintf_filtered (stream, "&virtual table offset ");
print_longest (stream, 'd', 1, ptr_value);
}
else
print_address_demangle (ptr_value, stream, demangle);
if (adjustment)
{
fprintf_filtered (stream, ", this adjustment ");
print_longest (stream, 'd', 1, adjustment);
}
}
/* GNU v3 implementation of cplus_method_ptr_size. */
static int
gnuv3_method_ptr_size (void)
{
return 2 * TYPE_LENGTH (builtin_type_void_data_ptr);
}
/* GNU v3 implementation of cplus_make_method_ptr. */
static void
gnuv3_make_method_ptr (gdb_byte *contents, CORE_ADDR value, int is_virtual)
{
int size = TYPE_LENGTH (builtin_type_void_data_ptr);
/* FIXME drow/2006-12-24: The adjustment of "this" is currently
always zero, since the method pointer is of the correct type.
But if the method pointer came from a base class, this is
incorrect - it should be the offset to the base. The best
fix might be to create the pointer to member pointing at the
base class and cast it to the derived class, but that requires
support for adjusting pointers to members when casting them -
not currently supported by GDB. */
if (!gdbarch_vbit_in_delta (current_gdbarch))
{
store_unsigned_integer (contents, size, value | is_virtual);
store_unsigned_integer (contents + size, size, 0);
}
else
{
store_unsigned_integer (contents, size, value);
store_unsigned_integer (contents + size, size, is_virtual);
}
}
/* GNU v3 implementation of cplus_method_ptr_to_value. */
static struct value *
gnuv3_method_ptr_to_value (struct value **this_p, struct value *method_ptr)
{
const gdb_byte *contents = value_contents (method_ptr);
CORE_ADDR ptr_value;
struct type *final_type, *method_type;
LONGEST adjustment;
struct value *adjval;
int vbit;
final_type = TYPE_DOMAIN_TYPE (check_typedef (value_type (method_ptr)));
final_type = lookup_pointer_type (final_type);
method_type = TYPE_TARGET_TYPE (check_typedef (value_type (method_ptr)));
ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
contents += TYPE_LENGTH (builtin_type_void_func_ptr);
adjustment = extract_signed_integer (contents,
TYPE_LENGTH (builtin_type_long));
if (!gdbarch_vbit_in_delta (current_gdbarch))
{
vbit = ptr_value & 1;
ptr_value = ptr_value ^ vbit;
}
else
{
vbit = adjustment & 1;
adjustment = adjustment >> 1;
}
/* First convert THIS to match the containing type of the pointer to
member. This cast may adjust the value of THIS. */
*this_p = value_cast (final_type, *this_p);
/* Then apply whatever adjustment is necessary. This creates a somewhat
strange pointer: it claims to have type FINAL_TYPE, but in fact it
might not be a valid FINAL_TYPE. For instance, it might be a
base class of FINAL_TYPE. And if it's not the primary base class,
then printing it out as a FINAL_TYPE object would produce some pretty
garbage.
But we don't really know the type of the first argument in
METHOD_TYPE either, which is why this happens. We can't
dereference this later as a FINAL_TYPE, but once we arrive in the
called method we'll have debugging information for the type of
"this" - and that'll match the value we produce here.
You can provoke this case by casting a Base::* to a Derived::*, for
instance. */
*this_p = value_cast (builtin_type_void_data_ptr, *this_p);
adjval = value_from_longest (builtin_type_long, adjustment);
*this_p = value_add (*this_p, adjval);
*this_p = value_cast (final_type, *this_p);
if (vbit)
{
LONGEST voffset = ptr_value / TYPE_LENGTH (builtin_type_long);
return gnuv3_get_virtual_fn (value_ind (*this_p), method_type, voffset);
}
else
return value_from_pointer (lookup_pointer_type (method_type), ptr_value);
}
static void
init_gnuv3_ops (void)
{
@ -433,6 +690,10 @@ init_gnuv3_ops (void)
gnu_v3_abi_ops.rtti_type = gnuv3_rtti_type;
gnu_v3_abi_ops.virtual_fn_field = gnuv3_virtual_fn_field;
gnu_v3_abi_ops.baseclass_offset = gnuv3_baseclass_offset;
gnu_v3_abi_ops.print_method_ptr = gnuv3_print_method_ptr;
gnu_v3_abi_ops.method_ptr_size = gnuv3_method_ptr_size;
gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr;
gnu_v3_abi_ops.method_ptr_to_value = gnuv3_method_ptr_to_value;
}
extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */

View file

@ -1,6 +1,6 @@
/* Read hp debug symbols and convert to internal format, for GDB.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004 Free Software Foundation, Inc.
2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@ -4875,9 +4875,7 @@ hpread_type_lookup (dnttpointer hp_type, struct objfile *objfile)
objfile),
class_type = hpread_type_lookup (dn_bufp->dptrmem.pointsto,
objfile),
ptrmemtype = alloc_type (objfile);
smash_to_member_type (ptrmemtype, class_type, memtype);
return make_pointer_type (ptrmemtype, NULL);
return lookup_memberptr_type (memtype, class_type);
}
break;
@ -4905,7 +4903,7 @@ hpread_type_lookup (dnttpointer hp_type, struct objfile *objfile)
TYPE_FIELDS (functype),
TYPE_NFIELDS (functype),
0);
return make_pointer_type (ptrmemtype, NULL);
return lookup_methodptr_type (ptrmemtype);
}
break;

View file

@ -40,6 +40,7 @@
#include "infcall.h"
#include "osabi.h"
#include "ia64-tdep.h"
#include "cp-abi.h"
#ifdef HAVE_LIBUNWIND_IA64_H
#include "elf/ia64.h" /* for PT_IA_64_UNWIND value */
@ -3306,6 +3307,17 @@ ia64_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
if (s && strcmp (s->the_bfd_section->name, ".opd") == 0)
return read_memory_unsigned_integer (addr, 8);
/* There are also descriptors embedded in vtables. */
if (s)
{
struct minimal_symbol *minsym;
minsym = lookup_minimal_symbol_by_pc (addr);
if (minsym && is_vtable_name (SYMBOL_LINKAGE_NAME (minsym)))
return read_memory_unsigned_integer (addr, 8);
}
return addr;
}
@ -3640,6 +3652,10 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_print_insn (gdbarch, ia64_print_insn);
set_gdbarch_convert_from_func_ptr_addr (gdbarch, ia64_convert_from_func_ptr_addr);
/* The virtual table contains 16-byte descriptors, not pointers to
descriptors. */
set_gdbarch_vtable_function_descriptors (gdbarch, 1);
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);

View file

@ -1,7 +1,7 @@
/* Perform an inferior function call, for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -169,7 +169,8 @@ value_arg_coerce (struct value *arg, struct type *param_type,
case TYPE_CODE_STRING:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_ERROR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_MEMBERPTR:
case TYPE_CODE_METHODPTR:
case TYPE_CODE_METHOD:
case TYPE_CODE_COMPLEX:
default:

View file

@ -112,10 +112,6 @@ m2_print_type (struct type *type, char *varstring, struct ui_file *stream,
m2_ref (type, stream, show, level);
break;
case TYPE_CODE_MEMBER:
m2_unknown (_("member"), type, stream, show, level);
break;
case TYPE_CODE_METHOD:
m2_unknown (_("method"), type, stream, show, level);
break;

View file

@ -327,10 +327,6 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
}
break;
case TYPE_CODE_MEMBER:
error (_("not implemented: member type in m2_val_print"));
break;
case TYPE_CODE_REF:
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (addressprint)

View file

@ -5231,6 +5231,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
/* Virtual tables. */
set_gdbarch_vbit_in_delta (gdbarch, 1);
mips_register_g_packet_guesses (gdbarch);
/* Hook in OS ABI-specific overrides, if they have been registered. */

View file

@ -1,6 +1,6 @@
/* Pascal language support definitions for GDB, the GNU debugger.
Copyright (C) 2000, 2005 Free Software Foundation, Inc.
Copyright (C) 2000, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@ -67,12 +67,6 @@ extern int vtblprint; /* Controls printing of vtbl's */
extern int static_field_print;
extern void pascal_object_print_class_member (const gdb_byte *, struct type *,
struct ui_file *, char *);
extern void pascal_object_print_class_method (const gdb_byte *, struct type *,
struct ui_file *);
extern void pascal_object_print_value_fields (struct type *, const gdb_byte *,
CORE_ADDR, struct ui_file *,
int, int, enum val_prettyprint,

View file

@ -1,5 +1,5 @@
/* Support for printing Pascal types for GDB, the GNU debugger.
Copyright (C) 2000, 2001, 2002
Copyright (C) 2000, 2001, 2002, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -208,19 +208,6 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
break; /* pointer should be handled normally in pascal */
case TYPE_CODE_MEMBER:
if (passed_a_ptr)
fprintf_filtered (stream, "(");
pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
fprintf_filtered (stream, " ");
name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
if (name)
fputs_filtered (name, stream);
else
pascal_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
fprintf_filtered (stream, "::");
break;
case TYPE_CODE_METHOD:
if (passed_a_ptr)
fprintf_filtered (stream, "(");
@ -353,12 +340,6 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
fprintf_filtered (stream, ")");
break;
case TYPE_CODE_MEMBER:
if (passed_a_ptr)
fprintf_filtered (stream, ")");
pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
break;
case TYPE_CODE_METHOD:
if (passed_a_ptr)
fprintf_filtered (stream, ")");
@ -481,7 +462,6 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show,
{
case TYPE_CODE_TYPEDEF:
case TYPE_CODE_PTR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_REF:
/* case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD: */

View file

@ -151,17 +151,6 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
break;
}
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
{
pascal_object_print_class_method (valaddr + embedded_offset, type, stream);
}
else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
{
pascal_object_print_class_member (valaddr + embedded_offset,
TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
stream, "&");
}
else
{
addr = unpack_pointer (type, valaddr + embedded_offset);
print_unpacked_pointer:
@ -259,19 +248,8 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
}
break;
case TYPE_CODE_MEMBER:
error (_("not implemented: member type in pascal_val_print"));
break;
case TYPE_CODE_REF:
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
{
pascal_object_print_class_member (valaddr + embedded_offset,
TYPE_DOMAIN_TYPE (elttype),
stream, "");
break;
}
if (addressprint)
{
fprintf_filtered (stream, "@");
@ -604,96 +582,6 @@ static void pascal_object_print_value (struct type *, const gdb_byte *,
int, int, enum val_prettyprint,
struct type **);
void
pascal_object_print_class_method (const gdb_byte *valaddr, struct type *type,
struct ui_file *stream)
{
struct type *domain;
struct fn_field *f = NULL;
int j = 0;
int len2;
int offset;
char *kind = "";
CORE_ADDR addr;
struct symbol *sym;
unsigned len;
unsigned int i;
struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
domain = TYPE_DOMAIN_TYPE (target_type);
if (domain == (struct type *) NULL)
{
fprintf_filtered (stream, "<unknown>");
return;
}
addr = unpack_pointer (lookup_pointer_type (builtin_type_void), valaddr);
if (METHOD_PTR_IS_VIRTUAL (addr))
{
offset = METHOD_PTR_TO_VOFFSET (addr);
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
f = TYPE_FN_FIELDLIST1 (domain, i);
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
check_stub_method_group (domain, i);
for (j = 0; j < len2; j++)
{
if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
{
kind = "virtual ";
goto common;
}
}
}
}
else
{
sym = find_pc_function (addr);
if (sym == 0)
{
error (_("invalid pointer to member function"));
}
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
f = TYPE_FN_FIELDLIST1 (domain, i);
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
check_stub_method_group (domain, i);
for (j = 0; j < len2; j++)
{
if (DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
goto common;
}
}
}
common:
if (i < len)
{
char *demangled_name;
fprintf_filtered (stream, "&");
fputs_filtered (kind, stream);
demangled_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (f, j),
DMGL_ANSI | DMGL_PARAMS);
if (demangled_name == NULL)
fprintf_filtered (stream, "<badly mangled name %s>",
TYPE_FN_FIELD_PHYSNAME (f, j));
else
{
fputs_filtered (demangled_name, stream);
xfree (demangled_name);
}
}
else
{
fprintf_filtered (stream, "(");
type_print (type, "", stream, -1);
fprintf_filtered (stream, ") %d", (int) addr >> 3);
}
}
/* It was changed to this after 2.4.5. */
const char pascal_vtbl_ptr_name[] =
{'_', '_', 'v', 't', 'b', 'l', '_', 'p', 't', 'r', '_', 't', 'y', 'p', 'e', 0};
@ -1060,58 +948,6 @@ pascal_object_print_static_field (struct value *val,
common_val_print (val, stream, format, 0, recurse, pretty);
}
void
pascal_object_print_class_member (const gdb_byte *valaddr, struct type *domain,
struct ui_file *stream, char *prefix)
{
/* VAL is a byte offset into the structure type DOMAIN.
Find the name of the field for that offset and
print it. */
int extra = 0;
int bits = 0;
unsigned int i;
unsigned len = TYPE_NFIELDS (domain);
/* @@ Make VAL into bit offset */
LONGEST val = unpack_long (builtin_type_int, valaddr) << 3;
for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
{
int bitpos = TYPE_FIELD_BITPOS (domain, i);
QUIT;
if (val == bitpos)
break;
if (val < bitpos && i != 0)
{
/* Somehow pointing into a field. */
i -= 1;
extra = (val - TYPE_FIELD_BITPOS (domain, i));
if (extra & 0x7)
bits = 1;
else
extra >>= 3;
break;
}
}
if (i < len)
{
char *name;
fputs_filtered (prefix, stream);
name = type_name_no_tag (domain);
if (name)
fputs_filtered (name, stream);
else
pascal_type_print_base (domain, stream, 0, 0);
fprintf_filtered (stream, "::");
fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
if (extra)
fprintf_filtered (stream, " + %d bytes", extra);
if (bits)
fprintf_filtered (stream, " (offset in bits)");
}
else
fprintf_filtered (stream, "%ld", (long int) (val >> 3));
}
extern initialize_file_ftype _initialize_pascal_valprint; /* -Wmissing-prototypes */
void

View file

@ -1,7 +1,7 @@
/* Support routines for decoding "stabs" debugging information format.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -1731,7 +1731,7 @@ again:
memtype = read_type (pp, objfile);
type = dbx_alloc_type (typenums, objfile);
smash_to_member_type (type, domain, memtype);
smash_to_memberptr_type (type, domain, memtype);
}
else
/* type attribute */

View file

@ -1,3 +1,21 @@
2007-01-03 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.cp/classes.exp (test_pointers_to_class_members): Update expected
output. Test the types of members and member pointers.
* gdb.cp/inherit.exp (test_print_mi_member_types): Remove KFAILs for
gdb/2092.
* gdb.cp/member-ptr.exp: Search for a comment instead of a
statement. Enable for GCC. Update expected output for some tests
and add new tests. Remove obsolete GCC KFAILs. Allow GCC's class
layout.
* gdb.cp/member-ptr.cc (Padding, Padding::vspacer, Base, Base::get_x)
(Base::vget_base, Left, Left::vget, Right, Right::vget, Diamond)
(Diamond::vget_base): New.
(main): Add new tests.
* gdb.cp/printmethod.exp: Update expected output for member functions.
* gdb.cp/virtfunc.exp (test_virtual_calls): Add a KFAIL for
print pEe->D::vg().
2007-01-03 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.threads/tls.exp: Allow stops in sem_post.

View file

@ -1,5 +1,5 @@
# Copyright 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# 2003, 2004, 2006 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -498,11 +498,14 @@ proc test_enums {} {
# Pointers to class members
proc test_pointers_to_class_members {} {
gdb_test "print Bar::z" "\\$\[0-9\]+ = \\(int ?\\( ?Bar::& ?\\) ?\\) ?Bar::z"
gdb_test "print &Foo::x" "\\$\[0-9\]+ = \\(int ?\\( ?Foo::\\* ?\\) ?\\) ?&Foo::x"
gdb_test "print Bar::z" "Cannot reference non-static field \"z\""
gdb_test "print &Foo::x" "\\$\[0-9\]+ = &Foo::x"
gdb_test "print (int)&Foo::x" "\\$\[0-9\]+ = 0"
gdb_test "print (int)&Bar::y == 2*sizeof(int)" "\\$\[0-9\]+ = true"
gdb_test "ptype Bar::z" "type = int"
gdb_test "ptype &Bar::z" "type = int Bar::\\*"
# TODO: this is a bogus test. It's looking at a variable that
# has not even been declared yet, so it's accessing random junk
# on the stack and comparing that it's NOT equal to a specific

View file

@ -389,29 +389,19 @@ proc test_print_mi_member_types {} {
# Print the types of qualified members; none of these tests pass today.
# Print all members of g_A.
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_A.A::a" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_A.A::x" "type = int"
# Print all members of g_B.
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_B.A::a" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_B.A::x" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_B.B::b" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_B.B::x" "type = int"
# Print all members of g_C.
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_C.A::a" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_C.A::x" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_C.C::c" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_C.C::x" "type = int"
# Print all members of g_D.
@ -423,9 +413,6 @@ proc test_print_mi_member_types {} {
set name "ptype g_D.A::a"
gdb_test_multiple "ptype g_D.A::a" $name {
-re "Attempt to take address of non-lval$nl$gdb_prompt $" {
kfail "gdb/2092" "$name"
}
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_D.A::a"
}
@ -433,25 +420,16 @@ proc test_print_mi_member_types {} {
set name "ptype g_D.A::x"
gdb_test_multiple "ptype g_D.A::x" $name {
-re "Attempt to take address of non-lval$nl$gdb_prompt $" {
kfail "gdb/2092" "$name"
}
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_D.A::x"
}
}
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_D.B::b" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_D.B::x" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_D.C::c" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_D.C::x" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_D.D::d" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_D.D::x" "type = int"
# Print all members of g_E.
@ -459,9 +437,6 @@ proc test_print_mi_member_types {} {
set name "ptype g_E.A::a"
gdb_test_multiple "ptype g_E.A::a" $name {
-re "Attempt to take address of non-lval$nl$gdb_prompt $" {
kfail "gdb/2092" "$name"
}
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_E.A::a"
}
@ -469,29 +444,18 @@ proc test_print_mi_member_types {} {
set name "ptype g_E.A::x"
gdb_test_multiple "ptype g_E.A::x" $name {
-re "Attempt to take address of non-lval$nl$gdb_prompt $" {
kfail "gdb/2092" "$name"
}
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_E.A::x"
}
}
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.B::b" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.B::x" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.C::c" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.C::x" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.D::d" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.D::x" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.E::e" "type = int"
setup_kfail "gdb/2092" "*-*-*"
gdb_test "ptype g_E.E::x" "type = int"
}

View file

@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 1998, 1999, 2004 Free Software Foundation, Inc.
Copyright 1998, 1999, 2004, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -81,6 +81,69 @@ typedef int (A::*PMF)(int);
typedef int A::*PMI;
/* This class is in front of the other base classes of Diamond, so
that we can detect if the offset for Left or the first Base is
added twice - otherwise it would be 2 * 0 == 0. */
class Padding
{
int spacer;
virtual int vspacer();
};
int Padding::vspacer()
{
return this->spacer;
}
class Base
{
public:
int x;
int get_x();
virtual int vget_base ();
};
int Base::get_x ()
{
return this->x;
}
int Base::vget_base ()
{
return this->x + 1000;
}
class Left : public Base {
public:
virtual int vget ();
};
int Left::vget ()
{
return this->x + 100;
}
class Right : public Base {
public:
virtual int vget ();
};
int Right::vget ()
{
return this->x + 200;
}
class Diamond : public Padding, public Left, public Right
{
public:
virtual int vget_base ();
};
int Diamond::vget_base ()
{
return this->Left::x + 2000;
}
int main ()
{
A a;
@ -90,6 +153,18 @@ int main ()
PMF * pmf_p;
PMI pmi;
Diamond diamond;
int (Diamond::*left_pmf) ();
int (Diamond::*right_pmf) ();
int (Diamond::*left_vpmf) ();
int (Diamond::*left_base_vpmf) ();
int (Diamond::*right_vpmf) ();
int (Base::*base_vpmf) ();
int Diamond::*diamond_pmi;
PMI null_pmi;
PMF null_pmf;
a.j = 121;
a.jj = 1331;
@ -101,8 +176,27 @@ int main ()
pmf = &A::bar;
pmf_p = &pmf;
pmi = NULL;
diamond.Left::x = 77;
diamond.Right::x = 88;
/* Some valid pointer to members from a base class. */
left_pmf = (int (Diamond::*) ()) (int (Left::*) ()) (&Base::get_x);
right_pmf = (int (Diamond::*) ()) (int (Right::*) ()) (&Base::get_x);
left_vpmf = &Left::vget;
left_base_vpmf = (int (Diamond::*) ()) (int (Left::*) ()) (&Base::vget_base);
right_vpmf = &Right::vget;
/* An unspecified, value preserving pointer to member cast. */
base_vpmf = (int (Base::*) ()) (int (Left::*) ()) &Diamond::vget_base;
/* A pointer to data member from a base class. */
diamond_pmi = (int Diamond::*) (int Left::*) &Base::x;
null_pmi = NULL;
null_pmf = NULL;
pmi = NULL; /* Breakpoint 1 here. */
k = (a.*pmf)(3);
pmi = &A::jj;

View file

@ -1,4 +1,4 @@
# Copyright 1998, 1999, 2003, 2004 Free Software Foundation, Inc.
# Copyright 1998, 1999, 2003, 2004, 2006 Free Software Foundation, Inc.
# This file is part of the gdb testsuite
@ -20,8 +20,6 @@
# Written by Satish Pai <pai@apollo.hp.com> 1997-08-19
# Rewritten by Michael Chastain <mec.gnu@mindspring.com> 2004-01-11
# TODO: copyright notice for member-ptr.cc
set vhn "\\$\[0-9\]+"
if $tracelevel then {
@ -56,16 +54,9 @@ if ![runto_main] then {
continue
}
gdb_breakpoint [gdb_get_line_number "pmi = NULL"]
gdb_breakpoint [gdb_get_line_number "Breakpoint 1 here"]
gdb_continue_to_breakpoint "continue to pmi = NULL"
# gcc is not ready for production
# -- chastain 2004-01-12
if { [test_compiler_info "gcc-*"] } {
continue
}
# ======================
# pointer to member data
# ======================
@ -74,14 +65,9 @@ if { [test_compiler_info "gcc-*"] } {
set name "ptype pmi (A::j)"
gdb_test_multiple "ptype pmi" $name {
-re "type = int *\\( ?A::\\*\\)\r\n$gdb_prompt $" {
-re "type = int A::\\*\r\n$gdb_prompt $" {
pass $name
}
-re "type = int *A::\r\n$gdb_prompt $" {
# gcc HEAD 2004-01-10 -gdwarf-2
# gcc HEAD 2004-01-10 -gstabs+
kfail "gdb/NNNN" $name
}
}
# print pointer to data member
@ -390,7 +376,7 @@ gdb_test_multiple "ptype *pmi" $name {
set name "print (int) pmi"
gdb_test_multiple "print (int) pmi" $name {
-re "$vhn = (4|8)\r\n$gdb_prompt" {
-re "$vhn = (4|8|12)\r\n$gdb_prompt" {
pass $name
}
}
@ -412,7 +398,7 @@ gdb_test_multiple "print ((int) pmi) == ((char *) &a.j - (char *) & a)" $name {
set name "ptype pmf"
gdb_test_multiple "ptype pmf" $name {
-re "type = int \\( ?A::\\*\\)\\(int\\)\r\n$gdb_prompt $" {
-re "type = int \\( ?A::\\*\\)\\(A \\*, int\\)\r\n$gdb_prompt $" {
pass $name
}
-re "type = int \\( ?A::\\*\\)\\(void\\)\r\n$gdb_prompt $" {
@ -434,7 +420,7 @@ gdb_test_multiple "ptype pmf" $name {
set name "print pmf"
gdb_test_multiple "print pmf" $name {
-re "$vhn = &A::bar\r\n$gdb_prompt $" {
-re "$vhn = $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
pass $name
}
-re "$vhn = .*not supported with HP aCC.*\r\n$gdb_prompt $" {
@ -456,7 +442,7 @@ gdb_test_multiple "print pmf" $name {
set name "ptype pmf_p"
gdb_test_multiple "ptype pmf_p" $name {
-re "type = int \\( ?A::\\*\\*\\)\\(int\\)\r\n$gdb_prompt $" {
-re "type = int \\( ?A::\\*\\*\\)\\(A \\*, int\\)\r\n$gdb_prompt $" {
pass $name
}
-re "type = int \\( ?A::\\*\\*\\)\\(void\\)\r\n$gdb_prompt $" {
@ -498,7 +484,7 @@ gdb_test_multiple "print pmf_p" $name {
set name "print a.*pmf"
gdb_test_multiple "print a.*pmf" $name {
-re "$vhn = \\(int \\(\\*\\)\\(int\\)\\) $hex <A::bar\\(int\\)>\r\n$gdb_prompt$ " {
-re "$vhn = {int \\(A \\*, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
pass $name
}
-re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" {
@ -520,7 +506,7 @@ gdb_test_multiple "print a.*pmf" $name {
set name "print a_p->*pmf"
gdb_test_multiple "print a_p->*pmf" $name {
-re "$vhn = \\(int \\(\\*\\)\\(int\\)\\) $hex <A::bar\\(int\\)>\r\n$gdb_prompt$ " {
-re "$vhn = {int \\(A \\*, int\\)} $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
pass $name
}
-re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" {
@ -621,3 +607,56 @@ gdb_test_multiple "print (a.*pmf)(3)" $name {
kfail "gdb/NNNN" $name
}
}
# Print out a pointer to data member which requires looking into
# a base class.
gdb_test "print diamond_pmi" "$vhn = &Base::x"
gdb_test "print diamond.*diamond_pmi" "$vhn = 77"
# Examine some more complicated pmfs, which require adjusting "this"
# and looking through virtual tables.
# These two have a different object adjustment, but call the same method.
gdb_test "print diamond.*left_pmf" \
"$vhn = {int \\(Diamond \\*\\)} $hex <Base::get_x\\((void|)\\)>"
gdb_test "print diamond.*right_pmf" \
"$vhn = {int \\(Diamond \\*\\)} $hex <Base::get_x\\((void|)\\)>"
gdb_test "print (diamond.*left_pmf) ()" "$vhn = 77"
gdb_test "print (diamond.*right_pmf) ()" "$vhn = 88"
# These two point to different methods, although they have the same
# virtual table offsets.
gdb_test "print diamond.*left_vpmf" \
"$vhn = {int \\(Diamond \\*\\)} $hex <Left::vget\\((void|)\\)>"
gdb_test "print diamond.*right_vpmf" \
"$vhn = {int \\(Diamond \\*\\)} $hex <Right::vget\\((void|)\\)>"
gdb_test "print (diamond.*left_vpmf) ()" "$vhn = 177"
gdb_test "print (diamond.*left_base_vpmf) ()" "$vhn = 2077"
gdb_test "print (diamond.*right_vpmf) ()" "$vhn = 288"
# We should be able to figure out left_vpmf even without an object,
# because it comes from a non-virtual base. The same for right_vpmf.
gdb_test "print left_vpmf" "$vhn = &virtual Left::vget\\(\\)"
gdb_test "print right_vpmf" "$vhn = &virtual Right::vget\\(\\)"
# But we should gracefully fail to figure out base_vpmf, because
# its runtime type is more derived than its static type. This
# is a valid but unspecified cast (it is value preserving, i.e.
# can be casted back to the correct type and used).
gdb_test "print base_vpmf" \
"$vhn = &virtual table offset \[0-9\]*, this adjustment -\[0-9\]*"
# Make sure we parse this correctly; it's invalid.
gdb_test "print diamond.*left_vpmf ()" \
"Invalid data type for function to be called\\."
# NULL pointer to member tests.
gdb_test "print null_pmi" "$vhn = NULL"
gdb_test "print null_pmi = &A::j" "$vhn = &A::j"
gdb_test "print null_pmi = 0" "$vhn = NULL"
gdb_test "print null_pmf" "$vhn = NULL"
gdb_test "print null_pmf = &A::foo" "$vhn = $hex <A::foo ?\\(int\\)>"
gdb_test "print null_pmf = 0" "$vhn = NULL"

View file

@ -1,4 +1,4 @@
# Copyright 2002, 2003, 2005 Free Software Foundation, Inc.
# Copyright 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -63,8 +63,12 @@ gdb_continue_to_breakpoint "end of constructors"
# The first of these is for PR gdb/653.
gdb_test "print theA->virt" "\\$\[0-9\]* = &A::virt\\((void|)\\)" "print virtual method."
gdb_test "print theA->nonvirt" "\\$\[0-9\]* = &A::nonvirt\\((void|)\\)" "print nonvirtual method."
gdb_test "print theA->virt" \
"\\$\[0-9\]* = {void \\(A \\*\\)} $hex <A::virt\\((void|)\\)>" \
"print virtual method."
gdb_test "print theA->nonvirt" \
"\\$\[0-9\]* = {void \\(A \\*\\)} $hex <A::nonvirt\\((void|)\\)>" \
"print nonvirtual method."
gdb_exit
return 0

View file

@ -1,4 +1,5 @@
# Copyright 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004
# Copyright 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004,
# 2006
# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
@ -217,6 +218,14 @@ proc test_virtual_calls {} {
-re "\\$\[0-9]+ = 102$nl$gdb_prompt $" {
pass "print pEe->D::vg()"
}
-re "\\$\[0-9]+ = 202$nl$gdb_prompt $" {
# To get this result, we have called pEe->*(&D::vg) ().
# That's how GDB interprets this, but it's wrong; in fact
# the explicit D:: means to bypass virtual function lookup,
# and call D::vg as if it were non-virtual. We still have
# to e.g. adjust "this", though.
kfail "gdb/1064" "print pEe->D::vg()"
}
-re "Attempt to take address of value not located in memory.$nl$gdb_prompt $" {
kfail "gdb/1064" "print pEe->D::vg()"
}

View file

@ -1,7 +1,7 @@
/* Language independent support for printing types for GDB, the GNU debugger.
Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998,
1999, 2000, 2001, 2003 Free Software Foundation, Inc.
1999, 2000, 2001, 2003, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@ -257,7 +257,8 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream)
case TYPE_CODE_SET:
case TYPE_CODE_STRING:
case TYPE_CODE_ERROR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_MEMBERPTR:
case TYPE_CODE_METHODPTR:
case TYPE_CODE_METHOD:
case TYPE_CODE_REF:
case TYPE_CODE_NAMESPACE:

View file

@ -1,7 +1,8 @@
/* Perform non-arithmetic operations on values, for GDB.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -97,14 +98,15 @@ static struct value *value_struct_elt_for_reference (struct type *domain,
struct type *curtype,
char *name,
struct type *intype,
int want_address,
enum noside noside);
static struct value *value_namespace_elt (const struct type *curtype,
char *name,
char *name, int want_address,
enum noside noside);
static struct value *value_maybe_namespace_elt (const struct type *curtype,
char *name,
char *name, int want_address,
enum noside noside);
static CORE_ADDR allocate_space_in_inferior (int);
@ -259,6 +261,7 @@ value_cast_pointers (struct type *type, struct value *arg2)
}
/* No superclass found, just change the pointer type. */
arg2 = value_copy (arg2);
deprecated_set_value_type (arg2, type);
arg2 = value_change_enclosing_type (arg2, type);
set_value_pointed_to_offset (arg2, 0); /* pai: chk_val */
@ -366,33 +369,24 @@ value_cast (struct type *type, struct value *arg2)
return value_from_double (type, value_as_double (arg2));
else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM
|| code1 == TYPE_CODE_RANGE)
&& (scalar || code2 == TYPE_CODE_PTR))
&& (scalar || code2 == TYPE_CODE_PTR
|| code2 == TYPE_CODE_MEMBERPTR))
{
LONGEST longest;
if (deprecated_hp_som_som_object_present /* if target compiled by HP aCC */
&& (code2 == TYPE_CODE_PTR))
/* If target compiled by HP aCC. */
if (deprecated_hp_som_som_object_present
&& code2 == TYPE_CODE_MEMBERPTR)
{
unsigned int *ptr;
struct value *retvalp;
switch (TYPE_CODE (TYPE_TARGET_TYPE (type2)))
{
/* With HP aCC, pointers to data members have a bias */
case TYPE_CODE_MEMBER:
retvalp = value_from_longest (type, value_as_long (arg2));
/* force evaluation */
ptr = (unsigned int *) value_contents (retvalp);
*ptr &= ~0x20000000; /* zap 29th bit to remove bias */
return retvalp;
/* While pointers to methods don't really point to a function */
case TYPE_CODE_METHOD:
error (_("Pointers to methods not supported with HP aCC"));
default:
break; /* fall out and go to normal handling */
}
/* With HP aCC, pointers to data members have a bias. */
retvalp = value_from_longest (type, value_as_long (arg2));
/* force evaluation */
ptr = (unsigned int *) value_contents (retvalp);
*ptr &= ~0x20000000; /* zap 29th bit to remove bias */
return retvalp;
}
/* When we cast pointers to integers, we mustn't use
@ -434,11 +428,26 @@ value_cast (struct type *type, struct value *arg2)
}
return value_from_longest (type, longest);
}
else if (code1 == TYPE_CODE_METHODPTR && code2 == TYPE_CODE_INT
&& value_as_long (arg2) == 0)
{
struct value *result = allocate_value (type);
cplus_make_method_ptr (value_contents_writeable (result), 0, 0);
return result;
}
else if (code1 == TYPE_CODE_MEMBERPTR && code2 == TYPE_CODE_INT
&& value_as_long (arg2) == 0)
{
/* The Itanium C++ ABI represents NULL pointers to members as
minus one, instead of biasing the normal case. */
return value_from_longest (type, -1);
}
else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
{
if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
return value_cast_pointers (type, arg2);
arg2 = value_copy (arg2);
deprecated_set_value_type (arg2, type);
arg2 = value_change_enclosing_type (arg2, type);
set_value_pointed_to_offset (arg2, 0); /* pai: chk_val */
@ -940,9 +949,6 @@ value_ind (struct value *arg1)
base_type = check_typedef (value_type (arg1));
if (TYPE_CODE (base_type) == TYPE_CODE_MEMBER)
error (_("not implemented: member types in value_ind"));
/* Allow * on an integer so we can cast it to whatever we want.
This returns an int, which seems like the most C-like thing
to do. "long long" variables are rare enough that
@ -957,9 +963,17 @@ value_ind (struct value *arg1)
/* Get the real type of the enclosing object */
enc_type = check_typedef (value_enclosing_type (arg1));
enc_type = TYPE_TARGET_TYPE (enc_type);
/* Retrieve the enclosing object pointed to */
arg2 = value_at_lazy (enc_type, (value_as_address (arg1)
- value_pointed_to_offset (arg1)));
if (TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_FUNC
|| TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_METHOD)
/* For functions, go through find_function_addr, which knows
how to handle function descriptors. */
arg2 = value_at_lazy (enc_type, find_function_addr (arg1, NULL));
else
/* Retrieve the enclosing object pointed to */
arg2 = value_at_lazy (enc_type, (value_as_address (arg1)
- value_pointed_to_offset (arg1)));
/* Re-adjust type */
deprecated_set_value_type (arg2, TYPE_TARGET_TYPE (base_type));
/* Add embedding info */
@ -1599,9 +1613,6 @@ value_struct_elt (struct value **argp, struct value **args,
t = check_typedef (value_type (*argp));
}
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
error (_("not implemented: member type in value_struct_elt"));
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error (_("Attempt to extract a component of a value that is not a %s."), err);
@ -1798,9 +1809,6 @@ value_find_oload_method_list (struct value **argp, char *method, int offset,
t = check_typedef (value_type (*argp));
}
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
error (_("Not implemented: member type in value_find_oload_lis"));
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error (_("Attempt to extract a component of a value that is not a struct or union"));
@ -2334,9 +2342,6 @@ check_field (struct value *arg1, const char *name)
t = TYPE_TARGET_TYPE (t);
}
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
error (_("not implemented: member type in check_field"));
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error (_("Internal error: `this' is not an aggregate"));
@ -2345,14 +2350,14 @@ check_field (struct value *arg1, const char *name)
}
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
return the appropriate member. This function is used to resolve
user expressions of the form "DOMAIN::NAME". For more details on
what happens, see the comment before
value_struct_elt_for_reference. */
return the appropriate member (or the address of the member, if
WANT_ADDRESS). This function is used to resolve user expressions
of the form "DOMAIN::NAME". For more details on what happens, see
the comment before value_struct_elt_for_reference. */
struct value *
value_aggregate_elt (struct type *curtype,
char *name,
char *name, int want_address,
enum noside noside)
{
switch (TYPE_CODE (curtype))
@ -2360,9 +2365,9 @@ value_aggregate_elt (struct type *curtype,
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
return value_struct_elt_for_reference (curtype, 0, curtype, name, NULL,
noside);
want_address, noside);
case TYPE_CODE_NAMESPACE:
return value_namespace_elt (curtype, name, noside);
return value_namespace_elt (curtype, name, want_address, noside);
default:
internal_error (__FILE__, __LINE__,
_("non-aggregate type in value_aggregate_elt"));
@ -2379,12 +2384,12 @@ value_aggregate_elt (struct type *curtype,
static struct value *
value_struct_elt_for_reference (struct type *domain, int offset,
struct type *curtype, char *name,
struct type *intype,
struct type *intype, int want_address,
enum noside noside)
{
struct type *t = curtype;
int i;
struct value *v;
struct value *v, *result;
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
@ -2402,15 +2407,21 @@ value_struct_elt_for_reference (struct type *domain, int offset,
if (v == NULL)
error (_("static field %s has been optimized out"),
name);
if (want_address)
v = value_addr (v);
return v;
}
if (TYPE_FIELD_PACKED (t, i))
error (_("pointers to bitfield members not allowed"));
return value_from_longest
(lookup_reference_type (lookup_member_type (TYPE_FIELD_TYPE (t, i),
domain)),
offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
if (want_address)
return value_from_longest
(lookup_memberptr_type (TYPE_FIELD_TYPE (t, i), domain),
offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
return allocate_value (TYPE_FIELD_TYPE (t, i));
else
error (_("Cannot reference non-static field \"%s\""), name);
}
}
@ -2461,33 +2472,52 @@ value_struct_elt_for_reference (struct type *domain, int offset,
else
j = 0;
if (TYPE_FN_FIELD_STATIC_P (f, j))
{
struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
0, VAR_DOMAIN, 0, NULL);
if (s == NULL)
return NULL;
if (want_address)
return value_addr (read_var_value (s, 0));
else
return read_var_value (s, 0);
}
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
{
return value_from_longest
(lookup_reference_type
(lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
domain)),
(LONGEST) METHOD_PTR_FROM_VOFFSET (TYPE_FN_FIELD_VOFFSET (f, j)));
if (want_address)
{
result = allocate_value
(lookup_methodptr_type (TYPE_FN_FIELD_TYPE (f, j)));
cplus_make_method_ptr (value_contents_writeable (result),
TYPE_FN_FIELD_VOFFSET (f, j), 1);
}
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
return allocate_value (TYPE_FN_FIELD_TYPE (f, j));
else
error (_("Cannot reference virtual member function \"%s\""),
name);
}
else
{
struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
0, VAR_DOMAIN, 0, NULL);
if (s == NULL)
{
v = 0;
}
return NULL;
v = read_var_value (s, 0);
if (!want_address)
result = v;
else
{
v = read_var_value (s, 0);
#if 0
VALUE_TYPE (v) = lookup_reference_type
(lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
domain));
#endif
result = allocate_value (lookup_methodptr_type (TYPE_FN_FIELD_TYPE (f, j)));
cplus_make_method_ptr (value_contents_writeable (result),
VALUE_ADDRESS (v), 0);
}
return v;
}
return result;
}
}
for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--)
@ -2503,7 +2533,7 @@ value_struct_elt_for_reference (struct type *domain, int offset,
offset + base_offset,
TYPE_BASECLASS (t, i),
name,
intype,
intype, want_address,
noside);
if (v)
return v;
@ -2513,7 +2543,7 @@ value_struct_elt_for_reference (struct type *domain, int offset,
it up that way; this (frequently) works for types nested inside
classes. */
return value_maybe_namespace_elt (curtype, name, noside);
return value_maybe_namespace_elt (curtype, name, want_address, noside);
}
/* C++: Return the member NAME of the namespace given by the type
@ -2521,11 +2551,11 @@ value_struct_elt_for_reference (struct type *domain, int offset,
static struct value *
value_namespace_elt (const struct type *curtype,
char *name,
char *name, int want_address,
enum noside noside)
{
struct value *retval = value_maybe_namespace_elt (curtype, name,
noside);
want_address, noside);
if (retval == NULL)
error (_("No symbol \"%s\" in namespace \"%s\"."), name,
@ -2542,11 +2572,12 @@ value_namespace_elt (const struct type *curtype,
static struct value *
value_maybe_namespace_elt (const struct type *curtype,
char *name,
char *name, int want_address,
enum noside noside)
{
const char *namespace_name = TYPE_TAG_NAME (curtype);
struct symbol *sym;
struct value *result;
sym = cp_lookup_symbol_namespace (namespace_name, name, NULL,
get_selected_block (0), VAR_DOMAIN,
@ -2556,9 +2587,14 @@ value_maybe_namespace_elt (const struct type *curtype,
return NULL;
else if ((noside == EVAL_AVOID_SIDE_EFFECTS)
&& (SYMBOL_CLASS (sym) == LOC_TYPEDEF))
return allocate_value (SYMBOL_TYPE (sym));
result = allocate_value (SYMBOL_TYPE (sym));
else
return value_of_variable (sym, get_selected_block (0));
result = value_of_variable (sym, get_selected_block (0));
if (result && want_address)
result = value_addr (result);
return result;
}
/* Given a pointer value V, find the real (RTTI) type

View file

@ -1090,6 +1090,7 @@ unpack_long (struct type *type, const gdb_byte *valaddr)
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
case TYPE_CODE_MEMBERPTR:
if (nosign)
return extract_unsigned_integer (valaddr, len);
else
@ -1104,9 +1105,6 @@ unpack_long (struct type *type, const gdb_byte *valaddr)
whether we want this to be true eventually. */
return extract_typed_address (valaddr, type);
case TYPE_CODE_MEMBER:
error (_("not implemented: member types in unpack_long"));
default:
error (_("Value can't be converted to integer."));
}
@ -1537,6 +1535,7 @@ retry:
case TYPE_CODE_FLAGS:
case TYPE_CODE_BOOL:
case TYPE_CODE_RANGE:
case TYPE_CODE_MEMBERPTR:
store_signed_integer (value_contents_raw (val), len, num);
break;

View file

@ -1,7 +1,8 @@
/* Definitions for values of C expressions, for GDB.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -345,7 +346,9 @@ extern struct value *value_struct_elt (struct value **argp,
char *err);
extern struct value *value_aggregate_elt (struct type *curtype,
char *name, enum noside noside);
char *name,
int want_address,
enum noside noside);
extern struct value *value_static_field (struct type *type, int fieldno);

View file

@ -2106,7 +2106,6 @@ c_variable_editable (struct varobj *var)
case TYPE_CODE_UNION:
case TYPE_CODE_ARRAY:
case TYPE_CODE_FUNC:
case TYPE_CODE_MEMBER:
case TYPE_CODE_METHOD:
return 0;
break;