diff options
author | Tom Tromey <tromey@redhat.com> | 2010-02-02 23:40:28 +0000 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2010-02-02 23:40:28 +0000 |
commit | 9c3c02fd158a5a0f8d64ec1c36078b1c9df0e6fc (patch) | |
tree | c1cdfef1022c3f73c6eabc8d781791261efb1d86 /gdb/valops.c | |
parent | f23f4c5973c3ad96ecf812036c6b0ee5a17d726f (diff) | |
download | gdb-9c3c02fd158a5a0f8d64ec1c36078b1c9df0e6fc.zip gdb-9c3c02fd158a5a0f8d64ec1c36078b1c9df0e6fc.tar.gz gdb-9c3c02fd158a5a0f8d64ec1c36078b1c9df0e6fc.tar.bz2 |
gdb
* valops.c (value_cast_structs): Try downcasting using the RTTI
type.
gdb/testsuite
* gdb.cp/virtbase.exp: Add regression tests.
* gdb.cp/virtbase.cc (RHA, RHB, RHC): New classes.
(main): Instantiate RHC.
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) |