* 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,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"));
}