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]

Re: [patch] fix for c++/2416


Daniel Jacobowitz wrote:
On Wed, Feb 27, 2008 at 04:08:08PM -0500, Aleksandar Ristovski wrote:
Another thing that confuses me is such a special treatment for references to something... in my mind, (talking about C++) we should be able to internally treat them as pointers to that something.

I take this back, it looks like we do treat them the way I thought it should.



value_as_address on a reference is supposed to referenced value as an address, not the pointer value stored in the reference. It's probably the caller of value_as_address which is mistaken.

This was the real clue! Thank you for the feedback! Indeed, it appears calling value_as_address is not needed. Once we dereference PTR/REF, we get value representing "the real thing". From there we can fetch address for calculating the offset, and then all works fine.

See revisited diff (attached). Also, please find attached the testcase diff, I added check for reference casting. Do I need to provide change log for tests too?

NOTE: value_as_address does *not* behave as you described, if passed in a REF to STRUCT, it will coerce_ref, that is ok, but then it will pass coerced value to unpack_long which doesn't know what to do with a STRUCT (which is why I had that confusing code you and Michael complained about).


2008-02-28 Aleksandar Ristovski <aristovski@qnx.com>


	* eval.c (evaluate_subexp_standard): UNOP_CAST use
	value_cast_pointers when casting reference to reference. Print
	error when reference/non-reference mix.
	* valops.c (value_cast_pointers): Use coerced value to determine
	address when downcasting.

Index: gdb/eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.80
diff -u -p -r1.80 eval.c
--- gdb/eval.c	4 Feb 2008 00:23:04 -0000	1.80
+++ gdb/eval.c	28 Feb 2008 18:47:40 -0000
@@ -1985,8 +1985,18 @@ evaluate_subexp_standard (struct type *e
       arg1 = evaluate_subexp (type, exp, pos, noside);
       if (noside == EVAL_SKIP)
 	goto nosideret;
-      if (type != value_type (arg1))
-	arg1 = value_cast (type, arg1);
+      if (type != value_type (arg1)) 
+	{
+	  if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_REF
+	      && TYPE_CODE (type) == TYPE_CODE_REF)
+	    arg1 = value_cast_pointers (type, arg1);
+	  else if (TYPE_CODE (value_type (arg1)) != TYPE_CODE_REF
+		   && TYPE_CODE (type) != TYPE_CODE_REF)
+	    arg1 = value_cast (type, arg1);
+	  else /* We can not do much here.  */
+	    error (_("Attempt to cast to reference type from non-reference "\
+		     "type or vice versa."));
+	}
       return arg1;
 
     case UNOP_MEMVAL:
Index: gdb/valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.183
diff -u -p -r1.183 valops.c
--- gdb/valops.c	4 Feb 2008 00:23:04 -0000	1.183
+++ gdb/valops.c	28 Feb 2008 18:47:50 -0000
@@ -199,6 +199,7 @@ allocate_space_in_inferior (int len)
 struct value *
 value_cast_pointers (struct type *type, struct value *arg2)
 {
+  struct type *type1 = check_typedef (type);
   struct type *type2 = check_typedef (value_type (arg2));
   struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type));
   struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2));
@@ -208,18 +209,20 @@ value_cast_pointers (struct type *type, 
       && !value_logical_not (arg2))
     {
       struct value *v;
+      struct value *v2; /* Real thing, dereferenced PTR/REF.  */
 
-      /* Look in the type of the source to see if it contains the
+      if (TYPE_CODE (type2) == TYPE_CODE_REF)
+	v2 = coerce_ref (arg2);
+      else
+	v2 = value_ind (arg2);
+      gdb_assert (TYPE_CODE (value_type (v2)) == TYPE_CODE_STRUCT
+		  && !!"Why did coercion fail?");
+
+      /* Upcasting: look in the type of the source to see if it contains the
 	 type of the target as a superclass.  If so, we'll need to
 	 offset the pointer rather than just change its type.  */
       if (TYPE_NAME (t1) != NULL)
 	{
-	  struct value *v2;
-
-	  if (TYPE_CODE (type2) == TYPE_CODE_REF)
-	    v2 = coerce_ref (arg2);
-	  else
-	    v2 = value_ind (arg2);
 	  v = search_struct_field (type_name_no_tag (t1),
 				   v2, 0, t2, 1);
 	  if (v)
@@ -230,7 +233,7 @@ value_cast_pointers (struct type *type, 
 	    }
 	}
 
-      /* Look in the type of the target to see if it contains the
+      /* 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.  */
@@ -240,11 +243,12 @@ value_cast_pointers (struct type *type, 
 				   value_zero (t1, not_lval), 0, t1, 1);
 	  if (v)
 	    {
-	      CORE_ADDR addr2 = value_as_address (arg2);
+	      /* Downcasting is possible (t1 is superclass of v2).  */
+	      CORE_ADDR addr2 = VALUE_ADDRESS (v2);
 	      addr2 -= (VALUE_ADDRESS (v)
 			+ value_offset (v)
 			+ value_embedded_offset (v));
-	      return value_from_pointer (type, addr2);
+	      return value_from_pointer (type1, addr2);
 	    }
 	}
     }
Index: gdb/testsuite/gdb.cp/casts.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/casts.cc,v
retrieving revision 1.1
diff -u -p -r1.1 casts.cc
--- gdb/testsuite/gdb.cp/casts.cc	23 Aug 2003 03:55:59 -0000	1.1
+++ gdb/testsuite/gdb.cp/casts.cc	28 Feb 2008 18:48:29 -0000
@@ -15,6 +15,8 @@ main (int argc, char **argv)
 {
   A *a = new B(42, 1729);
   B *b = (B *) a;
+  A &ar = *b;
+  B &br = (B&)ar;
 
   return 0;  /* breakpoint spot: casts.exp: 1 */
 }
Index: gdb/testsuite/gdb.cp/casts.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/casts.exp,v
retrieving revision 1.6
diff -u -p -r1.6 casts.exp
--- gdb/testsuite/gdb.cp/casts.exp	1 Jan 2008 22:53:19 -0000	1.6
+++ gdb/testsuite/gdb.cp/casts.exp	28 Feb 2008 18:48:29 -0000
@@ -80,3 +80,20 @@ gdb_test "print * (B *) a" ".* = {<A> = 
 # the dereference.
 gdb_test "print * b" ".* = {<A> = {a = 42}, b = 1729}" \
     "let compiler cast base class pointer to derived class pointer"
+
+# Check upcasting (it is trivial but still). 
+gdb_test "print * (A *) b" ".* = {a = 42}" \
+    "cast derived class pointer to base class pointer"
+
+# Casting References.
+# Check upcasting. 
+gdb_test "print (A &) br" ".* = .A &.* {a = 42}" \
+    "cast derived class reference to base class reference"
+
+# Check downcasting.
+gdb_test "print (B &) ar" ".* = .B.* {<A> = {a = 42}, b = 1729}" \
+    "cast base class reference to derived class reference"
+
+# Check compiler casting
+gdb_test "print br" ".* = .B.* {<A> = {a = 42}, b = 1729}" \
+    "let compiler cast base class reference to derived class reference"

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