From: Tom Tromey Date: Tue, 2 Feb 2010 16:45:17 +0000 (+0000) Subject: gdb X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=edf3d5f3f8c5adff55934e57da9cd8c874dc2a55;p=binutils-gdb.git gdb PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890: * valops.c (search_struct_field): Compute nbases after calling CHECK_TYPEDEF. (check_field): Call CHECK_TYPEDEF. * cp-valprint.c (cp_print_value): Pass correct address to baseclass_offset. Fix check for virtual base past the end of the object. Don't offset address passed to cp_print_value_fields or apply_val_pretty_printer. (cp_print_value_fields): Fix call to val_print. (cp_print_value_fields_rtti): New function. * c-valprint.c (c_val_print): Use cp_print_value_fields_rtti. * p-valprint.c (pascal_object_print_value_fields): Fix call to val_print. * python/py-prettyprint.c (apply_val_pretty_printer): Add embedded offset to address. * language.h (struct language_defn) : Document. * c-lang.h (cp_print_value_fields_rtti): Declare. gdb/testsuite PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890: * gdb.cp/virtbase.cc: New file. * gdb.cp/virtbase.exp: New file. * gdb.cp/userdef.exp: Allow 'struct' or 'class'. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b2b1ce09d81..01ce1210d9b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2010-02-02 Tom Tromey + + PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890: + * valops.c (search_struct_field): Compute nbases after calling + CHECK_TYPEDEF. + (check_field): Call CHECK_TYPEDEF. + * cp-valprint.c (cp_print_value): Pass correct address to + baseclass_offset. Fix check for virtual base past the end of the + object. Don't offset address passed to cp_print_value_fields or + apply_val_pretty_printer. + (cp_print_value_fields): Fix call to val_print. + (cp_print_value_fields_rtti): New function. + * c-valprint.c (c_val_print): Use cp_print_value_fields_rtti. + * p-valprint.c (pascal_object_print_value_fields): Fix call to + val_print. + * python/py-prettyprint.c (apply_val_pretty_printer): Add embedded + offset to address. + * language.h (struct language_defn) : Document. + * c-lang.h (cp_print_value_fields_rtti): Declare. + 2010-02-01 Jan Kratochvil PR libc/11214: diff --git a/gdb/c-lang.h b/gdb/c-lang.h index d567e81d76c..423cee05899 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -102,6 +102,12 @@ extern void cp_print_value_fields (struct type *, struct type *, const struct value_print_options *, struct type **, int); +extern void cp_print_value_fields_rtti (struct type *, + const gdb_byte *, int, CORE_ADDR, + struct ui_file *, int, + const struct value_print_options *, + struct type **, int); + extern int cp_is_vtbl_ptr_type (struct type *); extern int cp_is_vtbl_member (struct type *); diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index d681a03f96f..31ae4e795e8 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -389,8 +389,9 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, options->addressprint); } else - cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream, - recurse, options, NULL, 0); + cp_print_value_fields_rtti (type, valaddr, + embedded_offset, address, stream, + recurse, options, NULL, 0); break; case TYPE_CODE_ENUM: diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c index 3e9beb690ea..167c6d4e6cd 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -295,7 +295,7 @@ cp_print_value_fields (struct type *type, struct type *real_type, opts.deref_ref = 0; val_print (TYPE_FIELD_TYPE (type, i), valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8, - address + TYPE_FIELD_BITPOS (type, i) / 8, + address, stream, recurse + 1, &opts, current_language); } @@ -321,6 +321,39 @@ cp_print_value_fields (struct type *type, struct type *real_type, fprintf_filtered (stream, "}"); } +/* Like cp_print_value_fields, but find the runtime type of the object + and pass it as the `real_type' argument to cp_print_value_fields. + This function is a hack to work around the fact that + common_val_print passes the embedded offset to val_print, but not + the enclosing type. */ + +void +cp_print_value_fields_rtti (struct type *type, + const gdb_byte *valaddr, int offset, + CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value_print_options *options, + struct type **dont_print_vb, int dont_print_statmem) +{ + struct value *value; + int full, top, using_enc; + struct type *real_type; + + /* Ugh, we have to convert back to a value here. */ + value = value_from_contents_and_address (type, valaddr + offset, + address + offset); + /* We don't actually care about most of the result here -- just the + type. We already have the correct offset, due to how val_print + was initially called. */ + real_type = value_rtti_type (value, &full, &top, &using_enc); + if (!real_type) + real_type = type; + + cp_print_value_fields (type, real_type, valaddr, offset, + address, stream, recurse, options, + dont_print_vb, dont_print_statmem); +} + /* Special val_print routine to avoid printing multiple copies of virtual baseclasses. */ @@ -373,7 +406,7 @@ cp_print_value (struct type *type, struct type *real_type, thisoffset = offset; thistype = real_type; - boffset = baseclass_offset (type, i, valaddr + offset, address); + boffset = baseclass_offset (type, i, valaddr + offset, address + offset); skip = ((boffset == -1) || (boffset + offset) < 0) ? 1 : -1; if (BASETYPE_VIA_VIRTUAL (type, i)) @@ -384,7 +417,7 @@ cp_print_value (struct type *type, struct type *real_type, if (boffset != -1 && ((boffset + offset) < 0 - || (boffset + offset) >= TYPE_LENGTH (type))) + || (boffset + offset) >= TYPE_LENGTH (real_type))) { /* FIXME (alloca): unsafe if baseclass is really really large. */ gdb_byte *buf = alloca (TYPE_LENGTH (baseclass)); @@ -427,14 +460,14 @@ cp_print_value (struct type *type, struct type *real_type, if (!options->raw) result = apply_val_pretty_printer (baseclass, base_valaddr, thisoffset + boffset, - address + boffset, + address, stream, recurse, options, current_language); if (!result) cp_print_value_fields (baseclass, thistype, base_valaddr, - thisoffset + boffset, address + boffset, + thisoffset + boffset, address, stream, recurse, options, ((struct type **) obstack_base (&dont_print_vb_obstack)), @@ -501,7 +534,8 @@ cp_print_static_field (struct type *type, sizeof (CORE_ADDR)); CHECK_TYPEDEF (type); - cp_print_value_fields (type, type, value_contents_all (val), + cp_print_value_fields (type, value_enclosing_type (val), + value_contents_all (val), value_embedded_offset (val), addr, stream, recurse, options, NULL, 1); return; diff --git a/gdb/language.h b/gdb/language.h index aaefb036383..4f78a28a470 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -208,11 +208,32 @@ struct language_defn void (*la_print_typedef) (struct type *type, struct symbol *new_symbol, struct ui_file *stream); - /* Print a value using syntax appropriate for this language. */ + /* Print a value using syntax appropriate for this language. + + TYPE is the type of the sub-object to be printed. - int (*la_val_print) (struct type *, const gdb_byte *, int, CORE_ADDR, - struct ui_file *, int, - const struct value_print_options *); + CONTENTS holds the bits of the value. This holds the entire + enclosing object. + + EMBEDDED_OFFSET is the offset into the outermost object of the + sub-object represented by TYPE. This is the object which this + call should print. Note that the enclosing type is not + available. + + ADDRESS is the address in the inferior of the enclosing object. + + STREAM is the stream on which the value is to be printed. + + RECURSE is the recursion depth. It is zero-based. + + OPTIONS are the formatting options to be used when + printing. */ + + int (*la_val_print) (struct type *type, + const gdb_byte *contents, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value_print_options *options); /* Print a top-level value using syntax appropriate for this language. */ diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c index 193f97cc114..454aa5a3e3e 100644 --- a/gdb/python/py-prettyprint.c +++ b/gdb/python/py-prettyprint.c @@ -538,7 +538,8 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, /* Instantiate the printer. */ if (valaddr) valaddr += embedded_offset; - value = value_from_contents_and_address (type, valaddr, address); + value = value_from_contents_and_address (type, valaddr, + address + embedded_offset); val_obj = value_to_value_object (value); if (! val_obj) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 0be26e6d49a..d55d31a763e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-02-02 Tom Tromey + + PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890: + * gdb.cp/virtbase.cc: New file. + * gdb.cp/virtbase.exp: New file. + * gdb.cp/userdef.exp: Allow 'struct' or 'class'. + 2010-02-01 Jan Kratochvil PR libc/11214: diff --git a/gdb/testsuite/gdb.cp/userdef.exp b/gdb/testsuite/gdb.cp/userdef.exp index bd54c78ba30..2bbf95e91e0 100644 --- a/gdb/testsuite/gdb.cp/userdef.exp +++ b/gdb/testsuite/gdb.cp/userdef.exp @@ -153,7 +153,7 @@ gdb_test "break A2::'operator +'" ".*Breakpoint $decimal at.*" gdb_test "print c" "\\\$\[0-9\]* = {m = {z = .*}}" gdb_test "print *c" "\\\$\[0-9\]* = \\(Member &\\) @$hex: {z = .*}" gdb_test "print &*c" "\\\$\[0-9\]* = \\(Member \\*\\) $hex" -gdb_test "ptype &*c" "type = struct Member {\[\r\n \]+int z;\[\r\n\]+} &\\*" +gdb_test "ptype &*c" "type = (struct|class) Member {(\[\r\n \]+public:)?\[\r\n \]+int z;\[\r\n\]+} &\\*" gdb_exit return 0 diff --git a/gdb/testsuite/gdb.cp/virtbase.cc b/gdb/testsuite/gdb.cp/virtbase.cc new file mode 100644 index 00000000000..ae0a2c719ab --- /dev/null +++ b/gdb/testsuite/gdb.cp/virtbase.cc @@ -0,0 +1,57 @@ +// This first batch of classes are for PR 11226. +namespace mc { + class Base { + protected: + int x; + + public: + Base(void) { x = 2; }; + }; +} + +namespace ph { + class Middle: public virtual mc::Base { + protected: + int y; + + public: + Middle(void): mc::Base() { y = 3; }; + + int get_y(void) + { + return y; // breakpoint 1 + }; + }; + + class Derived: public virtual Middle { + protected: + int z; + + public: + Derived(void): Middle() { z = 4; }; + + int get_z(void) + { + return z; // breakpoint 2 + }; + }; +} + +// These classes are for PR 9629. +struct A {}; +struct B : virtual A {}; + +struct C {int v; C() {v=11;};}; +struct D:virtual C{}; + +class E:B,D{}; + +int main() { + ph::Derived tst; + tst.get_y(); + tst.get_z(); + + E *e = new E; + + return 0; // breakpoint 3 +} diff --git a/gdb/testsuite/gdb.cp/virtbase.exp b/gdb/testsuite/gdb.cp/virtbase.exp new file mode 100644 index 00000000000..6a37626bc06 --- /dev/null +++ b/gdb/testsuite/gdb.cp/virtbase.exp @@ -0,0 +1,57 @@ +# Copyright 2010 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +if { [skip_cplus_tests] } { continue } + +set testfile "virtbase" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested virtbase.exp + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if {![runto_main]} then { + perror "couldn't run to breakpoint" + continue +} + +gdb_breakpoint [gdb_get_line_number "breakpoint 1"] +gdb_continue_to_breakpoint "first breakpoint" + +# In PR 11226, we failed to print x correctly in the "print *this" +# case. +gdb_test "print *this" " = { = {x = 2}, _vptr.Middle = $hex, y = 3}" +gdb_test "print x" " = 2" + +gdb_breakpoint [gdb_get_line_number "breakpoint 2"] +gdb_continue_to_breakpoint "second breakpoint" + +# In PR 11226, we could not find x here. +gdb_test "print x" " = 2" + +gdb_breakpoint [gdb_get_line_number "breakpoint 3"] +gdb_continue_to_breakpoint "third breakpoint" + +# In PR 9629, we failed to print v correctly here. +gdb_test "print *(D *) e" " = { = {v = 11}, _vptr.D = $hex}" diff --git a/gdb/valops.c b/gdb/valops.c index 2cdbcbe873c..4c5927d7c57 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1787,9 +1787,10 @@ search_struct_field (char *name, struct value *arg1, int offset, struct type *type, int looking_for_baseclass) { int i; - int nbases = TYPE_N_BASECLASSES (type); + int nbases; CHECK_TYPEDEF (type); + nbases = TYPE_N_BASECLASSES (type); if (!looking_for_baseclass) for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) @@ -2763,6 +2764,9 @@ check_field (struct type *type, const char *name) { int i; + /* The type may be a stub. */ + CHECK_TYPEDEF (type); + for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) { char *t_field_name = TYPE_FIELD_NAME (type, i);