From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28509 invoked by alias); 28 Feb 2008 18:53:38 -0000 Received: (qmail 28492 invoked by uid 22791); 28 Feb 2008 18:53:36 -0000 X-Spam-Check-By: sourceware.org Received: from qnxmail.qnx.com (HELO qnxmail.qnx.com) (209.226.137.76) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 28 Feb 2008 18:53:17 +0000 Received: from smtp.ott.qnx.com (smtp.ott.qnx.com [10.42.96.5]) by hub.ott.qnx.com (8.9.3/8.9.3) with ESMTP id NAA17937; Thu, 28 Feb 2008 13:36:20 -0500 Received: from [10.42.100.129] (dhcp-100-129 [10.42.100.129]) by smtp.ott.qnx.com (8.8.8/8.6.12) with ESMTP id NAA08875; Thu, 28 Feb 2008 13:53:14 -0500 Message-ID: <47C70319.4050804@qnx.com> Date: Thu, 28 Feb 2008 19:12:00 -0000 From: Aleksandar Ristovski User-Agent: Thunderbird 2.0.0.12 (Windows/20080213) MIME-Version: 1.0 To: Daniel Jacobowitz CC: gdb-patches@sourceware.org Subject: Re: [patch] fix for c++/2416 References: <47C5A5EE.6070107@qnx.com> <20080227193546.GA11796@caradoc.them.org> <47C5BE84.7050803@qnx.com> <20080227200019.GB12434@caradoc.them.org> <47C5D138.6020909@qnx.com> <20080227220659.GE14556@caradoc.them.org> In-Reply-To: <20080227220659.GE14556@caradoc.them.org> Content-Type: multipart/mixed; boundary="------------030501090606010802000207" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-02/txt/msg00485.txt.bz2 This is a multi-part message in MIME format. --------------030501090606010802000207 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1625 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 * 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. --------------030501090606010802000207 Content-Type: text/plain; name="casting.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="casting.diff" Content-length: 3512 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); } } } --------------030501090606010802000207 Content-Type: text/plain; name="casting.tests.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="casting.tests.diff" Content-length: 1692 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" ".* = { = # the dereference. gdb_test "print * b" ".* = { = {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 = 42}, b = 1729}" \ + "cast base class reference to derived class reference" + +# Check compiler casting +gdb_test "print br" ".* = .B.* { = {a = 42}, b = 1729}" \ + "let compiler cast base class reference to derived class reference" --------------030501090606010802000207--