This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [patch] fix for c++/2416
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.
> 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).
That's what I was trying to describe, sorry if it was unclear.
There's value_addr, which takes the address of its argument - give
it a struct or a struct reference, get back a struct pointer. Then
there's value_as_address, which tries to interpret its argument as
an address. Give it a pointer, get back the pointer as a CORE_ADDR.
Giving it a struct doesn't do anything useful.
> @@ -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:
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);
> 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));
Probably t1 should be set from type1.
> 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);
Yep, that makes sense. This was the real bug.
> addr2 -= (VALUE_ADDRESS (v)
> + value_offset (v)
> + value_embedded_offset (v));
> - return value_from_pointer (type, addr2);
> + return value_from_pointer (type1, addr2);
Why type1? It's nice to preserve the requested type on results,
when we can.
--
Daniel Jacobowitz
CodeSourcery