aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2020-11-28 20:19:24 +0000
committerPhilip Herron <philip.herron@embecosm.com>2020-11-28 21:13:22 +0000
commitf28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2 (patch)
tree96c155ee48eef74c82336f2b4da3b1a92381f549 /gcc
parent0db8774645244b08d0e0cd18275ea64ff96f6911 (diff)
downloadgcc-f28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2.zip
gcc-f28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2.tar.gz
gcc-f28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2.tar.bz2
Initial TestSuite setup for make check-rust
This is an initial basic testsuite with one file with expected failures for now.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in6
-rw-r--r--gcc/testsuite/lib/rust-dg.exp106
-rw-r--r--gcc/testsuite/lib/rust.exp213
-rw-r--r--gcc/testsuite/rust.test/compilable/conditional.rs11
-rw-r--r--gcc/testsuite/rust.test/compilable/impl_block.rs14
-rw-r--r--gcc/testsuite/rust.test/compilable/static_function.rs7
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init.rs8
-rw-r--r--gcc/testsuite/rust.test/compilable/type_infer1.rs19
-rw-r--r--gcc/testsuite/rust.test/rust-test.exp449
9 files changed, 832 insertions, 1 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 3293f90..d35b41f 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -30,7 +30,7 @@ GCCRS_INSTALL_NAME := $(shell echo gccrs|sed '$(program_transform_name)')
GCCRS_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrs|sed '$(program_transform_name)')
# Define the names for selecting rust in LANGUAGES.
-rust: gccrs$(exeext) rust1$(exeext)
+rust: rust1$(exeext)
# Tell GNU make to ignore files by these names if they exist.
.PHONY: rust
@@ -88,6 +88,10 @@ rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
# Build hooks.
+lang_checks += check-rust
+lang_checks_parallelized += check-rust
+check_rust_parallelize = 10
+
# Copies its dependencies into the source directory. This generally should be used for generated files
# such as Bison output files which are not version-controlled, but should be included in any release
# tarballs. This target will be executed during a bootstrap if ‘--enable-generated-files-in-srcdir’
diff --git a/gcc/testsuite/lib/rust-dg.exp b/gcc/testsuite/lib/rust-dg.exp
new file mode 100644
index 0000000..e7c9852
--- /dev/null
+++ b/gcc/testsuite/lib/rust-dg.exp
@@ -0,0 +1,106 @@
+# Copyright (C) 2012-2019 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+load_lib gcc-dg.exp
+
+# Define rust callbacks for dg.exp.
+
+proc rust-dg-test { prog do_what extra_tool_flags } {
+ upvar dg-do-what dg-do-what
+
+ # Demote link and run tests to compile-only if D runtime is missing.
+ if ![check_effective_target_d_runtime] {
+ switch $do_what {
+ link -
+ run {
+ set do_what compile
+ set dg-do-what compile
+ }
+ }
+ }
+
+ # Strip rust.test prefix off test names to avoid pathname failures in
+ # some tests.
+ set prog [dg-trim-dirname rust.test $prog]
+
+ set result \
+ [gcc-dg-test-1 rust_target_compile $prog $do_what $extra_tool_flags]
+
+ set comp_output [lindex $result 0]
+ set output_file [lindex $result 1]
+
+ return [list $comp_output $output_file]
+}
+
+proc rust-dg-prune { system text } {
+ return [gcc-dg-prune $system $text]
+}
+
+# Utility routines.
+
+#
+# Modified dg-runtest that can cycle through a list of optimization options
+# as c-torture does.
+#
+
+proc rust-dg-runtest { testcases flags default-extra-flags } {
+ global runtests
+
+ foreach test $testcases {
+ # If we're only testing specific files and this isn't one of
+ # them, skip it.
+
+ if ![runtest_file_p $runtests $test] {
+ continue
+ }
+
+ # Use TORTURE_OPTIONS to cycle through an option list.
+ if [torture-options-exist] then {
+ global torture_with_loops
+ set option_list $torture_with_loops
+ } else {
+ set option_list { "" }
+ }
+
+ set nshort [file tail [file dirname $test]]/[file tail $test]
+
+ foreach flags_t $option_list {
+ verbose "Testing $nshort, $flags $flags_t" 1
+ dg-test $test "$flags $flags_t" ${default-extra-flags}
+ }
+ }
+}
+
+#
+# rust_load -- wrapper around default rust_load to handle tests that
+# require program arguments passed to them.
+#
+
+if { [info procs rust_load] != [list] \
+ && [info procs prev_rust_load] == [list] } {
+ rename rust_load prev_rust_load
+
+ proc rust_load { program args } {
+ global RUST_EXECUTE_ARGS
+ if [info exists RUST_EXECUTE_ARGS] then {
+ set args [concat "{$RUST_EXECUTE_ARGS}"]
+ }
+ #print "Running: $program [lindex $args 0]"
+ set result [eval [list prev_rust_load $program] $args ]
+ return $result
+ }
+}
+
diff --git a/gcc/testsuite/lib/rust.exp b/gcc/testsuite/lib/rust.exp
new file mode 100644
index 0000000..541b052
--- /dev/null
+++ b/gcc/testsuite/lib/rust.exp
@@ -0,0 +1,213 @@
+# Copyright (C) 2012-2020 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+#
+# rust support library routines
+#
+
+load_lib prune.exp
+load_lib gcc-defs.exp
+load_lib timeout.exp
+load_lib target-libpath.exp
+
+#
+# RUST_UNDER_TEST is the compiler under test.
+#
+
+set rust_compile_options ""
+
+
+#
+# rust_version -- extract and print the version number of the compiler
+#
+
+proc rust_version { } {
+ global RUST_UNDER_TEST
+
+ rust_init
+
+ # ignore any arguments after the command
+ set compiler [lindex $RUST_UNDER_TEST 0]
+
+ # verify that the compiler exists
+ if { [is_remote host] || [which $compiler] != 0 } then {
+ set tmp [remote_exec host "$compiler -v"]
+ set status [lindex $tmp 0]
+ set output [lindex $tmp 1]
+ regexp " version \[^\n\r\]*" $output version
+ if { $status == 0 && [info exists version] } then {
+ if [is_remote host] {
+ clone_output "$compiler $version\n"
+ } else {
+ clone_output "[which $compiler] $version\n"
+ }
+ } else {
+ clone_output "Couldn't determine version of $output [which $compiler]\n"
+ }
+ } else {
+ # compiler does not exist (this should have already been detected)
+ warning "$compiler does not exist"
+ }
+}
+
+#
+# rust_include_flags -- include flags for the gcc tree structure
+#
+
+proc rust_include_flags { paths } {
+ global srcdir
+ global TESTING_IN_BUILD_TREE
+
+ set flags ""
+
+ if { [is_remote host] || ![info exists TESTING_IN_BUILD_TREE] } {
+ return "${flags}"
+ }
+
+ set gccpath ${paths}
+
+ return "$flags"
+}
+
+#
+# rust_link_flags -- linker flags for the gcc tree structure
+#
+
+proc rust_link_flags { paths } {
+ global srcdir
+ global ld_library_path
+ global RUST_UNDER_TEST
+ global shlib_ext
+ global SHARED_OPTION
+
+ set gccpath ${paths}
+ set libio_dir ""
+ set flags ""
+ set ld_library_path "."
+ set shlib_ext [get_shlib_extension]
+ set SHARED_OPTION ""
+ verbose "shared lib extension: $shlib_ext"
+
+ set_ld_library_path_env_vars
+
+ return "$flags"
+}
+
+#
+# rust_init -- called at the start of each subdir of tests
+#
+
+proc rust_init { args } {
+ global subdir
+ global rust_initialized
+ global base_dir
+ global tmpdir
+ global libdir
+ global gluefile wrap_flags
+ global objdir srcdir
+ global ALWAYS_DFLAGS
+ global TOOL_EXECUTABLE TOOL_OPTIONS
+ global RUST_UNDER_TEST
+ global TESTING_IN_BUILD_TREE
+ global TEST_ALWAYS_FLAGS
+ global gcc_warning_prefix
+ global gcc_error_prefix
+
+ # We set LC_ALL and LANG to C so that we get the same error messages as expected.
+ setenv LC_ALL C
+ setenv LANG C
+
+ if ![info exists RUST_UNDER_TEST] then {
+ if [info exists TOOL_EXECUTABLE] {
+ set RUST_UNDER_TEST $TOOL_EXECUTABLE
+ } else {
+ if { [is_remote host] || ! [info exists TESTING_IN_BUILD_TREE] } {
+ set RUST_UNDER_TEST [transform gccrs]
+ } else {
+ set RUST_UNDER_TEST [findfile $base_dir/../../gccrs "$base_dir/../../gccrs -B$base_dir/../../" [findfile $base_dir/gccrs "$base_dir/gccrs -B$base_dir/" [transform gccrs]]]
+ }
+ }
+ }
+
+ if ![is_remote host] {
+ if { [which $RUST_UNDER_TEST] == 0 } then {
+ perror "RUST_UNDER_TEST ($RUST_UNDER_TEST) does not exist"
+ exit 1
+ }
+ }
+ if ![info exists tmpdir] {
+ set tmpdir "/tmp"
+ }
+
+ if [info exists gluefile] {
+ unset gluefile
+ }
+
+ rust_maybe_build_wrapper "${tmpdir}/rust-testglue.o"
+
+ set ALWAYS_RUSTFLAGS ""
+
+ # TEST_ALWAYS_FLAGS are flags that should be passed to every
+ # compilation. They are passed first to allow individual
+ # tests to override them.
+ if [info exists TEST_ALWAYS_FLAGS] {
+ lappend ALWAYS_DFLAGS "additional_flags=$TEST_ALWAYS_FLAGS"
+ }
+
+ if ![is_remote host] {
+ if [info exists TOOL_OPTIONS] {
+ lappend ALWAYS_DFLAGS "additional_flags=[rust_include_flags [get_multilibs ${TOOL_OPTIONS}] ]"
+ lappend ALWAYS_DFLAGS "ldflags=[rust_link_flags [get_multilibs ${TOOL_OPTIONS}] ]"
+ } else {
+ lappend ALWAYS_DFLAGS "additional_flags=[rust_include_flags [get_multilibs] ]"
+ lappend ALWAYS_DFLAGS "ldflags=[rust_link_flags [get_multilibs] ]"
+ }
+ }
+
+ if [info exists TOOL_OPTIONS] {
+ lappend ALWAYS_DFLAGS "additional_flags=$TOOL_OPTIONS"
+ }
+
+ verbose -log "ALWAYS_DFLAGS set to $ALWAYS_DFLAGS"
+
+ set gcc_warning_prefix "warning:"
+ set gcc_error_prefix "(fatal )?error:"
+
+ verbose "rust is initialized" 3
+}
+
+#
+# rust_target_compile -- compile a source file
+#
+
+proc rust_target_compile { source dest type options } {
+ global tmpdir
+ global gluefile wrap_flags
+ global ALWAYS_DFLAGS
+ global RUST_UNDER_TEST
+
+ if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } {
+ lappend options "libs=${gluefile}"
+ lappend options "ldflags=${wrap_flags}"
+ }
+
+ lappend options "timeout=[timeout_value]"
+ lappend options "compiler=$RUST_UNDER_TEST"
+
+ set options [concat "$ALWAYS_DFLAGS" $options]
+ set options [dg-additional-files-options $options $source]
+ return [target_compile $source $dest $type $options]
+}
diff --git a/gcc/testsuite/rust.test/compilable/conditional.rs b/gcc/testsuite/rust.test/compilable/conditional.rs
new file mode 100644
index 0000000..2bb3a95
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/conditional.rs
@@ -0,0 +1,11 @@
+fn main() {
+ let mut x = 5;
+
+ if x == 5 {
+ x = 1;
+ } else if x == 3 {
+ x = 2;
+ } else {
+ x = 3;
+ }
+}
diff --git a/gcc/testsuite/rust.test/compilable/impl_block.rs b/gcc/testsuite/rust.test/compilable/impl_block.rs
new file mode 100644
index 0000000..51ed74b
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/impl_block.rs
@@ -0,0 +1,14 @@
+struct Foo {
+ one: i32,
+ two: i32,
+}
+
+impl Foo {
+ fn new(a: i32, b: i32) -> Foo {
+ return Foo { one: a, two: b };
+ }
+}
+
+fn main() {
+ let cake = Foo::new(3, 4);
+}
diff --git a/gcc/testsuite/rust.test/compilable/static_function.rs b/gcc/testsuite/rust.test/compilable/static_function.rs
new file mode 100644
index 0000000..7a564af
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/static_function.rs
@@ -0,0 +1,7 @@
+fn test(x: i32) -> i32 {
+ return x + 1;
+}
+
+fn main() {
+ let call_test = test(1);
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init.rs b/gcc/testsuite/rust.test/compilable/struct_init.rs
new file mode 100644
index 0000000..6081476
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init.rs
@@ -0,0 +1,8 @@
+struct Foo {
+ one: i32,
+ two: i32,
+}
+
+fn main() {
+ let struct_test = Foo { one: 1, two: 2 };
+}
diff --git a/gcc/testsuite/rust.test/compilable/type_infer1.rs b/gcc/testsuite/rust.test/compilable/type_infer1.rs
new file mode 100644
index 0000000..bc4b09a
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/type_infer1.rs
@@ -0,0 +1,19 @@
+struct Foo {
+ one: i32,
+ two: i32,
+}
+
+fn test(x: i32) -> i32 {
+ return x + 1;
+}
+
+fn main() {
+ let logical: bool = true;
+ let an_integer = 5;
+ let mut default_integer = 7;
+
+ default_integer = 1 + an_integer;
+
+ let call_test = test(1);
+ let struct_test = Foo { one: 1, two: 2 };
+}
diff --git a/gcc/testsuite/rust.test/rust-test.exp b/gcc/testsuite/rust.test/rust-test.exp
new file mode 100644
index 0000000..fca3f16
--- /dev/null
+++ b/gcc/testsuite/rust.test/rust-test.exp
@@ -0,0 +1,449 @@
+# Copyright (C) 2012-2019 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Test using the DMD testsuite.
+# Load support procs.
+load_lib rust-dg.exp
+
+#
+# Convert DMD arguments to RUST equivalent
+#
+
+proc rust-convert-args { args } {
+ set out ""
+
+ foreach arg [split [lindex $args 0] " "] {
+ # List of switches kept in ASCII collated order.
+ if [string match "-D" $arg] {
+ lappend out "-fdoc"
+
+ } elseif { [regexp -- {^-I([\w+/-]+)} $arg pattern path] } {
+ lappend out "-I$path"
+
+ } elseif { [regexp -- {^-J([\w+/-]+)} $arg pattern path] } {
+ lappend out "-J$path"
+
+ } elseif [string match "-allinst" $arg] {
+ lappend out "-fall-instantiations"
+
+ } elseif [string match "-betterC" $arg] {
+ lappend out "-fno-druntime"
+
+ } elseif { [string match "-boundscheck" $arg]
+ || [string match "-boundscheck=on" $arg] } {
+ lappend out "-fbounds-check"
+
+ } elseif { [string match "-boundscheck=off" $arg]
+ || [string match "-noboundscheck" $arg] } {
+ lappend out "-fno-bounds-check"
+
+ } elseif [string match "-boundscheck=safeonly" $arg] {
+ lappend out "-fbounds-check=safeonly"
+
+ } elseif [string match "-c" $arg] {
+ lappend out "-c"
+
+ } elseif [string match "-d" $arg] {
+ lappend out "-Wno-deprecated"
+
+ } elseif [string match "-de" $arg] {
+ lappend out "-Wdeprecated"
+ lappend out "-Werror"
+
+ } elseif [string match "-debug" $arg] {
+ lappend out "-fdebug"
+
+ } elseif [regexp -- {^-debug=(\w+)} $arg pattern value] {
+ lappend out "-fdebug=$value"
+
+ } elseif [string match "-dip1000" $arg] {
+ lappend out "-ftransition=dip1000"
+
+ } elseif [string match "-dip25" $arg] {
+ lappend out "-ftransition=dip25"
+
+ } elseif [string match "-dw" $arg] {
+ lappend out "-Wdeprecated"
+ lappend out "-Wno-error"
+
+ } elseif [string match "-fPIC" $arg] {
+ lappend out "-fPIC"
+
+ } elseif { [string match "-g" $arg]
+ || [string match "-gc" $arg] } {
+ lappend out "-g"
+
+ } elseif [string match "-inline" $arg] {
+ lappend out "-finline-functions"
+
+ } elseif [string match "-main" $arg] {
+ lappend out "-fmain"
+
+ } elseif [regexp -- {^-mv=([\w+=./-]+)} $arg pattern value] {
+ lappend out "-fmodule-file=$value"
+
+ } elseif [string match "-O" $arg] {
+ lappend out "-O2"
+
+ } elseif [string match "-release" $arg] {
+ lappend out "-frelease"
+
+ } elseif [regexp -- {^-transition=(\w+)} $arg pattern value] {
+ lappend out "-ftransition=$value"
+
+ } elseif [string match "-unittest" $arg] {
+ lappend out "-funittest"
+
+ } elseif [string match "-verrors=spec" $arg] {
+ lappend out "-Wspeculative"
+
+ } elseif [regexp -- {^-verrors=(\d+)} $arg pattern num] {
+ lappend out "-fmax-errors=$num"
+
+ } elseif [regexp -- {^-version=(\w+)} $arg pattern value] {
+ lappend out "-fversion=$value"
+
+ } elseif [string match "-vtls" $arg] {
+ lappend out "-ftransition=tls"
+
+ } elseif [string match "-w" $arg] {
+ lappend out "-Wall"
+ lappend out "-Werror"
+
+ } elseif [string match "-wi" $arg] {
+ lappend out "-Wall"
+ lappend out "-Wno-error"
+
+ } else {
+ # print "Unhandled Argument: $arg"
+ }
+ }
+
+ return $out
+}
+
+proc rust-copy-extra { base extra } {
+ # Split base, folder/file.
+ set type [file dirname $extra]
+
+ # print "Filename: $base - $extra"
+
+ set fdin [open $base/$extra r]
+ fconfigure $fdin -encoding binary
+
+ file mkdir $type
+ set fdout [open $extra w]
+ fconfigure $fdout -encoding binary
+
+ while { [gets $fdin copy_line] >= 0 } {
+ set out_line $copy_line
+ puts $fdout $out_line
+ }
+
+ close $fdin
+ close $fdout
+
+ # Remove file once test is finished.
+ upvar 2 cleanup_extra_files cleanups
+ lappend cleanups $extra
+
+ return $extra
+}
+
+#
+# Translate DMD test directives to dejagnu equivalent.
+#
+# COMPILE_SEPARATELY: Not handled.
+# EXECUTE_ARGS: Parameters to add to the execution of the test.
+# COMPILED_IMPORTS: List of modules files that are imported by the main
+# source file that should be included in compilation.
+# Currently handled the same as EXTRA_SOURCES.
+# EXTRA_SOURCES: List of extra sources to build and link along with
+# the test.
+# EXTRA_FILES: List of extra files to copy for the test runs.
+# PERMUTE_ARGS: The set of arguments to permute in multiple compiler
+# invocations. An empty set means only one permutation
+# with no arguments.
+# TEST_OUTPUT: The output expected from the compilation.
+# POST_SCRIPT: Not handled.
+# REQUIRED_ARGS: Arguments to add to the compiler command line.
+# DISABLED: Not handled.
+#
+
+proc dmd2dg { base test } {
+ global DEFAULT_DFLAGS
+ global PERMUTE_ARGS
+ global RUST_EXECUTE_ARGS
+
+ set PERMUTE_ARGS $DEFAULT_DFLAGS
+ set RUST_EXECUTE_ARGS ""
+
+ set extra_sources ""
+ set extra_files ""
+
+ # Split base, folder/file.
+ set type [file dirname $test]
+ set name [file tail $test]
+
+ print "Filename: $base - $test"
+
+ set fdin [open $base/$test r]
+ #fconfigure $fdin -encoding binary
+
+ file mkdir $type
+ set fdout [open $test w]
+ #fconfigure $fdout -encoding binary
+
+ while { [gets $fdin copy_line] >= 0 } {
+ set out_line $copy_line
+
+ if [regexp -- {COMPILE_SEPARATELY} $copy_line] {
+ # COMPILE_SEPARATELY is not handled.
+ regsub -- {COMPILE_SEPARATELY.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {DISABLED} $copy_line] {
+ # DISABLED is not handled.
+ regsub -- {DISABLED.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {POST_SCRIPT} $copy_line] {
+ # POST_SCRIPT is not handled
+ regsub -- {POST_SCRIPT.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {PERMUTE_ARGS\s*:\s*(.*)} $copy_line match args] {
+ # PERMUTE_ARGS is handled by rust-do-test.
+ set PERMUTE_ARGS [rust-convert-args $args]
+ regsub -- {PERMUTE_ARGS.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {EXECUTE_ARGS\s*:\s*(.*)} $copy_line match args] {
+ # EXECUTE_ARGS is handled by rust_load.
+ foreach arg $args {
+ lappend RUST_EXECUTE_ARGS $arg
+ }
+ regsub -- {EXECUTE_ARGS.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {REQUIRED_ARGS\s*:\s*(.*)} $copy_line match args] {
+ # Convert all listed arguments to from dmd to rust-style.
+ set new_option "{ dg-additional-options \"[rust-convert-args $args]\" }"
+ regsub -- {REQUIRED_ARGS.*$} $copy_line $new_option out_line
+
+ } elseif [regexp -- {EXTRA_SOURCES\s*:\s*(.*)} $copy_line match sources] {
+ # EXTRA_SOURCES are appended to extra_sources list
+ foreach srcfile $sources {
+ lappend extra_sources $srcfile
+ }
+ regsub -- {EXTRA_SOURCES.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {EXTRA_CPP_SOURCES\s*:\s*(.*)} $copy_line match sources] {
+ # EXTRA_CPP_SOURCES are appended to extra_sources list
+ foreach srcfile $sources {
+ # C++ sources are found in the extra-files directory.
+ lappend extra_sources "extra-files/$srcfile"
+ }
+ regsub -- {EXTRA_CPP_SOURCES.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {EXTRA_FILES\s*:\s*(.*)} $copy_line match files] {
+ # EXTRA_FILES are appended to extra_files list
+ foreach file $files {
+ lappend extra_files $file
+ }
+ regsub -- {EXTRA_FILES.*$} $copy_line "" out_line
+
+ } elseif [regexp -- {COMPILED_IMPORTS\s*:\s*(.*)} $copy_line match sources] {
+ # COMPILED_IMPORTS are appended to extra_sources list
+ foreach import $sources {
+ lappend extra_sources $import
+ }
+ regsub -- {COMPILED_IMPORTS.*$} $copy_line "" out_line
+
+ }
+
+ puts $fdout $out_line
+ }
+
+ # Now that all extra sources and files have been collected, copy them all
+ # to the testsuite build directory.
+ if { [llength $extra_sources] > 0 } {
+ foreach srcfile $extra_sources {
+ rust-copy-extra $base "$type/$srcfile"
+ }
+ set out_line "// { dg-additional-sources \"$extra_sources\" }"
+ puts $fdout $out_line
+ }
+
+ if { [llength $extra_files] > 0 } {
+ foreach file $extra_files {
+ rust-copy-extra $base "$type/$file"
+ }
+ set out_line "// { dg-additional-files \"$extra_files\" }"
+ puts $fdout $out_line
+ }
+
+ # Add specific options for test type
+
+ # DMD's testsuite is extremely verbose, compiler messages from constructs
+ # such as pragma(msg, ...) would otherwise cause tests to fail.
+ set out_line "// { dg-prune-output .* }"
+ puts $fdout $out_line
+
+ # Compilable files are successful if an output is generated.
+ # Fail compilable are successful if an output is not generated.
+ # Runnable must compile, link, and return 0 to be successful by default.
+ switch $type {
+ runnable {
+ if ![isnative] {
+ set out_line "// { dg-final { output-exists } }"
+ puts $fdout $out_line
+ }
+ }
+
+ compilable {
+ set out_line "// { dg-final { output-exists } }"
+ puts $fdout $out_line
+
+ # Check that Ddoc tests also generate a html file.
+ if [regexp -- "ddoc.*" $name] {
+ set ddocfile "[file rootname $name].html"
+ set out_line "// { dg-final { scan-file $ddocfile \"Generated by Ddoc from $test\" } }"
+ puts $fdout $out_line
+ # Cleanup extra generated files.
+ set out_line "// { dg-final { file delete $ddocfile } }"
+ puts $fdout $out_line
+ }
+ }
+
+ fail_compilation {
+ set out_line "// { dg-final { output-exists-not } }"
+ puts $fdout $out_line
+ }
+ }
+
+ close $fdin
+ close $fdout
+
+ return $test
+}
+
+proc rust-permute-options { options } {
+ set result { }
+ set n [expr 1<<[llength $options]]
+ for { set i 0 } { $i<$n } { incr i } {
+ set option ""
+ for { set j 0 } { $j<[llength $options] } { incr j } {
+ if [expr $i & 1 << $j] {
+ append option [lindex $options $j]
+ append option " "
+ }
+ }
+ lappend result $option
+
+ }
+ return $result
+}
+
+
+proc rust-do-test { } {
+ global srcdir subdir
+ global dg-do-what-default
+ global verbose
+
+ # If a testcase doesn't have special options, use these.
+ global DEFAULT_DFLAGS
+ if ![info exists DEFAULT_DFLAGS] then {
+ set DEFAULT_DFLAGS "-g -O2"
+ }
+
+ # These are special options to use on testcase, and override DEFAULT_DFLAGS
+ global PERMUTE_ARGS
+
+ # Set if an extra option should be passed to link to shared druntime.
+ global SHARED_OPTION
+
+ # Additional arguments for rust_load
+ global RUST_EXECUTE_ARGS
+
+ # Initialize `dg'.
+ dg-init
+
+ # Allow blank linkes in output for all of rust.test.
+ global allow_blank_lines
+ set save_allow_blank_lines $allow_blank_lines
+ if { !$allow_blank_lines } {
+ set allow_blank_lines 2
+ }
+
+ # Create rust.test link so test names include that subdir.
+ catch { file link $subdir . }
+
+ # Main loop.
+
+ # set verbose 1
+ # set dg-final-code ""
+ # Find all tests and pass to routine.
+ foreach test [lsort [find $srcdir/$subdir *]] {
+ regexp -- "(.*)/(.+)/(.+)\.rs$" $test match base dir name ext
+ set ext "rs"
+
+ # Skip invalid test directory
+ if { [lsearch "compilable" $dir] == -1 } {
+ continue
+ }
+
+ # Skip invalid test extensions
+ if { [lsearch "rs" $ext] == -1 } {
+ continue
+ }
+
+ # Convert to DG test.
+ set imports [format "-I%s/%s" $base $dir]
+ set cleanup_extra_files ""
+ # Include $subdir prefix so test names follow DejaGnu conventions.
+ set filename "$subdir/[dmd2dg $base $dir/$name.$ext]"
+
+ if { $dir == "runnable" } {
+ append PERMUTE_ARGS " $SHARED_OPTION"
+ }
+ set options [rust-permute-options [lsort -unique $PERMUTE_ARGS]]
+
+ switch $dir {
+ compilable {
+ for { set i 0 } { $i<[llength $options] } { incr i } {
+ set flags [lindex $options $i]
+ # Compilable test may require checking another kind of output file.
+ if [regexp -- "ddoc.*" $name] {
+ set dg-do-what-default "compile"
+ } else {
+ set dg-do-what-default "assemble"
+ }
+ rust-dg-runtest $filename $flags $imports
+ }
+ }
+ }
+
+ # Cleanup test directory.
+ foreach srcfile $cleanup_extra_files {
+ file delete $subdir/$srcfile
+ }
+ file delete $filename
+ }
+
+ set allow_blank_lines $save_allow_blank_lines
+
+ # All done.
+ dg-finish
+}
+
+rust-do-test
+