aboutsummaryrefslogtreecommitdiff
path: root/gdb/valops.c
diff options
context:
space:
mode:
authorHannes Domani <ssbssa@yahoo.de>2022-03-29 20:05:06 +0200
committerHannes Domani <ssbssa@yahoo.de>2023-12-11 15:50:00 +0100
commit0238b543f3c294fc8512021a40b708e8ddc72bb2 (patch)
tree794db4b3b773c6de97035ffbd7b6c2fcfa9d47af /gdb/valops.c
parent22b78fad28d54bad1d0aee2fe0acf5f3f40648f6 (diff)
downloadbinutils-0238b543f3c294fc8512021a40b708e8ddc72bb2.zip
binutils-0238b543f3c294fc8512021a40b708e8ddc72bb2.tar.gz
binutils-0238b543f3c294fc8512021a40b708e8ddc72bb2.tar.bz2
Fix dynamic_cast
PR29011 notes that dynamic_cast does not work correctly if classes with virtual methods are involved, some of the results wrongly point into the vtable of the derived class: ``` (gdb) p vlr $1 = (VirtualLeftRight *) 0x162240 (gdb) p vl $2 = (VirtualLeft *) 0x162240 (gdb) p vr $3 = (VirtualRight *) 0x162250 (gdb) p dynamic_cast<VirtualLeftRight*>(vlr) $4 = (VirtualLeftRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16> (gdb) p dynamic_cast<VirtualLeftRight*>(vl) $5 = (VirtualLeftRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16> (gdb) p dynamic_cast<VirtualLeftRight*>(vr) $6 = (VirtualLeftRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16> (gdb) p dynamic_cast<VirtualLeft*>(vlr) $7 = (VirtualLeft *) 0x162240 (gdb) p dynamic_cast<VirtualLeft*>(vl) $8 = (VirtualLeft *) 0x13fab89b0 <vtable for VirtualLeftRight+16> (gdb) p dynamic_cast<VirtualLeft*>(vr) $9 = (VirtualLeft *) 0x162240 (gdb) p dynamic_cast<VirtualRight*>(vlr) $10 = (VirtualRight *) 0x162250 (gdb) p dynamic_cast<VirtualRight*>(vl) $11 = (VirtualRight *) 0x162250 (gdb) p dynamic_cast<VirtualRight*>(vr) $12 = (VirtualRight *) 0x13fab89b0 <vtable for VirtualLeftRight+16> ``` For the cases where the dynamic_cast type is the same as the original type, it used the ARG value for the result, which in case of pointer types was already the dereferenced value. And the TEM value at the value address was created with the pointer/reference type, not the actual class type. With these fixed, the dynamic_cast results make more sense: ``` (gdb) p vlr $1 = (VirtualLeftRight *) 0x692240 (gdb) p vl $2 = (VirtualLeft *) 0x692240 (gdb) p vr $3 = (VirtualRight *) 0x692250 (gdb) p dynamic_cast<VirtualLeftRight*>(vlr) $4 = (VirtualLeftRight *) 0x692240 (gdb) p dynamic_cast<VirtualLeftRight*>(vl) $5 = (VirtualLeftRight *) 0x692240 (gdb) p dynamic_cast<VirtualLeftRight*>(vr) $6 = (VirtualLeftRight *) 0x692240 (gdb) p dynamic_cast<VirtualLeft*>(vlr) $7 = (VirtualLeft *) 0x692240 (gdb) p dynamic_cast<VirtualLeft*>(vl) $8 = (VirtualLeft *) 0x692240 (gdb) p dynamic_cast<VirtualLeft*>(vr) $9 = (VirtualLeft *) 0x692240 (gdb) p dynamic_cast<VirtualRight*>(vlr) $10 = (VirtualRight *) 0x692250 (gdb) p dynamic_cast<VirtualRight*>(vl) $11 = (VirtualRight *) 0x692250 (gdb) p dynamic_cast<VirtualRight*>(vr) $12 = (VirtualRight *) 0x692250 ``` Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29011 Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb/valops.c')
-rw-r--r--gdb/valops.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/gdb/valops.c b/gdb/valops.c
index b0e95c3..49ea1fd 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -856,7 +856,7 @@ value_dynamic_cast (struct type *type, struct value *arg)
/* If the classes are the same, just return the argument. */
if (class_types_same_p (class_type, arg_type))
- return value_cast (type, arg);
+ return value_cast (type, original_arg);
/* If the target type is a unique base class of the argument's
declared type, just cast it. */
@@ -888,14 +888,18 @@ value_dynamic_cast (struct type *type, struct value *arg)
&& resolved_type->target_type ()->code () == TYPE_CODE_VOID)
return value_at_lazy (type, addr);
- tem = value_at (type, addr);
- type = tem->type ();
+ tem = value_at (resolved_type->target_type (), addr);
+ type = (is_ref
+ ? lookup_reference_type (tem->type (), resolved_type->code ())
+ : lookup_pointer_type (tem->type ()));
/* The first dynamic check specified in 5.2.7. */
if (is_public_ancestor (arg_type, resolved_type->target_type ()))
{
if (class_types_same_p (rtti_type, resolved_type->target_type ()))
- return tem;
+ return (is_ref
+ ? value_ref (tem, resolved_type->code ())
+ : value_addr (tem));
result = NULL;
if (dynamic_cast_check_1 (resolved_type->target_type (),
tem->contents_for_printing ().data (),