This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA/c++] Fix printing classes with virtual base classes


Whew.  Finally tracked this down.

The problem is in the layout of a class whose base class has a virtual
table.  Given:

class Bar {
  virtual int thunk ();
};

class Foo : public Bar {
  int test;
};

A Foo will look like this:

   /-----------------------\
   | Foo       |    test   |
   \-----------------------/

Its own vptr will be conveniently Foo's vptr.  But the type of Bar's field 0
(which is marked as having the vptr in it) is Foo, not some pointer type. 
If I explicitly cast to pointer, everything works more-or-less OK.

I'm pretty sure of the C++ side of this.  If there's a more appropriate
function for doing the cast to pointer I'd love to hear about it; otherwise,
OK to commit?

Can't really tell what effect it has on the testsuite, as just about
everything else in the relevant tests is failing anyway.  I have a few more
low-hanging bugs in this area that I'm debugging now.

-- 
Daniel Jacobowitz                           Carnegie Mellon University
MontaVista Software                         Debian GNU/Linux Developer

2001-11-26  Daniel Jacobowitz  <drow@mvista.com>

	* gnu-v3-abi.c (gnuv3_rtti_type): Explicitly cast
	the vtable pointer to a pointer before loading it.
	(gnuv3_virtual_fn_field): Likewise.

Index: gnu-v3-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v
retrieving revision 1.4
diff -u -p -r1.4 gnu-v3-abi.c
--- gnu-v3-abi.c	2001/10/16 01:58:07	1.4
+++ gnu-v3-abi.c	2001/11/27 00:21:44
@@ -188,7 +188,7 @@ gnuv3_rtti_type (struct value *value,
   struct type *vtable_type = gdbarch_data (vtable_type_gdbarch_data);
   struct type *value_type = check_typedef (VALUE_TYPE (value));
   CORE_ADDR vtable_address;
-  struct value *vtable;
+  struct value *vtable, *vtable_addr_value;
   struct minimal_symbol *vtable_symbol;
   const char *vtable_symbol_name;
   const char *class_name;
@@ -207,9 +207,17 @@ gnuv3_rtti_type (struct value *value,
     return NULL;
 
   /* Fetch VALUE's virtual table pointer, and tweak it to point at
-     an instance of our imaginary gdb_gnu_v3_abi_vtable structure.   */
+     an instance of our imaginary gdb_gnu_v3_abi_vtable structure.
+     The type of the field may not be a pointer type.  In a derived
+     class with a virtual base class, it will be the type of the base
+     class.  Thus we need to cast.  */
+  vtable_addr_value =
+    value_at (builtin_type_void_data_ptr,
+	      VALUE_ADDRESS (value_field (value,
+					  TYPE_VPTR_FIELDNO (value_type))),
+	      VALUE_BFD_SECTION (value));
   vtable_address
-    = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (value_type)));
+    = value_as_address (vtable_addr_value);
   vtable = value_at_lazy (vtable_type,
                           vtable_address - vtable_address_point_offset (),
                           VALUE_BFD_SECTION (value));
@@ -277,7 +285,7 @@ gnuv3_virtual_fn_field (struct value **v
   struct type *value_type = check_typedef (VALUE_TYPE (value));
   struct type *vfn_base;
   CORE_ADDR vtable_address;
-  struct value *vtable;
+  struct value *vtable, *vtable_addr_value;
   struct value *vfn;
 
   /* Some simple sanity checks.  */
@@ -309,9 +317,16 @@ gnuv3_virtual_fn_field (struct value **v
     value = value_ind (value_cast (vfn_base, value_addr (value)));
 
   /* Now value is an object of the appropriate base type.  Fetch its
-     virtual table.  */
+     virtual table.  As in gnuv3_rtti_type, the type of the field may
+     not be a pointer type.  In a derived class with a virtual base class,
+     it will be the type of the base class.  Thus we need to cast.  */
+  vtable_addr_value =
+    value_at (builtin_type_void_data_ptr,
+	      VALUE_ADDRESS (value_field (value,
+					  TYPE_VPTR_FIELDNO (vfn_base))),
+	      VALUE_BFD_SECTION (value));
   vtable_address
-    = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (vfn_base)));
+    = value_as_address (vtable_addr_value);
   vtable = value_at_lazy (vtable_type,
                           vtable_address - vtable_address_point_offset (),
                           VALUE_BFD_SECTION (value));


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]