This is the mail archive of the gdb-patches@sourceware.org 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]

FYI: fix casting bug


I'm checking this in.

This fixes a bug reported in Red Hat bugzilla:

    https://bugzilla.redhat.com/show_bug.cgi?id=560741

The bug is that downcasting gives the wrong result in some cases.  Not
only were the pointers offset incorrectly, but this also manifested as
an inability to find a field in one case.

I traced this down to some code in value_cast_structs that was commented
as not working in the presence of virtual base classes.

This patch fixes the bug by first trying to use the RTTI type when
downcasting.

Built and regtested on x86-64 (compile farm).
New test case included.

Tom

2010-02-02  Tom Tromey  <tromey@redhat.com>

	* valops.c (value_cast_structs): Try downcasting using the RTTI
	type.

2010-02-02  Tom Tromey  <tromey@redhat.com>

	* gdb.cp/virtbase.exp: Add regression tests.
	* gdb.cp/virtbase.cc (RHA, RHB, RHC): New classes.
	(main): Instantiate RHC.

Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.234
diff -u -r1.234 valops.c
--- valops.c	2 Feb 2010 16:45:16 -0000	1.234
+++ valops.c	2 Feb 2010 23:31:33 -0000
@@ -250,10 +250,33 @@
 
   /* Downcasting: look in the type of the target to see if it contains the
      type of the source as a superclass.  If so, we'll need to
-     offset the pointer rather than just change its type.
-     FIXME: This fails silently with virtual inheritance.  */
+     offset the pointer rather than just change its type.  */
   if (TYPE_NAME (t2) != NULL)
     {
+      /* Try downcasting using the run-time type of the value.  */
+      int full, top, using_enc;
+      struct type *real_type;
+
+      real_type = value_rtti_type (v2, &full, &top, &using_enc);
+      if (real_type)
+	{
+	  v = value_full_object (v2, real_type, full, top, using_enc);
+	  v = value_at_lazy (real_type, value_address (v));
+
+	  /* We might be trying to cast to the outermost enclosing
+	     type, in which case search_struct_field won't work.  */
+	  if (TYPE_NAME (real_type) != NULL
+	      && !strcmp (TYPE_NAME (real_type), TYPE_NAME (t1)))
+	    return v;
+
+	  v = search_struct_field (type_name_no_tag (t2), v, 0, real_type, 1);
+	  if (v)
+	    return v;
+	}
+
+      /* Try downcasting using information from the destination type
+	 T2.  This wouldn't work properly for classes with virtual
+	 bases, but those were handled above.  */
       v = search_struct_field (type_name_no_tag (t2),
 			       value_zero (t1, not_lval), 0, t1, 1);
       if (v)
Index: testsuite/gdb.cp/virtbase.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/virtbase.cc,v
retrieving revision 1.1
diff -u -r1.1 virtbase.cc
--- testsuite/gdb.cp/virtbase.cc	2 Feb 2010 16:45:17 -0000	1.1
+++ testsuite/gdb.cp/virtbase.cc	2 Feb 2010 23:31:34 -0000
@@ -46,12 +46,44 @@
 
 class E:B,D{};
 
+// These classes are for another regression test, from
+// https://bugzilla.redhat.com/show_bug.cgi?id=560741
+
+class RHA
+{
+public:
+  RHA() : mA(0xaaaaaaaa) {}
+  virtual void a() = 0;  
+  int mA;
+};
+
+class RHB
+{
+public:
+  RHB() : mB(0xbbbbbbbb) {}
+  virtual void b() = 0;
+  int mB;
+};
+
+class RHC : public RHA,
+	  public RHB
+{
+public:
+  RHC() : RHA(), RHB() {}
+  virtual void a() {}
+  virtual void b() {}
+};
+
+
+
+
 int main() {
   ph::Derived tst;
   tst.get_y();
   tst.get_z();
 
   E *e = new E;
+  RHB *b = new RHC();
 
   return 0;			// breakpoint 3
 }
Index: testsuite/gdb.cp/virtbase.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/virtbase.exp,v
retrieving revision 1.1
diff -u -r1.1 virtbase.exp
--- testsuite/gdb.cp/virtbase.exp	2 Feb 2010 16:45:17 -0000	1.1
+++ testsuite/gdb.cp/virtbase.exp	2 Feb 2010 23:31:34 -0000
@@ -55,3 +55,8 @@
 
 # In PR 9629, we failed to print v correctly here.
 gdb_test "print *(D *) e" " = {<C> = {v = 11}, _vptr.D = $hex}"
+
+# A regression test reported to Red Hat bugzilla, see:
+# https://bugzilla.redhat.com/show_bug.cgi?id=560741
+gdb_test "set print object on" ""
+gdb_test "print/x b->mA" " = 0xaaaaaaaa"


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