diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index d1e0c5d95001c..bf27a75c1cfde 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -358,7 +358,8 @@ impl TestProps { fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config: &Config) { if !testfile.is_dir() { let file_contents = fs::read_to_string(testfile).unwrap(); - let file_directives = FileDirectives::from_file_contents(testfile, &file_contents); + let file_directives = + FileDirectives::from_file_contents(config.suite, testfile, &file_contents); iter_directives( config.mode, diff --git a/src/tools/compiletest/src/directives/file.rs b/src/tools/compiletest/src/directives/file.rs index 57186faa56b87..c48d5aea09b92 100644 --- a/src/tools/compiletest/src/directives/file.rs +++ b/src/tools/compiletest/src/directives/file.rs @@ -9,15 +9,42 @@ pub(crate) struct FileDirectives<'a> { } impl<'a> FileDirectives<'a> { - pub(crate) fn from_file_contents(path: &'a Utf8Path, file_contents: &'a str) -> Self { + /// Create a new [`FileDirectives`] by iterating through the lines of `file_contents`. + /// + /// # Note + /// + /// When the `suite` argument matches [`crate::common::TestSuite::CodegenLlvm`] a synthetic + /// `needs-target-std` directive is inserted if needed - that is, if the file does not contain a + /// `#![no_std]` annotation. + /// + /// The objective of this addition is that of making it at least a bit easier to run + /// the codegen-llvm test suite for targets that do not have a stdlib, without forcing test + /// writers to remember yet another directive. + pub(crate) fn from_file_contents( + suite: crate::common::TestSuite, + path: &'a Utf8Path, + file_contents: &'a str, + ) -> Self { let mut lines = vec![]; + let mut generate_needs_std_stub = true; for (line_number, ln) in LineNumber::enumerate().zip(file_contents.lines()) { let ln = ln.trim(); if let Some(directive_line) = line_directive(path, line_number, ln) { + if directive_line.name == "needs-target-std" { + generate_needs_std_stub = false; + } lines.push(directive_line); } + + if ln == "#![no_std]" { + generate_needs_std_stub = false; + } + } + + if generate_needs_std_stub && matches!(suite, crate::common::TestSuite::CodegenLlvm) { + lines.push(crate::directives::line::generate_needs_std(path)) } Self { path, lines } diff --git a/src/tools/compiletest/src/directives/line.rs b/src/tools/compiletest/src/directives/line.rs index 9cc24c98a859d..bf86c7afc4c3a 100644 --- a/src/tools/compiletest/src/directives/line.rs +++ b/src/tools/compiletest/src/directives/line.rs @@ -41,6 +41,19 @@ pub(crate) fn line_directive<'a>( Some(DirectiveLine { file_path, line_number, revision, raw_directive, name }) } +/// Generate a synthetic [`DirectiveLine`] to add the "needs-target-std" directive to a specific +/// test. See [`crate::FileDirectives::from_file_contents`] for an explanation why this is needed. +#[inline] +pub(crate) fn generate_needs_std<'a>(file_path: &'a Utf8Path) -> DirectiveLine<'a> { + DirectiveLine { + file_path, + line_number: LineNumber::ZERO, + revision: None, + raw_directive: "needs-target-std", + name: "needs-target-std", + } +} + /// The (partly) broken-down contents of a line containing a test directive, /// which `iter_directives` passes to its callback function. /// diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs index 0d3777b8e60c6..58d3f81e56c27 100644 --- a/src/tools/compiletest/src/directives/tests.rs +++ b/src/tools/compiletest/src/directives/tests.rs @@ -49,7 +49,7 @@ fn make_test_description( ) -> CollectedTestDesc { let cache = DirectivesCache::load(config); let mut poisoned = false; - let file_directives = FileDirectives::from_file_contents(path, file_contents); + let file_directives = FileDirectives::from_file_contents(config.suite, path, file_contents); let mut aux_props = AuxProps::default(); let test = crate::directives::make_test_description( @@ -268,7 +268,8 @@ fn cfg() -> ConfigBuilder { } fn parse_early_props(config: &Config, contents: &str) -> EarlyProps { - let file_directives = FileDirectives::from_file_contents(Utf8Path::new("a.rs"), contents); + let file_directives = + FileDirectives::from_file_contents(config.suite, Utf8Path::new("a.rs"), contents); EarlyProps::from_file_directives(config, &file_directives) } @@ -842,7 +843,12 @@ fn threads_support() { } fn run_path(poisoned: &mut bool, path: &Utf8Path, file_contents: &str) { - let file_directives = FileDirectives::from_file_contents(path, file_contents); + let file_directives = FileDirectives::from_file_contents( + // Arbitrary suite to prevent from_file_contents to add synthetic directives. + crate::common::TestSuite::Coverage, + path, + file_contents, + ); let result = directives::do_early_directives_check(TestMode::Ui, &file_directives); if result.is_err() { *poisoned = true; diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index a64c7850aad4d..2134dba3cb324 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -855,7 +855,8 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te // Scan the test file to discover its revisions, if any. let file_contents = fs::read_to_string(&test_path).expect("reading test file for directives should succeed"); - let file_directives = FileDirectives::from_file_contents(&test_path, &file_contents); + let file_directives = + FileDirectives::from_file_contents(cx.config.suite, &test_path, &file_contents); if let Err(message) = directives::do_early_directives_check(cx.config.mode, &file_directives) { // FIXME(Zalathar): Overhaul compiletest error handling so that we