diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-07-13 04:31:42 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2006-07-13 04:31:42 +0000 |
commit | fb933624929d0716f25db8d1096557e7f5e72440 (patch) | |
tree | e216dad7d0d61e68304e7ab329fe58c5c850799b /gdb/valops.c | |
parent | d49c44d5f19771810279034d93060d13c13f0937 (diff) | |
download | gdb-fb933624929d0716f25db8d1096557e7f5e72440.zip gdb-fb933624929d0716f25db8d1096557e7f5e72440.tar.gz gdb-fb933624929d0716f25db8d1096557e7f5e72440.tar.bz2 |
gdb/
* infcall.c (value_arg_coerce): Use value_cast_pointers for
references. Avoid value_cast to a reference type. Don't silently
convert pointers to references.
* valops.c (value_cast_pointers): New, based on value_cast.
(value_cast): Use it. Reject reference types.
(value_ref): New.
(typecmp): Use it.
* value.h (value_cast_pointers, value_ref): New prototypes.
gdb/testsuite/
* gdb.cp/ref-params.exp: New test.
* gdb.cp/ref-params.cc: New source file.
* gdb.cp/Makefile.in (EXECUTABLES): Add ref-params.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r-- | gdb/valops.c | 130 |
1 files changed, 86 insertions, 44 deletions
diff --git a/gdb/valops.c b/gdb/valops.c index e86b532..7d1b7d8 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -201,6 +201,70 @@ allocate_space_in_inferior (int len) return value_as_long (value_allocate_space_in_inferior (len)); } +/* 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. */ + +struct value * +value_cast_pointers (struct type *type, struct value *arg2) +{ + 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)); + + if (TYPE_CODE (t1) == TYPE_CODE_STRUCT + && TYPE_CODE (t2) == TYPE_CODE_STRUCT + && !value_logical_not (arg2)) + { + struct value *v; + + /* 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) + { + 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); + } + } + } + + /* No superclass found, just change the pointer type. */ + deprecated_set_value_type (arg2, type); + arg2 = value_change_enclosing_type (arg2, type); + set_value_pointed_to_offset (arg2, 0); /* pai: chk_val */ + 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. */ @@ -224,6 +288,10 @@ value_cast (struct type *type, struct value *arg2) arg2 = coerce_ref (arg2); type2 = check_typedef (value_type (arg2)); + /* You can't cast to a reference type. See value_cast_pointers + instead. */ + gdb_assert (code1 != TYPE_CODE_REF); + /* A cast to an undetermined-length array_type, such as (TYPE [])OBJECT, is treated like a cast to (TYPE [N])OBJECT, where N is sizeof(OBJECT)/sizeof(TYPE). */ @@ -369,50 +437,8 @@ value_cast (struct type *type, struct value *arg2) else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2)) { if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR) - { - struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type)); - struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2)); - if (TYPE_CODE (t1) == TYPE_CODE_STRUCT - && TYPE_CODE (t2) == TYPE_CODE_STRUCT - && !value_logical_not (arg2)) - { - struct value *v; - - /* 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), - value_ind (arg2), 0, t2, 1); - if (v) - { - v = value_addr (v); - deprecated_set_value_type (v, type); - return v; - } - } + return value_cast_pointers (type, arg2); - /* 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); - } - } - } - /* No superclass found, just fall through to change ptr type. */ - } deprecated_set_value_type (arg2, type); arg2 = value_change_enclosing_type (arg2, type); set_value_pointed_to_offset (arg2, 0); /* pai: chk_val */ @@ -886,6 +912,22 @@ value_addr (struct value *arg1) return arg2; } +/* Return a reference value for the object for which ARG1 is the contents. */ + +struct value * +value_ref (struct value *arg1) +{ + struct value *arg2; + + struct type *type = check_typedef (value_type (arg1)); + if (TYPE_CODE (type) == TYPE_CODE_REF) + return arg1; + + arg2 = value_addr (arg1); + deprecated_set_value_type (arg2, lookup_reference_type (type)); + return arg2; +} + /* Given a value of a pointer type, apply the C unary * operator to it. */ struct value * @@ -1106,7 +1148,7 @@ typecmp (int staticp, int varargs, int nargs, if (TYPE_CODE (tt2) == TYPE_CODE_ARRAY) t2[i] = value_coerce_array (t2[i]); else - t2[i] = value_addr (t2[i]); + t2[i] = value_ref (t2[i]); continue; } |