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]

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


On Mon, Nov 26, 2001 at 11:39:34PM -0500, Jim Blandy wrote:
> 
> I'm with you on VALUE_OFFSET and VALUE_EMBEDDED_OFFSET.  I'm pretty
> sure VALUE_OFFSET can be eliminated from GDB entirely, with some minor
> changes to the representation of subvalues of registers and
> convenience variables.

Whew.  I'd like to reiterate my comment on VALUE_EMBEDDED_OFFSET.  See
the patch below.

> Can you explain exactly what TYPE_VPTR_FIELDNO means, and how it works
> in heavily derived classes?  What I think you're basically doing there
> is taking the address of the field indicated by TYPE_VPTR_FIELDNO,
> casting that to a void *, and then casting that to the `struct
> gdb_gnu_v3_abi_vtable' type.  I have this vague memory that maybe
> using TYPE_VPTR_FIELDNO correctly would fix that.

The important things to understand, now that I understand them:
 - TYPE_VPTR_FIELDNO is an index into TYPE_VPTR_BASETYPE.  Not into
 any of the other things we try to index with it.
 - value_cast from "pointer to struct" to "struct's base class" is not
 correct.  The comment about value_cast not finding superclasses
 correctly is also not correct.

How does this patch look?  With this patch, every virtual function call
that we think we know how to make (i.e. that we don't hit the "virtual
baseclass botch" that I'll look at with Daniel Berlin's suggestions
tomorrow) is now correct.  We don't call random offsets in the wrong
vtables any more.

I think these fixes also apply to gnu-v2-abi.c.  I'll check tomorrow. 
I'm tired :)

There are some multiple inheritance issues I'm not quite sure of that
I'd like to check, also.  They may require saving a tree of
superclasses rather than an absolute superclass, and while loops
walking/casting up the vptr_basetype chain.  I'll think about it.

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

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

	* values.c (value_primitive_field): Add embedded_offset to the
	address of structure members.
	* gnu-v3-abi.c (gnuv3_rtti_type): Cast to base type before
	attempting to access vtable pointer.  Set using_enc_p if we cast.
	(gnuv3_virtual_fn_field): Call value_cast with structure rather than
	structure pointer.  Cast to base type before attempting to access
	vtable pointer.

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 06:57:48
@@ -194,6 +194,7 @@ gnuv3_rtti_type (struct value *value,
   const char *class_name;
   struct symbol *class_symbol;
   struct type *run_time_type;
+  struct type *base_type;
   LONGEST offset_to_top;
 
   /* We only have RTTI for class objects.  */
@@ -206,8 +207,18 @@ gnuv3_rtti_type (struct value *value,
   if (TYPE_VPTR_FIELDNO (value_type) == -1)
     return NULL;
 
+  if (using_enc_p)
+    *using_enc_p = 0;
+
   /* 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.  */
+  base_type = check_typedef (TYPE_VPTR_BASETYPE (value_type));
+  if (value_type != base_type)
+    {
+      value = value_cast (base_type, value);
+      if (using_enc_p)
+	*using_enc_p = 1;
+    }
   vtable_address
     = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (value_type)));
   vtable = value_at_lazy (vtable_type,
@@ -260,8 +271,6 @@ gnuv3_rtti_type (struct value *value,
                    >= TYPE_LENGTH (run_time_type)));
   if (top_p)
     *top_p = - offset_to_top;
-  if (using_enc_p)
-    *using_enc_p = 0;
 
   return run_time_type;
 }
@@ -303,15 +312,17 @@ gnuv3_virtual_fn_field (struct value **v
      function, cast our value to that baseclass.  This takes care of
      any necessary `this' adjustments.  */
   if (vfn_base != value_type)
-    /* It would be nicer to simply cast the value to the appropriate
-       base class (and I think that is supposed to be legal), but
-       value_cast only does the right magic when casting pointers.  */
-    value = value_ind (value_cast (vfn_base, value_addr (value)));
+    value = value_cast (vfn_base, value);
 
   /* Now value is an object of the appropriate base type.  Fetch its
      virtual table.  */
+  /* It might be possible to do this cast at the same time as the above.
+     Does multiple inheritance affect this?  */
+  if (TYPE_VPTR_BASETYPE (vfn_base) != vfn_base)
+    value = value_cast (TYPE_VPTR_BASETYPE (vfn_base), value);
   vtable_address
     = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (vfn_base)));
+
   vtable = value_at_lazy (vtable_type,
                           vtable_address - vtable_address_point_offset (),
                           VALUE_BFD_SECTION (value));
Index: values.c
===================================================================
RCS file: /cvs/src/src/gdb/values.c,v
retrieving revision 1.27
diff -u -p -r1.27 values.c
--- values.c	2001/11/09 16:41:50	1.27
+++ values.c	2001/11/27 06:57:50
@@ -929,7 +929,8 @@ value_primitive_field (register value_pt
 	memcpy (VALUE_CONTENTS_RAW (v),
 		VALUE_CONTENTS_RAW (arg1) + offset,
 		TYPE_LENGTH (type));
-      VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset;
+      VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset
+			 + VALUE_EMBEDDED_OFFSET (arg1);
     }
   VALUE_LVAL (v) = VALUE_LVAL (arg1);
   if (VALUE_LVAL (arg1) == lval_internalvar)


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