diff mbox

[v2,6/8] Update gdb test suite for Rust

Message ID 1461789279-15996-7-git-send-email-tom@tromey.com
State New
Headers show

Commit Message

Tom Tromey April 27, 2016, 8:34 p.m. UTC
This updates the gdb test suite for Rust.

2016-04-26  Tom Tromey  <tom@tromey.com>
	    Manish Goregaokar <manishsmail@gmail.com>

	* 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.
---
 gdb/testsuite/ChangeLog             |  18 ++++
 gdb/testsuite/gdb.rust/expr.exp     | 137 ++++++++++++++++++++++++
 gdb/testsuite/gdb.rust/generics.exp |  45 ++++++++
 gdb/testsuite/gdb.rust/generics.rs  |  44 ++++++++
 gdb/testsuite/gdb.rust/methods.exp  |  63 +++++++++++
 gdb/testsuite/gdb.rust/methods.rs   | 129 ++++++++++++++++++++++
 gdb/testsuite/gdb.rust/modules.exp  |  89 ++++++++++++++++
 gdb/testsuite/gdb.rust/modules.rs   |  90 ++++++++++++++++
 gdb/testsuite/gdb.rust/simple.exp   | 206 ++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.rust/simple.rs    |  97 +++++++++++++++++
 gdb/testsuite/lib/future.exp        |  46 +++++++-
 gdb/testsuite/lib/gdb.exp           |  15 +++
 gdb/testsuite/lib/rust-support.exp  |  37 +++++++
 13 files changed, 1015 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.rust/expr.exp
 create mode 100644 gdb/testsuite/gdb.rust/generics.exp
 create mode 100644 gdb/testsuite/gdb.rust/generics.rs
 create mode 100644 gdb/testsuite/gdb.rust/methods.exp
 create mode 100644 gdb/testsuite/gdb.rust/methods.rs
 create mode 100644 gdb/testsuite/gdb.rust/modules.exp
 create mode 100644 gdb/testsuite/gdb.rust/modules.rs
 create mode 100644 gdb/testsuite/gdb.rust/simple.exp
 create mode 100644 gdb/testsuite/gdb.rust/simple.rs
 create mode 100644 gdb/testsuite/lib/rust-support.exp
diff mbox

Patch

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index c3b6104..8abd0ec 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,4 +1,22 @@ 
 2016-04-26  Tom Tromey  <tom@tromey.com>
+	    Manish Goregaokar <manishsmail@gmail.com>
+
+	* 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-04-26  Tom Tromey  <tom@tromey.com>
 
 	* gdb.gdb/unittest.exp: New file.
 
diff --git a/gdb/testsuite/gdb.rust/expr.exp b/gdb/testsuite/gdb.rust/expr.exp
new file mode 100644
index 0000000..99a697e
--- /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 <http://www.gnu.org/licenses/>.
+
+# 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 0000000..27601cc
--- /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 <http://www.gnu.org/licenses/>.
+
+# 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::<u32>(23u32)" " = 23"
+gdb_test "ptype identity::<u32>(23u32)" " = u32"
+gdb_test "print identity::<f64>(23)" " = 23"
+gdb_test "ptype identity::<f64>(23)" " = f64"
+
+gdb_test "print e" " = generics::Hold<i32> \\(7\\)"
+gdb_test "print generics::Hold::<i32> (7)" " = generics::Hold<i32> \\(7\\)"
+gdb_test "print Hold::<i32> (7)" " = generics::Hold<i32> \\(7\\)"
+gdb_test "print identity::< Hold<i32> >(e)" " = generics::Hold<i32> \\(7\\)"
+gdb_test "print identity::<generics::Hold<i32> >(e)" \
+    " = generics::Hold<i32> \\(7\\)"
+gdb_test "print identity::<Hold<i32>>(e)" " = generics::Hold<i32> \\(7\\)"
diff --git a/gdb/testsuite/gdb.rust/generics.rs b/gdb/testsuite/gdb.rust/generics.rs
new file mode 100644
index 0000000..ab5324b
--- /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 <http://www.gnu.org/licenses/>.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+
+#[derive(Clone, Copy)]
+struct Hold<T>(T);
+
+pub fn identity<T>(x: T) -> T { x }
+
+fn dowhatever() { () }
+
+pub fn main() {
+    let a = identity(23u32);
+    let b = identity(23.0f64);
+
+    let d = identity::<u32>(7);
+
+    let e = Hold(7);
+    let f = Hold::<u8>(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 0000000..4a53b70
--- /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 <http://www.gnu.org/licenses/>.
+
+# 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 0000000..d372214
--- /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 <http://www.gnu.org/licenses/>.
+
+#![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 0000000..0678f03
--- /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 <http://www.gnu.org/licenses/>.
+
+# 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<modules::Type>> \\("
+    "  modules::Generic<modules::Type>,"
+    "\\)"
+}
+
+gdb_test_sequence "ptype ::Generic::<::Generic<extern modules::Type> >" "" {
+    "type = struct modules::Generic<modules::Generic<modules::Type>> \\("
+    "  modules::Generic<modules::Type>,"
+    "\\)"
+}
+
+gdb_test_sequence "ptype ::Generic::<::Generic<::mod1::Type>>" "" {
+    "type = struct modules::Generic<modules::Generic<modules::mod1::Type>> \\("
+    "  modules::Generic<modules::mod1::Type>,"
+    "\\)"
+}
+
+gdb_test_sequence "ptype ::Generic::<::Generic<super::Type>>" "" {
+    "type = struct modules::Generic<modules::Generic<modules::mod1::inner::Type>> \\("
+    "  modules::Generic<modules::mod1::inner::Type>,"
+    "\\)"
+}
+
+gdb_test_sequence "ptype ::Generic::<::Generic<self::Type>>" "" {
+    "type = struct modules::Generic<modules::Generic<modules::mod1::inner::innest::Type>> \\("
+    "  modules::Generic<modules::mod1::inner::innest::Type>,"
+    "\\)"
+}
+
+# Not working yet.
+# gdb_test_sequence "ptype ::Generic<Type>" "" ...
+
+# 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 0000000..35829b8
--- /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 <http://www.gnu.org/licenses/>.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+fn f2() {
+    println!("::f2");
+}
+
+pub struct Generic<T>(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<T> (x: T) -> ::Generic<::Generic<T>> {
+                ::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 0000000..a4a2190
--- /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 <http://www.gnu.org/licenses/>.
+
+# 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 0000000..6d6395a
--- /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 <http://www.gnu.org/licenses/>.
+
+#![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<i32>),
+    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 4f771b8..2ecff2e 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 8b0241d..4fefbf9 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.
 
@@ -5238,6 +5243,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 0000000..f9296ab
--- /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 <http://www.gnu.org/licenses/>.
+
+# 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 ""
+}