diff options
Diffstat (limited to 'gdb/valops.c')
-rw-r--r-- | gdb/valops.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/gdb/valops.c b/gdb/valops.c index 4c5927d..cee10fb 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -250,10 +250,33 @@ value_cast_structs (struct type *type, struct value *v2) /* 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. */ + offset the pointer rather than just change its type. */ if (TYPE_NAME (t2) != NULL) { + /* Try downcasting using the run-time type of the value. */ + int full, top, using_enc; + struct type *real_type; + + real_type = value_rtti_type (v2, &full, &top, &using_enc); + if (real_type) + { + v = value_full_object (v2, real_type, full, top, using_enc); + v = value_at_lazy (real_type, value_address (v)); + + /* We might be trying to cast to the outermost enclosing + type, in which case search_struct_field won't work. */ + if (TYPE_NAME (real_type) != NULL + && !strcmp (TYPE_NAME (real_type), TYPE_NAME (t1))) + return v; + + v = search_struct_field (type_name_no_tag (t2), v, 0, real_type, 1); + if (v) + return v; + } + + /* Try downcasting using information from the destination type + T2. This wouldn't work properly for classes with virtual + bases, but those were handled above. */ v = search_struct_field (type_name_no_tag (t2), value_zero (t1, not_lval), 0, t1, 1); if (v) |