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) <la_val_print>: 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'.
This commit is contained in:
Tom Tromey 2010-02-02 16:45:17 +00:00
parent 4339cae0bb
commit edf3d5f3f8
11 changed files with 223 additions and 15 deletions

View File

@ -1,3 +1,23 @@
2010-02-02 Tom Tromey <tromey@redhat.com>
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) <la_val_print>: Document.
* c-lang.h (cp_print_value_fields_rtti): Declare.
2010-02-01 Jan Kratochvil <jan.kratochvil@redhat.com>
PR libc/11214:

View File

@ -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 *);

View File

@ -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:

View File

@ -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;

View File

@ -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. */

View File

@ -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)

View File

@ -1,3 +1,10 @@
2010-02-02 Tom Tromey <tromey@redhat.com>
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 <jan.kratochvil@redhat.com>
PR libc/11214:

View File

@ -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

View File

@ -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
}

View File

@ -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 <http://www.gnu.org/licenses/>.
# 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" " = {<mc::Base> = {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" " = {<C> = {v = 11}, _vptr.D = $hex}"

View File

@ -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);