PR c++/7173:

* gnu-v3-abi.c (gnuv3_baseclass_offset): Return early for Java
	types.
	* value.h (value_cast_pointers): Update.
	* valops.c (value_cast_pointers): Add 'subclass_check' argument.
	(value_cast): Update.
	(update_search_result): New function.
	(do_search_struct_field): New, from search_struct_field.  Check
	for ambiguous results.
	(search_struct_field): Rewrite.
	* infcall.c (value_arg_coerce): Update.
	* eval.c (evaluate_subexp_standard) <STRUCTOP_MEMBER>: Use
	value_cast_pointers.
	* ada-lang.c (ada_convert_actual): Update.
testsuite
	* gdb.cp/inherit.exp (test_print_mi_members): Expect errors.
	Remove kfails.
	(test_print_mi_member_types): Likewise.
This commit is contained in:
Tom Tromey 2012-05-21 19:47:54 +00:00
parent 248537e34b
commit b1af9e9750
9 changed files with 139 additions and 109 deletions

View file

@ -1,3 +1,20 @@
2012-05-21 Tom Tromey <tromey@redhat.com>
PR c++/7173:
* gnu-v3-abi.c (gnuv3_baseclass_offset): Return early for Java
types.
* value.h (value_cast_pointers): Update.
* valops.c (value_cast_pointers): Add 'subclass_check' argument.
(value_cast): Update.
(update_search_result): New function.
(do_search_struct_field): New, from search_struct_field. Check
for ambiguous results.
(search_struct_field): Rewrite.
* infcall.c (value_arg_coerce): Update.
* eval.c (evaluate_subexp_standard) <STRUCTOP_MEMBER>: Use
value_cast_pointers.
* ada-lang.c (ada_convert_actual): Update.
2012-05-21 Tom Tromey <tromey@redhat.com>
* macroexp.c (macro_stringify): Terminate the string.

View file

@ -4139,7 +4139,7 @@ ada_convert_actual (struct value *actual, struct type *formal_type0)
}
else
return actual;
return value_cast_pointers (formal_type, result);
return value_cast_pointers (formal_type, result, 0);
}
else if (TYPE_CODE (actual_type) == TYPE_CODE_PTR)
return ada_value_ind (actual);

View file

@ -2047,8 +2047,8 @@ evaluate_subexp_standard (struct type *expect_type,
case TYPE_CODE_MEMBERPTR:
/* Now, convert these values to an address. */
arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
arg1);
arg1 = value_cast_pointers (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
arg1, 1);
mem_offset = value_as_long (arg2);

View file

@ -430,8 +430,9 @@ gnuv3_baseclass_offset (struct type *type, int index,
ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
/* If it isn't a virtual base, this is easy. The offset is in the
type definition. */
if (!BASETYPE_VIA_VIRTUAL (type, index))
type definition. Likewise for Java, which doesn't really have
virtual inheritance in the C++ sense. */
if (!BASETYPE_VIA_VIRTUAL (type, index) || TYPE_CPLUS_REALLY_JAVA (type))
return TYPE_BASECLASS_BITPOS (type, index) / 8;
/* To access a virtual base, we need to use the vbase offset stored in

View file

@ -159,7 +159,7 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
struct value *new_value;
if (TYPE_CODE (arg_type) == TYPE_CODE_REF)
return value_cast_pointers (type, arg);
return value_cast_pointers (type, arg, 0);
/* Cast the value to the reference's target type, and then
convert it back to a reference. This will issue an error

View file

@ -1,3 +1,9 @@
2012-05-21 Tom Tromey <tromey@redhat.com>
* gdb.cp/inherit.exp (test_print_mi_members): Expect errors.
Remove kfails.
(test_print_mi_member_types): Likewise.
2012-05-21 Tom Tromey <tromey@redhat.com>
* gdb.base/callfuncs.exp (do_function_calls): Update for 'set

View file

@ -321,25 +321,11 @@ proc test_print_mi_members {} {
# Print all members of g_D.
#
# g_D.A::a and g_D.A::x are ambiguous member accesses, and gdb
# should detect these. There are no ways to PASS these tests
# because I don't know what the gdb message will be. -- chastain
# 2004-01-27.
set name "print g_D.A::a"
gdb_test_multiple "print g_D.A::a" $name {
-re "$vhn = (15|11)$nl$gdb_prompt $" {
kfail "gdb/68" "print g_D.A::a"
}
}
set name "print g_D.A::x"
gdb_test_multiple "print g_D.A::x" $name {
-re "$vhn = (16|12)$nl$gdb_prompt $" {
kfail "gdb/68" "print g_D.A::x"
}
}
# g_D.A::a and g_D.A::x are ambiguous member accesses.
gdb_test "print g_D.A::a" "base class 'A' is ambiguous in type 'D'"
gdb_test "print g_D.C::a" "$vhn = 15"
gdb_test "print g_D.B::a" "$vhn = 11"
gdb_test "print g_D.A::x" "base class 'A' is ambiguous in type 'D'"
gdb_test "print g_D.B::b" "$vhn = 13"
gdb_test "print g_D.B::x" "$vhn = 14"
gdb_test "print g_D.C::c" "$vhn = 17"
@ -350,20 +336,8 @@ proc test_print_mi_members {} {
# Print all members of g_E.
# g_E.A::a and g_E.A::x are ambiguous.
set name "print g_E.A::a"
gdb_test_multiple "print g_E.A::a" $name {
-re "$vhn = (21|25)$nl$gdb_prompt $" {
kfail "gdb/68" "print g_E.A::a"
}
}
set name "print g_E.A::x"
gdb_test_multiple "print g_E.A::x" $name {
-re "$vhn = (26|22)$nl$gdb_prompt $" {
kfail "gdb/68" "print g_E.A::x"
}
}
gdb_test "print g_E.A::a" "base class 'A' is ambiguous in type 'E'"
gdb_test "print g_E.A::x" "base class 'A' is ambiguous in type 'E'"
gdb_test "print g_E.B::b" "$vhn = 23"
gdb_test "print g_E.B::x" "$vhn = 24"
gdb_test "print g_E.C::c" "$vhn = 27"
@ -406,25 +380,10 @@ proc test_print_mi_member_types {} {
# Print all members of g_D.
#
# g_D.A::a and g_D.A::x are ambiguous member accesses, and gdb
# should detect these. There are no ways to PASS these tests
# because I don't know what the gdb message will be. -- chastain
# 2004-01-27.
set name "ptype g_D.A::a"
gdb_test_multiple "ptype g_D.A::a" $name {
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_D.A::a"
}
}
set name "ptype g_D.A::x"
gdb_test_multiple "ptype g_D.A::x" $name {
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_D.A::x"
}
}
# g_D.A::a and g_D.A::x are ambiguous member accesses.
gdb_test "ptype g_D.A::a" "base class 'A' is ambiguous in type 'D'"
gdb_test "ptype g_D.A::x" "base class 'A' is ambiguous in type 'D'"
gdb_test "ptype g_D.B::b" "type = int"
gdb_test "ptype g_D.B::x" "type = int"
gdb_test "ptype g_D.C::c" "type = int"
@ -435,20 +394,8 @@ proc test_print_mi_member_types {} {
# Print all members of g_E.
# g_E.A::a and g_E.A::x are ambiguous.
set name "ptype g_E.A::a"
gdb_test_multiple "ptype g_E.A::a" $name {
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_E.A::a"
}
}
set name "ptype g_E.A::x"
gdb_test_multiple "ptype g_E.A::x" $name {
-re "type = int$nl$gdb_prompt $" {
kfail "gdb/68" "ptype g_E.A::x"
}
}
gdb_test "ptype g_E.A::a" "base class 'A' is ambiguous in type 'E'"
gdb_test "ptype g_E.A::x" "base class 'A' is ambiguous in type 'E'"
gdb_test "ptype g_E.B::b" "type = int"
gdb_test "ptype g_E.B::x" "type = int"
gdb_test "ptype g_E.C::c" "type = int"

View file

@ -301,10 +301,14 @@ value_cast_structs (struct type *type, struct value *v2)
/* Cast one pointer or reference type to another. Both TYPE and
the type of ARG2 should be pointer types, or else both should be
reference types. Returns the new pointer or reference. */
reference types. If SUBCLASS_CHECK is non-zero, this will force a
check to see whether TYPE is a superclass of ARG2's type. If
SUBCLASS_CHECK is zero, then the subclass check is done only when
ARG2 is itself non-zero. Returns the new pointer or reference. */
struct value *
value_cast_pointers (struct type *type, struct value *arg2)
value_cast_pointers (struct type *type, struct value *arg2,
int subclass_check)
{
struct type *type1 = check_typedef (type);
struct type *type2 = check_typedef (value_type (arg2));
@ -313,7 +317,7 @@ value_cast_pointers (struct type *type, struct value *arg2)
if (TYPE_CODE (t1) == TYPE_CODE_STRUCT
&& TYPE_CODE (t2) == TYPE_CODE_STRUCT
&& !value_logical_not (arg2))
&& (subclass_check || !value_logical_not (arg2)))
{
struct value *v2;
@ -568,7 +572,7 @@ value_cast (struct type *type, struct value *arg2)
else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
{
if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
return value_cast_pointers (type, arg2);
return value_cast_pointers (type, arg2, 0);
arg2 = value_copy (arg2);
deprecated_set_value_type (arg2, type);
@ -1976,17 +1980,41 @@ typecmp (int staticp, int varargs, int nargs,
return i + 1;
}
/* Helper function used by value_struct_elt to recurse through
baseclasses. Look for a field NAME in ARG1. Adjust the address of
ARG1 by OFFSET bytes, and search in it assuming it has (class) type
TYPE. If found, return value, else return NULL.
/* Helper class for do_search_struct_field that updates *RESULT_PTR
and *LAST_BOFFSET, and possibly throws an exception if the field
search has yielded ambiguous results. */
If LOOKING_FOR_BASECLASS, then instead of looking for struct
fields, look for a baseclass named NAME. */
static void
update_search_result (struct value **result_ptr, struct value *v,
int *last_boffset, int boffset,
const char *name, struct type *type)
{
if (v != NULL)
{
if (*result_ptr != NULL
/* The result is not ambiguous if all the classes that are
found occupy the same space. */
&& *last_boffset != boffset)
error (_("base class '%s' is ambiguous in type '%s'"),
name, TYPE_SAFE_NAME (type));
*result_ptr = v;
*last_boffset = boffset;
}
}
static struct value *
search_struct_field (const char *name, struct value *arg1, int offset,
struct type *type, int looking_for_baseclass)
/* A helper for search_struct_field. This does all the work; most
arguments are as passed to search_struct_field. The result is
stored in *RESULT_PTR, which must be initialized to NULL.
OUTERMOST_TYPE is the type of the initial type passed to
search_struct_field; this is used for error reporting when the
lookup is ambiguous. */
static void
do_search_struct_field (const char *name, struct value *arg1, int offset,
struct type *type, int looking_for_baseclass,
struct value **result_ptr,
int *last_boffset,
struct type *outermost_type)
{
int i;
int nbases;
@ -2012,12 +2040,9 @@ search_struct_field (const char *name, struct value *arg1, int offset,
name);
}
else
{
v = value_primitive_field (arg1, offset, i, type);
if (v == 0)
error (_("there is no field named %s"), name);
}
return v;
v = value_primitive_field (arg1, offset, i, type);
*result_ptr = v;
return;
}
if (t_field_name
@ -2042,7 +2067,7 @@ search_struct_field (const char *name, struct value *arg1, int offset,
represented as a struct, with a member for each
<variant field>. */
struct value *v;
struct value *v = NULL;
int new_offset = offset;
/* This is pretty gross. In G++, the offset in an
@ -2056,18 +2081,23 @@ search_struct_field (const char *name, struct value *arg1, int offset,
&& TYPE_FIELD_BITPOS (field_type, 0) == 0))
new_offset += TYPE_FIELD_BITPOS (type, i) / 8;
v = search_struct_field (name, arg1, new_offset,
field_type,
looking_for_baseclass);
do_search_struct_field (name, arg1, new_offset,
field_type,
looking_for_baseclass, &v,
last_boffset,
outermost_type);
if (v)
return v;
{
*result_ptr = v;
return;
}
}
}
}
for (i = 0; i < nbases; i++)
{
struct value *v;
struct value *v = NULL;
struct type *basetype = check_typedef (TYPE_BASECLASS (type, i));
/* If we are looking for baseclasses, this is what we get when
we hit them. But it could happen that the base part's member
@ -2077,10 +2107,10 @@ search_struct_field (const char *name, struct value *arg1, int offset,
&& (strcmp_iw (name,
TYPE_BASECLASS_NAME (type,
i)) == 0));
int boffset = value_embedded_offset (arg1) + offset;
if (BASETYPE_VIA_VIRTUAL (type, i))
{
int boffset;
struct value *v2;
boffset = baseclass_offset (type, i,
@ -2116,22 +2146,51 @@ search_struct_field (const char *name, struct value *arg1, int offset,
}
if (found_baseclass)
return v2;
v = search_struct_field (name, v2, 0,
TYPE_BASECLASS (type, i),
looking_for_baseclass);
v = v2;
else
{
do_search_struct_field (name, v2, 0,
TYPE_BASECLASS (type, i),
looking_for_baseclass,
result_ptr, last_boffset,
outermost_type);
}
}
else if (found_baseclass)
v = value_primitive_field (arg1, offset, i, type);
else
v = search_struct_field (name, arg1,
offset + TYPE_BASECLASS_BITPOS (type,
i) / 8,
basetype, looking_for_baseclass);
if (v)
return v;
{
do_search_struct_field (name, arg1,
offset + TYPE_BASECLASS_BITPOS (type,
i) / 8,
basetype, looking_for_baseclass,
result_ptr, last_boffset,
outermost_type);
}
update_search_result (result_ptr, v, last_boffset,
boffset, name, outermost_type);
}
return NULL;
}
/* Helper function used by value_struct_elt to recurse through
baseclasses. Look for a field NAME in ARG1. Adjust the address of
ARG1 by OFFSET bytes, and search in it assuming it has (class) type
TYPE. If found, return value, else return NULL.
If LOOKING_FOR_BASECLASS, then instead of looking for struct
fields, look for a baseclass named NAME. */
static struct value *
search_struct_field (const char *name, struct value *arg1, int offset,
struct type *type, int looking_for_baseclass)
{
struct value *result = NULL;
int boffset = 0;
do_search_struct_field (name, arg1, offset, type, looking_for_baseclass,
&result, &boffset, type);
return result;
}
/* Helper function used by value_struct_elt to recurse through

View file

@ -669,7 +669,7 @@ extern struct type *value_rtti_indirect_type (struct value *, int *, int *,
extern struct value *value_full_object (struct value *, struct type *, int,
int, int);
extern struct value *value_cast_pointers (struct type *, struct value *);
extern struct value *value_cast_pointers (struct type *, struct value *, int);
extern struct value *value_cast (struct type *type, struct value *arg2);