diff --git a/gdb/ChangeLog b/gdb/ChangeLog index aa694be1bc7..b57bbdf1cf3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2011-02-02 Pedro Alves + + * c-valprint.c (c_value_print): When doing virtual base pointer + adjustment, create a new value with adjusted contents rather than + changing the contents of the value being printed (and getting it + wrong). + 2011-02-02 Pedro Alves * xml-support.c (xml_find_attribute): New. diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 3bd4db25650..287dc0ba2a7 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -706,8 +706,7 @@ c_value_print (struct value *val, struct ui_file *stream, type = lookup_reference_type (real_type); } /* JYG: Need to adjust pointer value. */ - /* NOTE: cagney/2005-01-02: THIS IS BOGUS. */ - value_contents_writeable (val)[0] -= top; + val = value_from_pointer (type, value_as_address (val) - top); /* Note: When we look up RTTI entries, we don't get any information on const or volatile attributes. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 3afe2e53909..0b6095c8d1c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-02-02 Pedro Alves + + * gdb.cp/virtbase.cc (VirtualBase, VirtualMiddleA, VirtualMiddleB) + (Virtual): New structs. + (virtual_o, virtual_middle_b): New globals. + * gdb.cp/virtbase.exp: New tests. + 2011-01-31 Paul Pluzhnikov * gdb.base/jit.exp: New file. diff --git a/gdb/testsuite/gdb.cp/virtbase.cc b/gdb/testsuite/gdb.cp/virtbase.cc index 1e6874fd3b0..e23dbda813a 100644 --- a/gdb/testsuite/gdb.cp/virtbase.cc +++ b/gdb/testsuite/gdb.cp/virtbase.cc @@ -88,6 +88,37 @@ public: RTTI_data() : data(1) {} }; +/* These classes are for testing pointer adjustment when printing a + pointer into a virtual base, with print object on. */ +struct VirtualBase { + int x; + + virtual ~VirtualBase() {} +}; + +struct VirtualMiddleA : public virtual VirtualBase { + /* Make sure the vbase offset of Virtual::VirtualBaseB is larger + than what fits in one byte. */ + int y[300]; + + virtual ~VirtualMiddleA() {} +}; + +struct VirtualMiddleB : public virtual VirtualBase { + int y; + + virtual ~VirtualMiddleB() {} +}; + +struct Virtual : public virtual VirtualMiddleA, public virtual VirtualMiddleB { + int z; + + virtual ~Virtual() {} +}; + +Virtual virtual_o; +VirtualMiddleB *virtual_middle_b = &virtual_o; + int main() { ph::Derived tst; tst.get_y(); diff --git a/gdb/testsuite/gdb.cp/virtbase.exp b/gdb/testsuite/gdb.cp/virtbase.exp index 460c96893cf..4bfec44574f 100644 --- a/gdb/testsuite/gdb.cp/virtbase.exp +++ b/gdb/testsuite/gdb.cp/virtbase.exp @@ -65,3 +65,18 @@ gdb_test "print/x b->mA" " = 0xaaaaaaaa" # https://bugzilla.redhat.com/show_bug.cgi?id=606660 # `set print object on' is expected. gdb_test "print rtti_data" " = .*, data = 1\}" + +# Printing a pointer into a virtual base of a larger object used to do +# pointer adjusment directly into the value being printed, in-place +# (and did it wrong, too). Print the pointer, and then access the +# value history to check the pointer value is not changed. If it had +# been changed, then we'd not be able to find the real type anymore. +gdb_test "print virtual_middle_b" \ + " = \\(Virtual \\*\\) $hex" \ + "print pointer to virtual base at non-zero offset of larger object" +gdb_test "print $" \ + " = \\(Virtual \\*\\) $hex" \ + "print same pointer from history value" +gdb_test "print *$$" \ + " = \\(Virtual\\) { = { = {_vptr.VirtualBase = $hex, x = 0}, _vptr.VirtualMiddleA = $hex, y = \\{0 \\}}, = {_vptr.VirtualMiddleB = $hex, y = 0}, _vptr.Virtual = $hex, z = 0}" \ + "print whole pointed-to object, starting from the virtual base pointer"