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); } } }