This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[patch/testsuite/c++] test script for PR c++/186
- From: mec dot gnu at mindspring dot com (Michael Elizabeth Chastain)
- To: gdb-patches at sources dot redhat dot com
- Date: Sun, 23 Nov 2003 17:04:45 -0500 (EST)
- Subject: [patch/testsuite/c++] test script for PR c++/186
This is a new test script. It's for PR gdb/186:
http://sources.redhat.com/gdb/bugs/186
gdb have problems with C++ casting
Here is a summary of the code:
class A;
class B : public A;
int main (void)
{
B beta, *beta_p;
beta_p = β
...
} // breakpoint here
And here is a summary of the *.exp file:
(gdb) break "breakpoint here"
(gdb) print beta
... okay ...
(gdb) print * beta_p
... gdb prints bogus data ...
The issue is that the user is accessing a destroyed object through a
pointer. Because the object has been destroyed, its vptr has been
degraded to its most primitive base class. gdb gets confused and prints
incorrect data, which is always wrong.
Testing: I tested this on native i686-pc-linux-gnu with:
gcc 2.95.3 -gdwarf-2
gcc 2.95.3 -gstabs+
gcc 3.3.2 -gdwarf-2
gcc 3.3.2 -gstabs+
The results are all PASS and KFAIL, with no FAIL.
I'll put this up for a few days for comment, especially from David C.
Then I'll commit it.
Michael C
===
2003-11-23 Michael Chastain <mec.gnu@mindspring.com>
New test case for PR c++/186.
* gdb.cp/gdb186.cc: New file.
* gdb.cp/gdb186.exp: New file.
===
/* This testcase is part of GDB, the GNU debugger.
Copyright 2003 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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Please email any bugs, comments, and/or additions to this file to:
bug-gdb@prep.ai.mit.edu */
struct A
{
virtual ~A ();
int a1;
};
A::~A()
{
;
}
struct B : public A
{
virtual ~B ();
int b1;
int b2;
};
B::~B()
{
;
}
void marker1 (A *)
{
;
}
int main (void)
{
A *alpha_p;
B beta, *beta_p;
beta.a1 = 100;
beta.b1 = 200;
beta.b2 = 201;
alpha_p = β
beta_p = (B *) alpha_p;
marker1 (alpha_p);
marker1 (beta_p);
return 0; // marker return 0
} // marker close brace
===
# Copyright 2003 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Test for PR gdb/186.
#
# This is a problem with C++ casting on a dead object. The object's
# type (its vptr) has been degraded by its destructors.
if $tracelevel then {
strace $tracelevel
}
if { [skip_cplus_tests] } { continue }
set prms_id 0
set bug_id 0
set testfile "gdb186"
set srcfile ${testfile}.cc
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
}
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
if ![runto_main] then {
perror "couldn't run to main"
continue
}
gdb_test "break [gdb_get_line_number "marker return 0"]" \
"Breakpoint.*at.* file .*" ""
gdb_test "continue" "Breakpoint .* at .*" ""
# This part should be simple and good.
gdb_test "print beta" \
"= {.*a1 = 100.*b1 = 200.*b2 = 201}" \
"print beta at marker return 0"
gdb_test "print * beta_p" \
"= {.*a1 = 100.*b1 = 200.*b2 = 201}" \
"print * beta_p at marker return 0"
gdb_test "print * (B *) alpha_p" \
"= {.*a1 = 100.*b1 = 200.*b2 = 201}" \
"print * (B *) alpha_p at marker return 0"
gdb_test "print * alpha_p" \
"= {.*a1 = 100.*}" \
"print * alpha_p at marker return 0"
# All that again, at the close brace.
#
# This is where the real problem happens. "beta" has been destroyed!
# The gcc code for B::~B changes the type (the vptr) of "beta" from
# "B" to "A" so that B::~B can call A::~A. Every C++ compiler has to
# do something like this, in case A::~A calls a virtual function.
#
# It would also be legal for a C++ compiler to put some kind of sentinel
# value in beta.vptr so that it's not even an "A" any more. But I am
# not seeing that with gcc.
#
# So, the user is trying to print a structure of type "B", but there is
# only an "A" in memory, and the user might not even realize that.
gdb_test "break [gdb_get_line_number "marker close brace"]" \
"Breakpoint.*at.* file .*" ""
gdb_test "continue" "Breakpoint .* at .*" ""
gdb_test_multiple "print beta" "print beta at marker close brace" {
-re "= {.*a1 = 100.*b1 = 200.*b2 = 201}\r\n$gdb_prompt " {
# the data fields should still be okay even though beta is dead
pass "print beta at marker close brace"
}
}
# "* beta_p" has static type "B", but there is probably only an "A"
# in memory after B::~B does its thing. The user may not realize
# this so gdb should be careful to be informative here.
#
# TODO: add another PASS case for this depending on what David C
# thinks the correct output should be.
gdb_test_multiple "print * beta_p" "print * beta_p at marker close brace" {
-re "= {.*a1 = 100.*b1 = 200.*b2 = 201}\r\n$gdb_prompt $" {
# This is not happening, but it would be okay.
pass "print * beta_p at marker close brace"
}
-re "= {.*a1 = 100}\r\n$gdb_prompt $" {
# This is not happening, but it would be okay,
# although a little surprising.
pass "print * beta_p at marker close brace"
}
-re "= {.*a1 = 100.*b1 = .*b2 = .*}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gstabs+
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
# Someone might argue that gdb is not buggy here but I think it is.
kfail "gdb/186" "print * beta_p at marker close brace #1"
}
-re "= {.*a1 = .*b1 = .*b2 = .*}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gdb does not even get the value of a1 right!
kfail "gdb/186" "print * beta_p at marker close brace #2"
}
}
# Another way to pose the same question.
gdb_test_multiple "print * (B *) alpha_p " "print * (B *) alpha_p at marker close brace" {
-re "= {.*a1 = 100.*b1 = 200.*b2 = 201}\r\n$gdb_prompt $" {
# This is not happening, but it would be okay.
pass "print * (B *) alpha_p at marker close brace"
}
-re "= {.*a1 = 100}\r\n$gdb_prompt $" {
# This is not happening, but it would be okay,
# although a little surprising.
pass "print * (B *) alpha_p at marker close brace"
}
-re "= {.*a1 = 100.*b1 = .*b2 = .*}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gstabs+
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
# Someone might argue that gdb is not buggy here but I think it is.
kfail "gdb/186" "print * (B *) alpha_p at marker close brace #1"
}
-re "= {.*a1 = .*b1 = .*b2 = .*}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
# gdb does not even get the value of a1 right!
kfail "gdb/186" "print * (B *) alpha_p at marker close brace #2"
}
}
# This should work better, as long as beta is still an "A" at least.
gdb_test_multiple "print * alpha_p" "print * alpha_p at marker close brace" {
-re "= {.*a1 = 100.*b1 = 200.*b2 = 201}\r\n$gdb_prompt $" {
# this should not happen but if it did, it would be okay
pass "print * alpha_p at marker close brace"
}
-re "= {.*a1 = .*b1 = .*b2 = .*}\r\n$gdb_prompt $" {
# if gdb prints any values and they are WRONG, that is not okay
kfail "gdb/186" "print * alpha_p at marker close brace #1"
}
-re "= {.*a1 = 100.*}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gstabs+
# gcc 3.3.2 -gdwarf-2
# gcc 3.3.2 -gstabs+
# this is okay
pass "print * alpha_p at marker close brace"
}
-re "= {.*a1 = .*}\r\n$gdb_prompt $" {
# gcc 2.95.3 -gdwarf-2
kfail "gdb/186" "print * alpha_p at marker close brace #2"
}
}