+/* Cast struct value VAL to type TYPE and return as a value.
+ Both type and val must be of TYPE_CODE_STRUCT or TYPE_CODE_UNION
+ for this to work. Typedef to one of the codes is permitted.
+ Returns NULL if the cast is neither an upcast nor a downcast. */
+
+static struct value *
+value_cast_structs (struct type *type, struct value *v2)
+{
+ struct type *t1;
+ struct type *t2;
+ struct value *v;
+
+ 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
+ offset the pointer rather than just change its type. */
+ if (TYPE_NAME (t1) != NULL)
+ {
+ v = search_struct_field (type_name_no_tag (t1),
+ v2, 0, t2, 1);
+ if (v)
+ return v;
+ }
+
+ /* 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. */
+ if (TYPE_NAME (t2) != NULL)
+ {
+ v = search_struct_field (type_name_no_tag (t2),
+ value_zero (t1, not_lval), 0, t1, 1);
+ if (v)
+ {
+ /* Downcasting is possible (t1 is superclass of v2). */
+ CORE_ADDR addr2 = value_address (v2);
+ addr2 -= value_address (v) + value_embedded_offset (v);
+ return value_at (type, addr2);
+ }
+ }
+
+ return NULL;
+}
+
+/* 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 (check_typedef (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. */
+ arg2 = value_copy (arg2);
+ 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;
+}
+