Hi, I pulled out the guality.exp [p]type test extension from the actual dwarf2out.c changes (which I will repost soon with some tweaks). I think the test extension itself is useful on its own (and will use it to add tests for my new patches).
All new tests PASS, except when using -flto, so you'll need the "Don't run guality.exp tests with LTO_TORTURE_OPTIONS" if you don't want to add new FAILs. But I hope this patch can go in even without that because I do think it is useful on its own. Add a new type:var variant to the guality.exp testsuite to check that gdb gets the correct type for a variable or function. To use it in a guality test add something like: /* { dg-final { gdb-test 50 "type:main" "int (int, char **)" } } */ Which will put a breakpoint at line 50 and check that the type of "main" equals "int (int, char **)" according to gdb. The test harness will make sure to squash all extra whitespace/newlines that gdb might use to make comparisons of large structs easy. gcc/testsuite/ChangeLog * lib/gcc-gdb-test.exp (gdb-test): Handle type:var for gdb ptype matching. Catch '<unknown type in ' to recognize older gdb versions. * gcc.dg/guality/const-volatile.c: New test. --- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.dg/guality/const-volatile.c | 83 +++++++++++++++++++++++++ gcc/testsuite/lib/gcc-gdb-test.exp | 47 +++++++++++++- 3 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/guality/const-volatile.c diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 421e006..1abc700 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-07-03 Mark Wielaard <m...@redhat.com> + + * lib/gcc-gdb-test.exp (gdb-test): Handle type:var for gdb ptype + matching. Catch '<unknown type in ' to recognize older gdb versions. + * gcc.dg/guality/const-volatile.c: New test. + 2014-07-02 Mark Wielaard <m...@redhat.com> * gcc.dg/guality/guality.exp: Remove LTO_TORTURE_OPTIONS from diff --git a/gcc/testsuite/gcc.dg/guality/const-volatile.c b/gcc/testsuite/gcc.dg/guality/const-volatile.c new file mode 100644 index 0000000..6c2b617 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/const-volatile.c @@ -0,0 +1,83 @@ +/* debuginfo tests for combinations of const and volatile type qualifiers. */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +int i; +const int ci; +volatile int vi; +const volatile int cvi; + +int *pi; +const int *pci; +volatile int *pvi; +const volatile int *pcvi; + +int * const cip; +int * volatile vip; +int * const volatile cvip; + +volatile struct +{ + const long cli; + const signed char csc; +} vs; + +struct foo +{ + const long cli; + const signed char csc; +}; + +struct foo foo; +const struct foo cfoo; +volatile struct foo vfoo; +const volatile struct foo cvfoo; + +typedef volatile signed char score; + +score s; +const score cs; + +static __attribute__((noclone, noinline)) int +f (const char *progname, volatile struct foo *dummy, const score s) +{ + return progname == 0 || dummy == 0 || dummy->csc == s; +} + +int +main (int argc, char **argv) +{ + score as = argc; + struct foo dummy = { 1, 1 }; + return f (argv[0], &dummy, as) - 1; +} + +/* { dg-final { gdb-test 50 "type:main" "int (int, char **)" } } */ + +/* { dg-final { gdb-test 50 "type:i" "int" } } */ +/* { dg-final { gdb-test 50 "type:ci" "const int" } } */ +/* { dg-final { gdb-test 50 "type:vi" "volatile int" } } */ +/* { dg-final { gdb-test 50 "type:cvi" "const volatile int" } } */ + +/* { dg-final { gdb-test 50 "type:pi" "int *" } } */ +/* { dg-final { gdb-test 50 "type:pci" "const int *" } } */ +/* { dg-final { gdb-test 50 "type:pvi" "volatile int *" } } */ +/* { dg-final { gdb-test 50 "type:pcvi" "const volatile int *" } } */ + +/* { dg-final { gdb-test 50 "type:cip" "int * const" } } */ +/* { dg-final { gdb-test 50 "type:vip" "int * volatile" } } */ +/* { dg-final { gdb-test 50 "type:cvip" "int * const volatile" } } */ + +/* { dg-final { gdb-test 50 "type:vs" "volatile struct { const long cli; const signed char csc; }" } } */ + +/* { dg-final { gdb-test 50 "type:cvip" "int * const volatile" } } */ + +/* { dg-final { gdb-test 50 "type:foo" "struct foo { const long cli; const signed char csc; }" } } */ +/* { dg-final { gdb-test 50 "type:cfoo" "const struct foo { const long cli; const signed char csc; }" } } */ +/* { dg-final { gdb-test 50 "type:vfoo" "volatile struct foo { const long cli; const signed char csc; }" } } */ +/* { dg-final { gdb-test 50 "type:cvfoo" "const volatile struct foo { const long cli; const signed char csc; }" } } */ + +/* { dg-final { gdb-test 58 "type:s" "volatile signed char" } } */ +/* { dg-final { gdb-test 50 "type:cs" "const volatile signed char" } } */ + +/* { dg-final { gdb-test 50 "type:f" "int (const char *, volatile struct foo *, const score)" } } */ diff --git a/gcc/testsuite/lib/gcc-gdb-test.exp b/gcc/testsuite/lib/gcc-gdb-test.exp index d182d88..c729793 100644 --- a/gcc/testsuite/lib/gcc-gdb-test.exp +++ b/gcc/testsuite/lib/gcc-gdb-test.exp @@ -19,7 +19,12 @@ # # Argument 0 is the line number on which to put a breakpoint # Argument 1 is the name of the variable to be checked -# Argument 2 is the expected value of the variable +# possibly prefixed with type: to get the type of the variable +# instead of the value of the variable (the default). +# Argument 2 is the expected value (or type) of the variable +# When asking for the value, the expected value is produced +# calling print on it in gdb. When asking for the type it is +# the literal string with extra whitespace removed. # Argument 3 handles expected failures and the like proc gdb-test { args } { if { ![isnative] || [is_remote target] } { return } @@ -39,6 +44,16 @@ proc gdb-test { args } { upvar 2 name testcase upvar 2 prog prog + # The command to run on the variable + set arg1 [lindex $args 1] + if { [string equal -length 5 "type:" $arg1] == 1 } { + set command "ptype" + set var [string range $arg1 5 end] + } else { + set command "print" + set var $arg1 + } + set gdb_name $::env(GUALITY_GDB_NAME) set testname "$testcase line [lindex $args 0] [lindex $args 1] == [lindex $args 2]" set output_file "[file rootname [file tail $prog]].exe" @@ -47,8 +62,14 @@ proc gdb-test { args } { set fd [open $cmd_file "w"] puts $fd "break [lindex $args 0]" puts $fd "run" - puts $fd "print [lindex $args 1]" - puts $fd "print [lindex $args 2]" + puts $fd "$command $var" + if { $command == "print" } { + # For values, let gdb interpret them by printing them. + puts $fd "print [lindex $args 2]" + } else { + # Since types can span multiple lines, we need an end marker. + puts $fd "echo TYPE_END\\n" + } puts $fd "quit" close $fd @@ -62,12 +83,13 @@ proc gdb-test { args } { remote_expect target [timeout_value] { # Too old GDB - -re "Unhandled dwarf expression|Error in sourced command file" { + -re "Unhandled dwarf expression|Error in sourced command file|<unknown type in " { unsupported "$testname" remote_close target file delete $cmd_file return } + # print var; print expected -re {[\n\r]\$1 = ([^\n\r]*)[\n\r]+\$2 = ([^\n\r]*)[\n\r]} { set first $expect_out(1,string) set second $expect_out(2,string) @@ -83,6 +105,23 @@ proc gdb-test { args } { file delete $cmd_file return } + # ptype var; + -re {[\n\r]type = (.*)[\n\r][\n\r]TYPE_END[\n\r]} { + set type $expect_out(1,string) + # Squash all extra whitespace/newlines that gdb might use for + # "pretty printing" into one so result is just one line. + regsub -all {[\n\r\t ]+} $type " " type + set expected [lindex $args 2] + if { $type == $expected } { + pass "$testname" + } else { + send_log -- "$type != $expected\n" + fail "$testname" + } + remote_close target + file delete $cmd_file + return + } timeout { unsupported "$testname" remote_close target -- 1.7.1