diff mbox

Add guality [p]type test.

Message ID 1404381209-11280-1-git-send-email-mjw@redhat.com
State New
Headers show

Commit Message

Mark Wielaard July 3, 2014, 9:53 a.m. UTC
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

Comments

Jakub Jelinek July 3, 2014, 10:05 a.m. UTC | #1
On Thu, Jul 03, 2014 at 11:53:29AM +0200, Mark Wielaard wrote:
> 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.

Is what gdb prints for ptype stable across different gdb versions (except
for whitespace that you canonicalize)?  If yes, this looks good to me.

	Jakub
Mark Wielaard July 3, 2014, 11:15 a.m. UTC | #2
On Thu, 2014-07-03 at 12:05 +0200, Jakub Jelinek wrote:
> On Thu, Jul 03, 2014 at 11:53:29AM +0200, Mark Wielaard wrote:
> > 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.
> 
> Is what gdb prints for ptype stable across different gdb versions (except
> for whitespace that you canonicalize)?  If yes, this looks good to me.

Yes, I believe it is (I tested against gdb git master and gdb 7.6.50).
It tries to print the expression as a canonical C type, so it should be
stable. GDB itself contains similar tests, but for pregenerated .S files
or synthetic generated DWARF. This just extends it to make sure gcc and
gdb agree on the produced/consumed debuginfo.

Cheers,

Mark
Tom Tromey July 3, 2014, 7:43 p.m. UTC | #3
>> Is what gdb prints for ptype stable across different gdb versions (except
>> for whitespace that you canonicalize)?  If yes, this looks good to me.

Mark> Yes, I believe it is (I tested against gdb git master and gdb 7.6.50).
Mark> It tries to print the expression as a canonical C type, so it should be
Mark> stable. GDB itself contains similar tests, but for pregenerated .S files
Mark> or synthetic generated DWARF. This just extends it to make sure gcc and
Mark> gdb agree on the produced/consumed debuginfo.

I think it should be reasonably reliable.
Something like this (but for value-printing) is already done in the
libstdc++ test suite.

Tom
Richard Biener July 7, 2014, 9:57 a.m. UTC | #4
On Thu, Jul 3, 2014 at 11:53 AM, Mark Wielaard <mjw@redhat.com> wrote:
> 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.

You could add a dg-skip-if "" { *-*-* } { "-flto" } with a comment.
Btw, why doesn't it succeed with LTO?  I suspect it's because
we drop the unused variables - try adding __attribute__((used)) to
them.  Same effect should be observable with -fwhole-program
(which doesn't use LTO).

Richard.

> 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  <mjw@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  <mjw@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
>
diff mbox

Patch

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