PR c++/7173:
authorTom Tromey <tromey@redhat.com>
Mon, 21 May 2012 19:47:54 +0000 (19:47 +0000)
committerTom Tromey <tromey@redhat.com>
Mon, 21 May 2012 19:47:54 +0000 (19:47 +0000)
* 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.

gdb/ChangeLog
gdb/ada-lang.c
gdb/eval.c
gdb/gnu-v3-abi.c
gdb/infcall.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/inherit.exp
gdb/valops.c
gdb/value.h

index 5fd2f3c44a3e4d68cce79c575ab6cd3d3d8d6474..c12d3fd5c2f545dbeb0895ca369d0e1818f1779b 100644 (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.
index 72d47684399eeafe1bde8c25ffcc48126d36e150..1fac31656fe1397099fb8719010b89889038a899 100644 (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);
index 59d8bff88e2d29cbb03f70e2f8cd85f9ea3241af..7f1dfac0cc70f3b4cf44dfb62fc989c9df655025 100644 (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);
 
index 42b939d4192c218df793dd1756ee1cca3ce280ae..3a83e2d48b5424588cfe55fdae81aeaf63bb6440 100644 (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
index 4ace08b7a7aa4ee1c8937e42bd7f8d04f2c98cf2..8d7c621d763133ff295d055243b408a5acde46fe 100644 (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
index 8e36471ff93b49ea6c4fdac508af859533d1b7d3..21809b885bb360223bef586ec033d53ed017e728 100644 (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
index 7e2e871e9e0abe1aa97d6ee81de1661e09bbcb5b..7a590533572e05be00c311030cb4278ac5ce22b5 100644 (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"
index ee450e3c8f520126a0b3a56fee8e165eefd9d76d..feb47f543b03ee8770b0857bc3c3b74d5409bb72 100644 (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
index 25013d8855c668c526c6dd00feb9e7990f31c848..b630fc7245528a478142720d66dc2e42af934e83 100644 (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);