summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2012-05-21 19:47:50 +0000
committerTom Tromey <tromey@redhat.com>2012-05-21 19:47:50 +0000
commitc69ef372db94854dd1d77034692380c36826d32c (patch)
tree5c3e739f946de48f81d73fbb016ea2703bd49dcb /gdb
parent595d240f3ac8cddd8d730ef30b2521474855b5ef (diff)
downloadgdb-c69ef372db94854dd1d77034692380c36826d32c.tar.gz
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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/ada-lang.c2
-rw-r--r--gdb/eval.c4
-rw-r--r--gdb/gnu-v3-abi.c5
-rw-r--r--gdb/infcall.c2
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.cp/inherit.exp77
-rw-r--r--gdb/valops.c133
-rw-r--r--gdb/value.h2
9 files changed, 139 insertions, 109 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5fd2f3c44a3..c12d3fd5c2f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,22 @@
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.
2012-05-20 Jan Kratochvil <jan.kratochvil@redhat.com>
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 72d47684399..1fac31656fe 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -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);
diff --git a/gdb/eval.c b/gdb/eval.c
index 59d8bff88e2..7f1dfac0cc7 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -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);
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 42b939d4192..3a83e2d48b5 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -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
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 4ace08b7a7a..8d7c621d763 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -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
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 8e36471ff93..21809b885bb 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,11 @@
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
print symbol' change.
diff --git a/gdb/testsuite/gdb.cp/inherit.exp b/gdb/testsuite/gdb.cp/inherit.exp
index 7e2e871e9e0..7a590533572 100644
--- a/gdb/testsuite/gdb.cp/inherit.exp
+++ b/gdb/testsuite/gdb.cp/inherit.exp
@@ -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"
diff --git a/gdb/valops.c b/gdb/valops.c
index ee450e3c8f5..feb47f543b0 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -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
diff --git a/gdb/value.h b/gdb/value.h
index 25013d8855c..b630fc72455 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -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);