* 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.
This commit is contained in:
Aleksandar Ristovski 2008-04-01 16:12:49 +00:00
parent 6c2d1a6bc9
commit 6af87b0348
2 changed files with 105 additions and 52 deletions

View File

@ -1,3 +1,14 @@
2008-04-01 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.
2008-04-01 Marc Khouzam <marc.khouzam@ericsson.com> 2008-04-01 Marc Khouzam <marc.khouzam@ericsson.com>
* MAINTAINERS: Added myself to section Write After Approval. * MAINTAINERS: Added myself to section Write After Approval.

View File

@ -192,45 +192,42 @@ allocate_space_in_inferior (int len)
return value_as_long (value_allocate_space_in_inferior (len)); return value_as_long (value_allocate_space_in_inferior (len));
} }
/* Cast one pointer or reference type to another. Both TYPE and /* Cast struct value VAL to type TYPE and return as a value.
the type of ARG2 should be pointer types, or else both should be Both type and val must be of TYPE_CODE_STRUCT or TYPE_CODE_UNION
reference types. Returns the new pointer or reference. */ for this to work. Typedef to one of the codes is permitted. */
struct value * static struct value *
value_cast_pointers (struct type *type, struct value *arg2) value_cast_structs (struct type *type, struct value *v2)
{
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 type *t1;
struct type *t2;
struct value *v; struct value *v;
/* Look in the type of the source to see if it contains the 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 type of the target as a superclass. If so, we'll need to
offset the pointer rather than just change its type. */ offset the pointer rather than just change its type. */
if (TYPE_NAME (t1) != NULL) 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), v = search_struct_field (type_name_no_tag (t1),
v2, 0, t2, 1); v2, 0, t2, 1);
if (v) if (v)
{
v = value_addr (v);
deprecated_set_value_type (v, type);
return v; return v;
} }
}
/* 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 type of the source as a superclass. If so, we'll need to
offset the pointer rather than just change its type. offset the pointer rather than just change its type.
FIXME: This fails silently with virtual inheritance. */ FIXME: This fails silently with virtual inheritance. */
@ -240,13 +237,49 @@ value_cast_pointers (struct type *type, struct value *arg2)
value_zero (t1, not_lval), 0, t1, 1); value_zero (t1, not_lval), 0, t1, 1);
if (v) 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) addr2 -= (VALUE_ADDRESS (v)
+ value_offset (v) + value_offset (v)
+ value_embedded_offset (v)); + value_embedded_offset (v));
return value_from_pointer (type, addr2); 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. */
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));
if (TYPE_CODE (t1) == TYPE_CODE_STRUCT
&& TYPE_CODE (t2) == TYPE_CODE_STRUCT
&& !value_logical_not (arg2))
{
struct value *v2;
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 *v = value_addr (v2);
deprecated_set_value_type (v, type);
return v;
}
} }
/* No superclass found, just change the pointer type. */ /* No superclass found, just change the pointer type. */
@ -275,6 +308,26 @@ value_cast (struct type *type, struct value *arg2)
if (value_type (arg2) == type) if (value_type (arg2) == type)
return arg2; 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); CHECK_TYPEDEF (type);
code1 = TYPE_CODE (type); code1 = TYPE_CODE (type);
arg2 = coerce_ref (arg2); arg2 = coerce_ref (arg2);
@ -342,21 +395,10 @@ value_cast (struct type *type, struct value *arg2)
|| code2 == TYPE_CODE_DECFLOAT || code2 == TYPE_CODE_ENUM || code2 == TYPE_CODE_DECFLOAT || code2 == TYPE_CODE_ENUM
|| code2 == TYPE_CODE_RANGE); || code2 == TYPE_CODE_RANGE);
if (code1 == TYPE_CODE_STRUCT if ((code1 == TYPE_CODE_STRUCT || code1 == TYPE_CODE_UNION)
&& code2 == TYPE_CODE_STRUCT && (code2 == TYPE_CODE_STRUCT || code2 == TYPE_CODE_UNION)
&& TYPE_NAME (type) != 0) && TYPE_NAME (type) != 0)
{ return value_cast_structs (type, arg2);
/* 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;
}
}
if (code1 == TYPE_CODE_FLT && scalar) if (code1 == TYPE_CODE_FLT && scalar)
return value_from_double (type, value_as_double (arg2)); return value_from_double (type, value_as_double (arg2));
else if (code1 == TYPE_CODE_DECFLOAT && scalar) else if (code1 == TYPE_CODE_DECFLOAT && scalar)