Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Aleksandar Ristovski <aristovski@qnx.com>
To: Daniel Jacobowitz <drow@false.org>
Cc: gdb-patches@sourceware.org
Subject: Re: [patch] fix for c++/2416
Date: Fri, 29 Feb 2008 10:10:00 -0000	[thread overview]
Message-ID: <47C78DD3.4080109@qnx.com> (raw)
In-Reply-To: <20080228191516.GA8975@caradoc.them.org>

[-- Attachment #1: Type: text/plain, Size: 1785 bytes --]

Daniel Jacobowitz wrote:
> On Thu, Feb 28, 2008 at 01:53:13PM -0500, Aleksandar Ristovski wrote:
>> 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?
> 
> The testsuite changes look fine but do need a changelog; that
> goes in testsuite/ChangeLog.

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

	* gdb.cp/casts.cc: Add class reference variables.
	* gdb.cp/casts.exp: New test cases for up/down casting references.


> 
> There's nothing wrong with casting a reference to a non-reference;
> that coerces the reference.  Also you have to beware typedefs.
> 
> 	  enum type_code code1, code2;
> 	  code1 = TYPE_CODE (check_typedef (value_type (arg1)));
> 	  code2 = TYPE_CODE (check_typedef (value_type (arg2)));
> 
> 	  if (code1 == TYPE_CODE_REF && code2 == TYPE_CODE_REF)
> 	    arg1 = value_cast_pointers (type, arg1);
> 	  else if (code1 == TYPE_CODE_REF)
> 	    error (_("Attempt to cast to reference type from non-reference type."));
> 	  else
> 	    arg1 = value_cast (type, arg1);

Allright, then how about this, yet newer and yet more revisited diff? I removed 
changes to eval.c and let it simply call value_cast as it used to. Now 
value_cast knows how to handle references.


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

	* valops.c (value_cast_structs): New function. Cast related
	STRUCT types up/down and return cast value. The body of this
	function comes mostly from value_cast_pointers.
	(value_cast_pointers): Code for actual cast STRUCT-STRUCT moved
	to value_cast_structs. Now value_cast_pointers needs only create
	appropriate reference after using value_cast_structs for actual
	casting.
	(value_cast): Handle references.
	


[-- Attachment #2: valops.c.diff --]
[-- Type: text/plain, Size: 6951 bytes --]

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	29 Feb 2008 04:30:05 -0000
@@ -192,6 +192,62 @@ allocate_space_in_inferior (int len)
   return value_as_long (value_allocate_space_in_inferior (len));
 }
 
+/* Cast struct value VAL to type TYPE and return as a value.
+   Both type and val must be of TYPE_CODE_STRUCT or TYPE_CODE_UNION
+   for this to work. Typedef to one of the codes is permitted.  */
+
+static struct value *
+value_cast_structs (struct type *type, struct value *v2)
+{
+  struct type *t1;
+  struct type *t2;
+  struct value *v;
+
+  gdb_assert (type != NULL && v2 != NULL);
+
+  t1 = check_typedef (type);
+  t2 = check_typedef (value_type (v2));
+
+  /* Check preconditions.  */
+  gdb_assert ((TYPE_CODE (t1) == TYPE_CODE_STRUCT
+	       || TYPE_CODE (t1) == TYPE_CODE_UNION)
+	      && !!"Precondition is that type is of STRUCT or UNION kind.");
+  gdb_assert ((TYPE_CODE (t2) == TYPE_CODE_STRUCT
+	       || TYPE_CODE (t2) == TYPE_CODE_UNION)
+	      && !!"Precondition is that value is of STRUCT or UNION kind");
+
+  /* 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)
+    {
+      v = search_struct_field (type_name_no_tag (t1),
+			       v2, 0, t2, 1);
+      if (v)
+	return v;
+    }
+
+  /* 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.  */
+  if (TYPE_NAME (t2) != NULL)
+    {
+      v = search_struct_field (type_name_no_tag (t2),
+			       value_zero (t1, not_lval), 0, t1, 1);
+      if (v)
+	{
+	  /* 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_at (type, addr2);
+	}
+    }
+  return 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.  */
@@ -199,6 +255,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));
@@ -207,47 +264,23 @@ value_cast_pointers (struct type *type, 
       && TYPE_CODE (t2) == TYPE_CODE_STRUCT
       && !value_logical_not (arg2))
     {
-      struct value *v;
+      struct value *v2;
 
-      /* 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)
+      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?");
+      v2 = value_cast_structs (t1, v2);
+      /* At this point we have what we can have, un-dereference if needed.  */
+      if (v2)
 	{
-	  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)
-	    {
-	      v = value_addr (v);
-	      deprecated_set_value_type (v, type);
-	      return v;
-	    }
-	}
-
-      /* 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.  */
-      if (TYPE_NAME (t2) != NULL)
-	{
-	  v = search_struct_field (type_name_no_tag (t2),
-				   value_zero (t1, not_lval), 0, t1, 1);
-	  if (v)
-	    {
-	      CORE_ADDR addr2 = value_as_address (arg2);
-	      addr2 -= (VALUE_ADDRESS (v)
-			+ value_offset (v)
-			+ value_embedded_offset (v));
-	      return value_from_pointer (type, addr2);
-	    }
+	  struct value *v = value_addr (v2);
+	  deprecated_set_value_type (v, type);
+	  return v;
 	}
-    }
+   }
 
   /* No superclass found, just change the pointer type.  */
   arg2 = value_copy (arg2);
@@ -257,6 +290,7 @@ value_cast_pointers (struct type *type, 
   return arg2;
 }
 
+
 /* Cast value ARG2 to type TYPE and return as a value.
    More general than a C cast: accepts any two types of the same length,
    and if ARG2 is an lvalue it can be cast into anything at all.  */
@@ -275,6 +309,26 @@ value_cast (struct type *type, struct va
   if (value_type (arg2) == type)
     return arg2;
 
+  code1 = TYPE_CODE (check_typedef (type));
+
+  /* Check if we are casting struct reference to struct reference.  */
+  if (code1 == TYPE_CODE_REF)
+    {
+      /* We dereference type; then we recurse and finally
+         we generate value of the given reference. Nothing wrong with 
+	 that.  */
+      struct type *t1 = check_typedef (type);
+      struct type *dereftype = check_typedef (TYPE_TARGET_TYPE (t1));
+      struct value *val =  value_cast (dereftype, arg2);
+      return value_ref (val); 
+    }
+
+  code2 = TYPE_CODE (check_typedef (value_type (arg2)));
+
+  if (code2 == TYPE_CODE_REF)
+    /* We deref the value and then do the cast.  */
+    return value_cast (type, coerce_ref (arg2)); 
+
   CHECK_TYPEDEF (type);
   code1 = TYPE_CODE (type);
   arg2 = coerce_ref (arg2);
@@ -342,21 +396,10 @@ value_cast (struct type *type, struct va
 	    || code2 == TYPE_CODE_DECFLOAT || code2 == TYPE_CODE_ENUM
 	    || code2 == TYPE_CODE_RANGE);
 
-  if (code1 == TYPE_CODE_STRUCT
-      && code2 == TYPE_CODE_STRUCT
+  if ((code1 == TYPE_CODE_STRUCT || code1 == TYPE_CODE_UNION)
+      && (code2 == TYPE_CODE_STRUCT || code2 == TYPE_CODE_UNION)
       && TYPE_NAME (type) != 0)
-    {
-      /* 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 object in addition to changing its type.  */
-      struct value *v = search_struct_field (type_name_no_tag (type),
-					     arg2, 0, type2, 1);
-      if (v)
-	{
-	  deprecated_set_value_type (v, type);
-	  return v;
-	}
-    }
+    return value_cast_structs (type, arg2);
   if (code1 == TYPE_CODE_FLT && scalar)
     return value_from_double (type, value_as_double (arg2));
   else if (code1 == TYPE_CODE_DECFLOAT && scalar)

  reply	other threads:[~2008-02-29  4:45 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-27 18:43 Aleksandar Ristovski
2008-02-27 19:30 ` Michael Snyder
2008-02-27 19:36   ` Aleksandar Ristovski
2008-02-27 19:47 ` Daniel Jacobowitz
2008-02-27 20:00   ` Aleksandar Ristovski
2008-02-27 20:09     ` Daniel Jacobowitz
2008-02-27 21:26       ` Aleksandar Ristovski
2008-02-27 23:50         ` Daniel Jacobowitz
2008-02-28 19:12           ` Aleksandar Ristovski
2008-02-28 19:39             ` Daniel Jacobowitz
2008-02-29 10:10               ` Aleksandar Ristovski [this message]
2008-03-04 19:39                 ` Aleksandar Ristovski
2008-04-01 14:51                 ` Daniel Jacobowitz
2008-02-29  2:44             ` Michael Snyder
2008-03-31 19:01 Aleksandar Ristovski
2008-04-01 16:26 Aleksandar Ristovski
2008-04-01 17:06 ` Daniel Jacobowitz
2008-04-01 18:10 Aleksandar Ristovski
2008-04-01 18:52 ` Daniel Jacobowitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47C78DD3.4080109@qnx.com \
    --to=aristovski@qnx.com \
    --cc=drow@false.org \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox