From: Tom Tromey Date: Wed, 27 Apr 2016 01:38:43 +0000 (-0600) Subject: Update gdb test suite for Rust X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=67218854b1987d89593ccaf5feaf5b29b1b976f2;p=binutils-gdb.git Update gdb test suite for Rust This updates the gdb test suite for Rust. 2016-05-17 Tom Tromey Manish Goregaokar * lib/rust-support.exp: New file. * lib/gdb.exp (skip_rust_tests): New proc. (build_executable_from_specs): Handle rust. * lib/future.exp (gdb_find_rustc): New proc. (gdb_default_target_compile): Handle rust. * gdb.rust/expr.exp: New file. * gdb.rust/generics.exp: New file. * gdb.rust/generics.rs: New file. * gdb.rust/methods.exp: New file. * gdb.rust/methods.rs: New file. * gdb.rust/modules.exp: New file. * gdb.rust/modules.rs: New file. * gdb.rust/simple.exp: New file. * gdb.rust/simple.rs: New file. --- diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 2cc8585d6a8..afe1e9e1dfc 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,21 @@ +2016-05-17 Tom Tromey + Manish Goregaokar + + * lib/rust-support.exp: New file. + * lib/gdb.exp (skip_rust_tests): New proc. + (build_executable_from_specs): Handle rust. + * lib/future.exp (gdb_find_rustc): New proc. + (gdb_default_target_compile): Handle rust. + * gdb.rust/expr.exp: New file. + * gdb.rust/generics.exp: New file. + * gdb.rust/generics.rs: New file. + * gdb.rust/methods.exp: New file. + * gdb.rust/methods.rs: New file. + * gdb.rust/modules.exp: New file. + * gdb.rust/modules.rs: New file. + * gdb.rust/simple.exp: New file. + * gdb.rust/simple.rs: New file. + 2016-05-17 Tom Tromey * gdb.base/default.exp (set language): Add rust. diff --git a/gdb/testsuite/gdb.rust/expr.exp b/gdb/testsuite/gdb.rust/expr.exp new file mode 100644 index 00000000000..99a697e7e05 --- /dev/null +++ b/gdb/testsuite/gdb.rust/expr.exp @@ -0,0 +1,137 @@ +# Copyright (C) 2016 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 . + +# Test basic expression parsing and evaluation, without requiring a +# Rust compiler. This serves as a smoke test. + +load_lib "rust-support.exp" +if {[skip_rust_tests]} { continue } + +gdb_start + +gdb_test_no_output "set var \$something = 27" + +if {![set_lang_rust]} { + warning "Rust expression tests suppressed." + continue +} + +gdb_test "print 9__97" " = 997" +gdb_test "print -5" " = -5" +gdb_test "print +5" " = 5" +gdb_test "print +-+-5" " = 5" +gdb_test "print 3_2i32" " = 32" +gdb_test "print 32i64" " = 32" +gdb_test "print 8u8" " = 8" +gdb_test "print 0x1f" " = 31" +gdb_test "print 0o07" " = 7" +gdb_test "print 0o70" " = 56" +gdb_test "print 0b1_111" " = 15" +gdb_test "print 32usize" " = 32" +gdb_test "print 0x_4" " = 4" + +gdb_test "print 'z'" " = 122 'z'" +gdb_test "print '\\t'" " = 9 '\\\\t'" +gdb_test "print '\\n'" " = 10 '\\\\n'" +gdb_test "print '\\r'" " = 13 '\\\\r'" +gdb_test "print '\\\\'" " = 92 '\\\\\\\\'" +gdb_test "print '\\0'" " = 0 '\\\\0'" +gdb_test "print '\\''" " = 39 '\\\\''" +gdb_test "print '\\\"'" " = 34 '\"'" +gdb_test "print '\\xff'" " = 255 '\\\\xff'" +gdb_test "print '\\xFF'" " = 255 '\\\\xff'" +gdb_test "print '\\u\{F0eF\}'" " = 61679 '\\\\u\\{00f0ef\\}'" + +gdb_test "print b'z'" " = 122" +gdb_test "print b'\\xfe'" " = 254" +gdb_test "print b'\\t'" " = 9" +gdb_test "print b'\\n'" " = 10" +gdb_test "print b'\\r'" " = 13" +gdb_test "print b'\\\\'" " = 92" +gdb_test "print b'\\0'" " = 0" +gdb_test "print b'\\''" " = 39" +gdb_test "print b'\\\"'" " = 34" +gdb_test "print b'\\xff'" " = 255" + +gdb_test "print 23.5" " = 23.5" +gdb_test "print 23.5e1" " = 235" +gdb_test "print 2e4" " = 20000" +gdb_test "print 2_E+4_f64" " = 20000" +gdb_test "print 5e-1" " = 0.5" +gdb_test "print 5e-1f32" " = 0.5" + +gdb_test "print false" " = false" +gdb_test "print true" " = true" + +gdb_test "print 1+2" " = 3" +gdb_test "print 1i32 + 2i32" " = 3" +gdb_test "print 2.0 - 1.0" " = 1" +gdb_test "print !false" " = true" +gdb_test "print !true" " = false" +gdb_test "print !0u8" " = 255" +gdb_test "print 7 * 7" " = 49" +gdb_test "print 7usize * 7usize" " = 49" +gdb_test "print 42 / 7" " = 6" +gdb_test "print 42 % 7" " = 0" +gdb_test "print 1.0 / 2.0" " = 0.5" +gdb_test "print 1 < 2" " = true" +gdb_test "print !(1 < 2)" " = false" +gdb_test "print 3 + 4 * 7" " = 31" +gdb_test "print 1 > 2" " = false" +gdb_test "print 1 | 2" " = 3" +gdb_test "print 1 & 2" " = 0" +gdb_test "print 3 & 2" " = 2" +gdb_test "print 3 ^ 2" " = 1" +gdb_test "print (1 < 0) || true" " = true" +gdb_test "print (1 > 0) && false" " = false" +gdb_test "print 'z' == 'z'" " = true" +gdb_test "print '\\u{1016f}' != 'q'" " = true" +gdb_test "print 32 <= 32" " = true" +gdb_test "print 32 >= 32" " = true" +gdb_test "print 1 << 5" " = 32" +gdb_test "print 32usize >> 5" " = 1" +gdb_test "ptype 32i32 as f64" "type = f64" + +gdb_test "print ()" " = \\(\\)" + +gdb_test "print \[1,2,3,4\]" " = \\\[1, 2, 3, 4\\\]" +gdb_test "ptype \[1,2,3,4\]" "type = \\\[i32; 4\\\]" +gdb_test "print \[mut 1,2,3,4\]" " = \\\[1, 2, 3, 4\\\]" + +gdb_test "print b\"hi rust\"" " = b\"hi rust\"" +# This isn't rusty syntax yet, but that's another bug -- this is just +# testing that byte escapes work properly. +gdb_test "print b\"\\xddhi bob\"" " = b\"\\\\335hi bob\"" +gdb_test "print b\"has\\0nul\"" " = b\"has\\\\000nul\"" + +gdb_test "print br##\"hi\"##" " = b\"hi\"" +gdb_test "print br##\"hi" "Unexpected EOF in string" +gdb_test "print br##\"hi\"" "Unexpected EOF in string" +gdb_test "print br##\"hi\"#" "Unexpected EOF in string" + +# Test that convenience variables and functions work with the Rust +# parser. +gdb_test "print \$something" " = 27" +gdb_test "print \$_isvoid(\$nosuchvariable)" " = 1" +gdb_test "print \$_isvoid(\$something)" " = 0" + +gdb_test "print \[23usize; 4\]" " = \\\[23, 23, 23, 23\\\]" +gdb_test "ptype \[23usize; 4\]" " = \\\[usize; 4\\\]" +gdb_test "print \[mut 23usize; 4\]" " = \\\[23, 23, 23, 23\\\]" + +# Test a lexer corner case. +gdb_test "print r#" "syntax error in expression, near `#'\\." + +gdb_test "printf \"%d %d\\n\", 23+1, 23-1" "24 22" diff --git a/gdb/testsuite/gdb.rust/generics.exp b/gdb/testsuite/gdb.rust/generics.exp new file mode 100644 index 00000000000..27601cc9439 --- /dev/null +++ b/gdb/testsuite/gdb.rust/generics.exp @@ -0,0 +1,45 @@ +# Copyright (C) 2016 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 . + +# Test expressions involving generics. + +load_lib rust-support.exp +if {[skip_rust_tests]} { + continue +} + +standard_testfile .rs +if {[prepare_for_testing ${testfile}.exp $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "set breakpoint here"] +if {![runto ${srcfile}:$line]} { + untested $testfile + return -1 +} + +gdb_test "print identity::(23u32)" " = 23" +gdb_test "ptype identity::(23u32)" " = u32" +gdb_test "print identity::(23)" " = 23" +gdb_test "ptype identity::(23)" " = f64" + +gdb_test "print e" " = generics::Hold \\(7\\)" +gdb_test "print generics::Hold:: (7)" " = generics::Hold \\(7\\)" +gdb_test "print Hold:: (7)" " = generics::Hold \\(7\\)" +gdb_test "print identity::< Hold >(e)" " = generics::Hold \\(7\\)" +gdb_test "print identity:: >(e)" \ + " = generics::Hold \\(7\\)" +gdb_test "print identity::>(e)" " = generics::Hold \\(7\\)" diff --git a/gdb/testsuite/gdb.rust/generics.rs b/gdb/testsuite/gdb.rust/generics.rs new file mode 100644 index 00000000000..ab5324be6e6 --- /dev/null +++ b/gdb/testsuite/gdb.rust/generics.rs @@ -0,0 +1,44 @@ +// Copyright (C) 2016 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 . + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + + +#[derive(Clone, Copy)] +struct Hold(T); + +pub fn identity(x: T) -> T { x } + +fn dowhatever() { () } + +pub fn main() { + let a = identity(23u32); + let b = identity(23.0f64); + + let d = identity::(7); + + let e = Hold(7); + let f = Hold::(7); + + let g = identity(e); + + let h = Hold(e); + let i = identity(h); + + let z = (); // set breakpoint here + dowhatever() +} diff --git a/gdb/testsuite/gdb.rust/methods.exp b/gdb/testsuite/gdb.rust/methods.exp new file mode 100644 index 00000000000..4a53b709a46 --- /dev/null +++ b/gdb/testsuite/gdb.rust/methods.exp @@ -0,0 +1,63 @@ +# Copyright (C) 2016 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 . + +# Test method calls. + +load_lib rust-support.exp +if {[skip_rust_tests]} { + continue +} + +standard_testfile .rs +if {[prepare_for_testing ${testfile}.exp $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "set breakpoint 1 here"] +if {![runto ${srcfile}:$line]} { + untested $testfile + return -1 +} + +gdb_test "print x" " = methods::HasMethods \\{value: 0\\}" + +gdb_test "print methods::HasMethods{value: 73}" \ + " = methods::HasMethods \\{value: 73\\}" +gdb_test "print methods::HasMethods{..x}" \ + " = methods::HasMethods \\{value: 0\\}" +gdb_test "print methods::HasMethods{value:19, ..x}" \ + " = methods::HasMethods \\{value: 19\\}" + +gdb_test "print x.take()" " = methods::HasMethods \\{value: 0\\}" +gdb_test "print *(x.incr())" " = methods::HasMethods \\{value: 1\\}" +gdb_test "print *((&mut x).incr())" " = methods::HasMethods \\{value: 2\\}" + +gdb_test "print a.value()" " = 23" +gdb_test "print (&mut a).value()" " = 23" +# gdb_test "print a.take_value().0" " = 23" +gdb_test "print b.value()" " = 24" + +gdb_test "print c.value()" " = 452" + +set line [gdb_get_line_number "set breakpoint 2 here"] +gdb_breakpoint ${srcfile}:$line +gdb_continue_to_breakpoint "second breakpoint" + +gdb_test "print *self" " = 23" + + +gdb_test "info functions HasMethods::new" \ + "fn methods::HasMethods::new\\(\\) -> methods::HasMethods;" + diff --git a/gdb/testsuite/gdb.rust/methods.rs b/gdb/testsuite/gdb.rust/methods.rs new file mode 100644 index 00000000000..d37221432b6 --- /dev/null +++ b/gdb/testsuite/gdb.rust/methods.rs @@ -0,0 +1,129 @@ +// Copyright (C) 2016 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 . + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + + +pub trait Whatever { + fn whatever(&self) -> i32; + fn static_i32(x: i32) -> Self; +} + +impl Whatever for i32 { + fn whatever(&self) -> i32 { + *self // set breakpoint 2 here + } + + fn static_i32(x: i32) -> i32 { + x + } +} + +pub struct HasMethods { + value: i32 +} + +impl HasMethods { + pub fn new() -> HasMethods { + HasMethods { value: 0 } + } + + pub fn incr(&mut self) -> &mut HasMethods { + self.value += 1; + self + } + + pub fn take(self) -> HasMethods { + self + } +} + +impl Whatever for HasMethods { + fn whatever(&self) -> i32 { + self.value + } + + fn static_i32(x: i32) -> HasMethods { + HasMethods{value: x} + } +} + +enum SomeEnum { + One, + Two, + Three(i32), + Four{x: i32} +} + +impl SomeEnum { + fn value(&self) -> i32 { + match *self { + SomeEnum::Three(x) => x, + SomeEnum::Four{x} => x, + _ => 0 + } + } + + fn mut_value(&mut self) -> i32 { + match *self { + SomeEnum::Three(x) => x, + SomeEnum::Four{x} => x, + _ => 0 + } + } + + fn take_value(self) -> (i32, SomeEnum) { + (match self { + SomeEnum::Three(x) => x, + SomeEnum::Four{x} => x, + _ => 0 + }, self) + } +} + +enum SimpleEnum { + One, + Two, + Three +} + +impl SimpleEnum { + fn value(&self) -> i32 { + match *self { + SimpleEnum::One => 1, + SimpleEnum::Two => 2, + SimpleEnum::Three => 452, + } + } +} + +fn main() { + let mut a = SomeEnum::Three(23); + let av = a.value(); + let amv = (&mut a).mut_value(); + let atv = a.take_value(); + let b = SomeEnum::Four{x: 24}; + let bv = b.value(); + let c = SimpleEnum::Three; + let d = c.value(); + let mut x = HasMethods::new(); + x.incr(); // set breakpoint 1 here + (&mut x).incr(); + let y = 23i32.whatever(); + println!("{}", y); + let z = x.take(); +} diff --git a/gdb/testsuite/gdb.rust/modules.exp b/gdb/testsuite/gdb.rust/modules.exp new file mode 100644 index 00000000000..0678f037325 --- /dev/null +++ b/gdb/testsuite/gdb.rust/modules.exp @@ -0,0 +1,89 @@ +# Copyright (C) 2016 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 . + +# Test name lookup. + +load_lib rust-support.exp +if {[skip_rust_tests]} { + continue +} + +standard_testfile .rs +if {[prepare_for_testing ${testfile}.exp $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "set breakpoint here"] +if {![runto ${srcfile}:$line]} { + untested $testfile + return -1 +} + +# Currently a closure type is not described by rustc. +# https://github.com/rust-lang/rust/issues/33121 +# gdb_test "call f2()" "lambda f2" + +gdb_test "call f3()" "mod1::inner::innest::f3" +gdb_test "call self::f2()" "mod1::inner::innest::f2" +gdb_test "call self::super::f2()" "mod1::inner::f2" +gdb_test "call super::f2()" "mod1::inner::f2" +gdb_test "call self::super::super::f2()" "mod1::f2" +gdb_test "call super::super::f2()" "mod1::f2" +gdb_test "call ::f2()" "::f2" +gdb_test "call super::super::super::f2()" \ + "Too many super:: uses from 'modules::mod1::inner::innest'" +gdb_test "call extern modules::mod1::f2()" "mod1::f2" + +gdb_test_sequence "ptype ::Generic::<::Generic<::Type> >" "" { + "type = struct modules::Generic> \\(" + " modules::Generic," + "\\)" +} + +gdb_test_sequence "ptype ::Generic::<::Generic >" "" { + "type = struct modules::Generic> \\(" + " modules::Generic," + "\\)" +} + +gdb_test_sequence "ptype ::Generic::<::Generic<::mod1::Type>>" "" { + "type = struct modules::Generic> \\(" + " modules::Generic," + "\\)" +} + +gdb_test_sequence "ptype ::Generic::<::Generic>" "" { + "type = struct modules::Generic> \\(" + " modules::Generic," + "\\)" +} + +gdb_test_sequence "ptype ::Generic::<::Generic>" "" { + "type = struct modules::Generic> \\(" + " modules::Generic," + "\\)" +} + +# Not working yet. +# gdb_test_sequence "ptype ::Generic" "" ... + +# Some basic linespec tests. +foreach mod {mod1::inner::innest mod1::inner mod1 {}} { + if {$mod != ""} { + append mod :: + } + gdb_breakpoint modules::${mod}f2 message + gdb_breakpoint "*::${mod}f2" message +} diff --git a/gdb/testsuite/gdb.rust/modules.rs b/gdb/testsuite/gdb.rust/modules.rs new file mode 100644 index 00000000000..35829b8fc40 --- /dev/null +++ b/gdb/testsuite/gdb.rust/modules.rs @@ -0,0 +1,90 @@ +// Copyright (C) 2016 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 . + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + +fn f2() { + println!("::f2"); +} + +pub struct Generic(T); + +pub struct Type; + +pub mod mod1 { + pub struct Type(usize, isize); + + pub mod inner { + pub struct Type(f64); + + pub mod innest { + pub struct Type {pub x : u32} + + fn wrap (x: T) -> ::Generic<::Generic> { + ::Generic(::Generic(x)) + } + + pub fn f1 () { + struct Type(i8); + + let x: u8 = 0; + + let ct = ::Type; + let ctg = wrap(ct); + let m1t = ::mod1::Type(23, 97); + let m1tg = wrap(m1t); + let innert = super::Type(10101.5); + let innertg = wrap(innert); + let innestt = self::Type{x: 0xfff}; + let innesttg = wrap(innestt); + let f1t = Type(9); + let f1tg = wrap(f1t); + + let f2 = || println!("lambda f2"); + + f2(); // set breakpoint here + f3(); + self::f2(); + super::f2(); + self::super::f2(); + self::super::super::f2(); + super::super::f2(); + ::f2(); + } + + pub fn f2() { + println!("mod1::inner::innest::f2"); + } + + pub fn f3() { + println!("mod1::inner::innest::f3"); + } + } + + pub fn f2() { + println!("mod1::inner::f2"); + } + } + + pub fn f2() { + println!("mod1::f2"); + } +} + +fn main () { + mod1::inner::innest::f1(); +} diff --git a/gdb/testsuite/gdb.rust/simple.exp b/gdb/testsuite/gdb.rust/simple.exp new file mode 100644 index 00000000000..a4a21904426 --- /dev/null +++ b/gdb/testsuite/gdb.rust/simple.exp @@ -0,0 +1,206 @@ +# Copyright (C) 2016 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 . + +# Test expression parsing and evaluation that requires Rust compiler. + +load_lib rust-support.exp +if {[skip_rust_tests]} { + continue +} + +standard_testfile .rs +if {[prepare_for_testing ${testfile}.exp $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "set breakpoint here"] +if {![runto ${srcfile}:$line]} { + untested $testfile + return -1 +} + +gdb_test "print a" " = \\(\\)" +gdb_test "ptype a" " = \\(\\)" + +gdb_test "print b" " = \\\[\\\]" +gdb_test "ptype b" " = \\\[i32; 0\\\]" +gdb_test "print *(&b as *const \[i32; 0\])" " = \\\[\\\]" +gdb_test "print *(&b as *const \[i32; 0_0\])" " = \\\[\\\]" + +gdb_test "print c" " = 99" +gdb_test "ptype c" " = i32" + +gdb_test "print c = 87" " = \\(\\)" +gdb_test "print c" " = 87" +gdb_test "print c += 3" " = \\(\\)" +gdb_test "print c" " = 90" +gdb_test "print c -= 90" " = \\(\\)" +gdb_test "print c" " = 0" +gdb_test "print *&c" " = 0" +gdb_test "print *(&c as &i32)" " = 0" +gdb_test "print *(&c as *const i32)" " = 0" +gdb_test "print *(&c as *mut i32)" " = 0" + +gdb_test "print j" " = simple::Unit" +gdb_test "ptype j" " = struct simple::Unit" +gdb_test "print simple::Unit" " = simple::Unit" + +gdb_test "print g" " = \\(u8 \\(\\*\\)\\\[6\\\]\\) $hex b\"hi bob\"" +gdb_test "ptype g" " = u8 \\(\\*\\)\\\[6\\\]" + +gdb_test "print v" " = simple::Something::Three" +gdb_test_sequence "ptype v" "" { + " = enum simple::Something \\{" + " One," + " Two," + " Three," + "\\}" +} + +gdb_test "print w" " = \\\[1, 2, 3, 4\\\]" +gdb_test "ptype w" " = \\\[i32; 4\\\]" +gdb_test "print w\[2\]" " = 3" +gdb_test "print w\[2\] @ 2" " = \\\[3, 4\\\]" +gdb_test "print fromslice" " = 3" +gdb_test "print slice\[0\]" " = 3" +gdb_test "print slice as &\[i32\]\[0\]" " = 3" + +gdb_test "print x" " = \\(23, 25\\.5\\)" +gdb_test "ptype x" " = \\(i32, f64\\)" +gdb_test "print x as (i32,f64)" " = \\(23, 25\\.5\\)" + +gdb_test "print y" " = simple::HiBob \\{field1: 7, field2: 8\\}" +gdb_test_sequence "ptype y" "" { + " = struct simple::HiBob \\{" + " field1: i32," + " field2: u64," + "\\}" +} +gdb_test "print y.field2" " = 8" + +gdb_test "print z" " = simple::ByeBob \\(7, 8\\)" +gdb_test_sequence "ptype z" "" { + " = struct simple::ByeBob \\(" + " i32," + " u64," + "\\)" +} +gdb_test "print z.1" " = 8" + +gdb_test_sequence "ptype simple::ByeBob" "" { + " = struct simple::ByeBob \\(" + " i32," + " u64," + "\\)" +} +gdb_test "print simple::ByeBob(0xff, 5)" \ + " = simple::ByeBob \\(255, 5\\)" +gdb_test "print simple::ByeBob\{field1: 0xff, field2:5\}" \ + "Struct expression applied to non-struct type" + +gdb_test "print simple::HiBob(0xff, 5)" \ + "Type simple::HiBob is not a tuple struct" +gdb_test "print nosuchsymbol" \ + "No symbol 'nosuchsymbol' in current context" + +gdb_test "print e" " = simple::MoreComplicated::Two\\(73\\)" +gdb_test "print e2" \ + " = simple::MoreComplicated::Four\\{this: true, is: 8, a: 109 'm', struct_: 100, variant: 10\\}" + +gdb_test_sequence "ptype e" "" { + " = enum simple::MoreComplicated \\{" + " One," + " Two\\(i32\\)," + " Three\\(simple::HiBob\\)," + " Four\\{this: bool, is: u8, a: char, struct_: u64, variant: u32\\}," + "\\}" +} + +gdb_test "print e.0" " = 73" +gdb_test "print e.1" \ + "Cannot access field 1 of variant simple::MoreComplicated::Two, there are only 1 fields" +gdb_test "print e.foo" \ + "Attempting to access named field foo of tuple variant simple::MoreComplicated::Two, which has only anonymous fields" + +gdb_test "print e2.variant" " = 10" +gdb_test "print e2.notexist" \ + "Could not find field notexist of struct variant simple::MoreComplicated::Four" +gdb_test "print e2.0" \ + "Variant simple::MoreComplicated::Four is not a tuple variant" + +gdb_test "print k" " = simple::SpaceSaver::Nothing" +gdb_test "print l" " = simple::SpaceSaver::Thebox\\(9, $hex\\)" +gdb_test "print *l.1" " = 1729" + +gdb_test "print diff2(3, 7)" " = -4" +gdb_test "print self::diff2(8, 9)" " = -1" +gdb_test "print ::diff2(23, -23)" " = 46" + +gdb_test "ptype diff2" "fn \\(i32, i32\\) -> i32" + +gdb_test "print (diff2 as fn(i32, i32) -> i32)(19, -2)" " = 21" + +# We need the ".*" because currently we don't extract the length and +# use it to intelligently print the string data. +gdb_test "print \"hello rust\"" \ + " = &str \\{data_ptr: $hex \"hello rust.*\", length: 10\\}" +gdb_test "print \"hello" "Unexpected EOF in string" +gdb_test "print r##\"hello \" rust\"##" \ + " = &str \\{data_ptr: $hex \"hello \\\\\" rust.*\", length: 12\\}" +gdb_test "print r\"hello" "Unexpected EOF in string" +gdb_test "print r###\"###hello\"" "Unexpected EOF in string" +gdb_test "print r###\"###hello\"##" "Unexpected EOF in string" +gdb_test "print r###\"hello###" "Unexpected EOF in string" + +gdb_test "print 0..5" " = .*::ops::Range.* \\{start: 0, end: 5\\}" +gdb_test "print ..5" " = .*::ops::RangeTo.* \\{end: 5\\}" +gdb_test "print 5.." " = .*::ops::RangeFrom.* \\{start: 5\\}" +gdb_test "print .." " = .*::ops::RangeFull" + +proc test_one_slice {svar length base range} { + global hex + + set result " = &\\\[.*\\\] \\{data_ptr: $hex, length: $length\\}" + + gdb_test "print $svar" $result + gdb_test "print &${base}\[${range}\]" $result +} + +test_one_slice slice 1 w 2..3 +test_one_slice slice2 1 slice 0..1 + +test_one_slice all1 4 w .. +test_one_slice all2 1 slice .. + +test_one_slice from1 3 w 1.. +test_one_slice from2 0 slice 1.. + +test_one_slice to1 3 w ..3 +test_one_slice to2 1 slice ..1 + +gdb_test "print w\[2..3\]" "Can't take slice of array without '&'" + + +gdb_test_sequence "complete print y.f" "" \ + {"print y.field1" "print y.field2"} +gdb_test_sequence "complete print y." "" \ + {"print y.field1" "print y.field2"} + +# Unimplemented, but we can at least test the parser productions. +gdb_test "print (1,2,3)" "Tuple expressions not supported yet" +gdb_test "print (1,)" "Tuple expressions not supported yet" +gdb_test "print (1)" " = 1" + +gdb_test "print 23..97.0" "Range expression with different types" diff --git a/gdb/testsuite/gdb.rust/simple.rs b/gdb/testsuite/gdb.rust/simple.rs new file mode 100644 index 00000000000..6d6395a8c33 --- /dev/null +++ b/gdb/testsuite/gdb.rust/simple.rs @@ -0,0 +1,97 @@ +// Copyright (C) 2016 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 . + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + + +pub struct HiBob { + pub field1: i32, + field2: u64, +} + +struct ByeBob(i32, u64); + +enum Something { + One, + Two, + Three +} + +enum MoreComplicated { + One, + Two(i32), + Three(HiBob), + Four{this: bool, is: u8, a: char, struct_: u64, variant: u32}, +} + +fn diff2(x: i32, y: i32) -> i32 { + x - y +} + +pub struct Unit; + +// This triggers the non-zero optimization that yields a different +// enum representation in the debug info. +enum SpaceSaver { + Thebox(u8, Box), + Nothing, +} + +fn main () { + let a = (); + let b : [i32; 0] = []; + + let mut c = 27; + let d = c = 99; + + let e = MoreComplicated::Two(73); + let e2 = MoreComplicated::Four {this: true, is: 8, a: 'm', + struct_: 100, variant: 10}; + + let f = "hi bob"; + let g = b"hi bob"; + let h = b'9'; + + let i = ["whatever"; 8]; + + let j = Unit; + + let k = SpaceSaver::Nothing; + let l = SpaceSaver::Thebox(9, Box::new(1729)); + + let v = Something::Three; + let w = [1,2,3,4]; + let x = (23, 25.5); + let y = HiBob {field1: 7, field2: 8}; + let z = ByeBob(7, 8); + + let slice = &w[2..3]; + let fromslice = slice[0]; + let slice2 = &slice[0..1]; + + let all1 = &w[..]; + let all2 = &slice[..]; + + let from1 = &w[1..]; + let from2 = &slice[1..]; + + let to1 = &w[..3]; + let to2 = &slice[..1]; + + println!("{}, {}", x.0, x.1); // set breakpoint here + println!("{}", diff2(92, 45)); +} diff --git a/gdb/testsuite/lib/future.exp b/gdb/testsuite/lib/future.exp index 4f771b8cfc7..2ecff2ef200 100644 --- a/gdb/testsuite/lib/future.exp +++ b/gdb/testsuite/lib/future.exp @@ -105,6 +105,22 @@ proc gdb_find_go_linker {} { return [find_go] } +proc gdb_find_rustc {} { + global tool_root_dir + if {![is_remote host]} { + set rustc [lookfor_file $tool_root_dir rustc] + if {$rustc == ""} { + set rustc rustc + } + } else { + set rustc "" + } + if {$rustc != ""} { + append rustc " --color never" + } + return $rustc +} + proc gdb_find_ldd {} { global LDD_FOR_TARGET if [info exists LDD_FOR_TARGET] { @@ -262,6 +278,18 @@ proc gdb_default_target_compile {source destfile type options} { } } + if { $i == "rust" } { + set compiler_type "rust" + if {[board_info $dest exists rustflags]} { + append add_flags " [target_info rustflags]" + } + if {[board_info $dest exists rustflags]} { + set compiler [target_info rustflags] + } else { + set compiler [find_rustc] + } + } + if {[regexp "^dest=" $i]} { regsub "^dest=" $i "" tmp if {[board_info $tmp exists name]} { @@ -324,6 +352,7 @@ proc gdb_default_target_compile {source destfile type options} { global GNATMAKE_FOR_TARGET global GO_FOR_TARGET global GO_LD_FOR_TARGET + global RUSTC_FOR_TARGET if {[info exists GNATMAKE_FOR_TARGET]} { if { $compiler_type == "ada" } { @@ -370,6 +399,12 @@ proc gdb_default_target_compile {source destfile type options} { } } + if {[info exists RUSTC_FOR_TARGET]} { + if {$compiler_type == "rust"} { + set compiler $RUSTC_FOR_TARGET + } + } + if { $type == "executable" && $linker != "" } { set compiler $linker } @@ -388,7 +423,11 @@ proc gdb_default_target_compile {source destfile type options} { } if {$type == "object"} { - append add_flags " -c" + if {$compiler_type == "rust"} { + append add_flags "--emit obj" + } else { + append add_flags " -c" + } } if { $type == "preprocess" } { @@ -605,6 +644,11 @@ if {[info procs find_gdc] == ""} { set use_gdb_compile 1 } +if {[info procs find_rustc] == ""} { + rename gdb_find_rustc find_rustc + set use_gdb_compile 1 +} + if {$use_gdb_compile} { catch {rename default_target_compile {}} rename gdb_default_target_compile default_target_compile diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 6d25b0c7727..436f708f5bd 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -1733,6 +1733,11 @@ proc skip_d_tests {} { return 0 } +# Return 1 to skip Rust tests, 0 to try them. +proc skip_rust_tests {} { + return [expr {![isnative]}] +} + # Return a 1 for configurations that do not support Python scripting. # PROMPT_REGEXP is the expected prompt. @@ -5258,6 +5263,16 @@ proc build_executable_from_specs {testname executable options args} { } } set ret [$func $sources_path "${binfile}" $options] + } elseif {[lsearch -exact $options rust] != -1} { + set sources_path {} + foreach {s local_options} $args { + if { [regexp "^/" "$s"] } then { + lappend sources_path "$s" + } else { + lappend sources_path "$srcdir/$subdir/$s" + } + } + set ret [gdb_compile_rust $sources_path "${binfile}" $options] } else { set objects {} set i 0 diff --git a/gdb/testsuite/lib/rust-support.exp b/gdb/testsuite/lib/rust-support.exp new file mode 100644 index 00000000000..f9296ab9a2d --- /dev/null +++ b/gdb/testsuite/lib/rust-support.exp @@ -0,0 +1,37 @@ +# Copyright 2016 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 . + +# Auxiliary function to set the language to Rust. +# The result is 1 (true) for success, 0 (false) for failure. +proc set_lang_rust {} { + if [gdb_test_no_output "set language rust"] { + return 0 + } + if [gdb_test "show language" ".* source language is \"rust\"." \ + "set language to \"rust\""] { + return 0 + } + return 1 +} + +proc gdb_compile_rust {sources dest options} { + if {[llength $sources] > 1} { + error "gdb rust setup can only compile one source file at a time" + } + if {[gdb_compile [lindex $sources 0] $dest executable $options] != ""} { + return -1 + } + return "" +}