From 505a2084e683662e1521b3ba64e23e9271f8e192 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 29 Sep 2025 22:57:14 +1000 Subject: [PATCH 1/3] Split off a separate name/value parser for debuginfo test commands --- src/tools/compiletest/src/directives.rs | 2 +- src/tools/compiletest/src/runtest/debugger.rs | 27 ++++++++++--------- .../compiletest/src/runtest/debuginfo.rs | 6 ++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index e84a22787668d..e864594ade2e8 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -1121,7 +1121,7 @@ impl Config { line.starts_with("no-") && self.parse_name_directive(&line[3..], directive) } - pub fn parse_name_value_directive( + fn parse_name_value_directive( &self, line: &str, directive: &str, diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index ba824124e875d..3d439e98eb7e1 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -4,7 +4,6 @@ use std::io::{BufRead, BufReader}; use camino::{Utf8Path, Utf8PathBuf}; -use crate::common::Config; use crate::runtest::ProcRes; /// Representation of information to invoke a debugger and check its output @@ -20,11 +19,7 @@ pub(super) struct DebuggerCommands { } impl DebuggerCommands { - pub fn parse_from( - file: &Utf8Path, - config: &Config, - debugger_prefix: &str, - ) -> Result { + pub fn parse_from(file: &Utf8Path, debugger_prefix: &str) -> Result { let command_directive = format!("{debugger_prefix}-command"); let check_directive = format!("{debugger_prefix}-check"); @@ -47,14 +42,10 @@ impl DebuggerCommands { continue; }; - if let Some(command) = - config.parse_name_value_directive(&line, &command_directive, file, line_no) - { + if let Some(command) = parse_name_value(&line, &command_directive) { commands.push(command); } - if let Some(pattern) = - config.parse_name_value_directive(&line, &check_directive, file, line_no) - { + if let Some(pattern) = parse_name_value(&line, &check_directive) { check_lines.push((line_no, pattern)); } } @@ -114,6 +105,18 @@ impl DebuggerCommands { } } +/// Split off from the main `parse_name_value_directive`, so that improvements +/// to directive handling aren't held back by debuginfo test commands. +fn parse_name_value(line: &str, name: &str) -> Option { + if let Some(after_name) = line.strip_prefix(name) + && let Some(value) = after_name.strip_prefix(':') + { + Some(value.to_owned()) + } else { + None + } +} + /// Check that the pattern in `check_line` applies to `line`. Returns `true` if they do match. fn check_single_line(line: &str, check_line: &str) -> bool { // Allow check lines to leave parts unspecified (e.g., uninitialized diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 071c0863b7e9f..9175a38ffa5c9 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -59,7 +59,7 @@ impl TestCx<'_> { } // Parse debugger commands etc from test files - let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "cdb") + let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "cdb") .unwrap_or_else(|e| self.fatal(&e)); // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands @@ -130,7 +130,7 @@ impl TestCx<'_> { } fn run_debuginfo_gdb_test_no_opt(&self) { - let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "gdb") + let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "gdb") .unwrap_or_else(|e| self.fatal(&e)); let mut cmds = dbg_cmds.commands.join("\n"); @@ -397,7 +397,7 @@ impl TestCx<'_> { } // Parse debugger commands etc from test files - let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "lldb") + let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "lldb") .unwrap_or_else(|e| self.fatal(&e)); // Write debugger script: From ffaf607cf2743f1206a739e02f7b194a4767f9a8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 30 Sep 2025 12:20:42 +1000 Subject: [PATCH 2/3] Remove `parse_negative_name_directive` This isn't actually used for anything, and its presence complicates the migration to `DirectiveLine`. --- src/tools/compiletest/src/directives.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index e864594ade2e8..01a663b016f7d 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -1117,10 +1117,6 @@ impl Config { && matches!(line.as_bytes().get(directive.len()), None | Some(&b' ') | Some(&b':')) } - fn parse_negative_name_directive(&self, line: &str, directive: &str) -> bool { - line.starts_with("no-") && self.parse_name_directive(&line[3..], directive) - } - fn parse_name_value_directive( &self, line: &str, @@ -1149,18 +1145,8 @@ impl Config { } fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) { - match value { - true => { - if self.parse_negative_name_directive(line, directive) { - *value = false; - } - } - false => { - if self.parse_name_directive(line, directive) { - *value = true; - } - } - } + // If the flag is already true, don't bother looking at the directive. + *value = *value || self.parse_name_directive(line, directive); } fn set_name_value_directive( From e491056ac5722bd404dd6c326c76f457eb08b467 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 29 Sep 2025 22:25:23 +1000 Subject: [PATCH 3/3] Pass around `DirectiveLine` instead of bare strings --- src/tools/compiletest/src/directives.rs | 197 +++++++----------- .../compiletest/src/directives/auxiliary.rs | 35 ++-- src/tools/compiletest/src/directives/cfg.rs | 14 +- src/tools/compiletest/src/directives/needs.rs | 6 +- 4 files changed, 107 insertions(+), 145 deletions(-) diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 01a663b016f7d..e6916610190e6 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -63,9 +63,10 @@ impl EarlyProps { &mut poisoned, testfile, rdr, - &mut |DirectiveLine { line_number, raw_directive: ln, .. }| { - parse_and_update_aux(config, ln, testfile, line_number, &mut props.aux); - config.parse_and_update_revisions(testfile, line_number, ln, &mut props.revisions); + // (dummy comment to force args into vertical layout) + &mut |ref ln: DirectiveLine<'_>| { + parse_and_update_aux(config, ln, testfile, &mut props.aux); + config.parse_and_update_revisions(testfile, ln, &mut props.revisions); }, ); @@ -367,8 +368,8 @@ impl TestProps { &mut poisoned, testfile, file, - &mut |directive @ DirectiveLine { line_number, raw_directive: ln, .. }| { - if !directive.applies_to_test_revision(test_revision) { + &mut |ref ln: DirectiveLine<'_>| { + if !ln.applies_to_test_revision(test_revision) { return; } @@ -378,7 +379,6 @@ impl TestProps { ln, ERROR_PATTERN, testfile, - line_number, &mut self.error_patterns, |r| r, ); @@ -386,7 +386,6 @@ impl TestProps { ln, REGEX_ERROR_PATTERN, testfile, - line_number, &mut self.regex_error_patterns, |r| r, ); @@ -395,7 +394,6 @@ impl TestProps { ln, DOC_FLAGS, testfile, - line_number, &mut self.doc_flags, |r| r, ); @@ -414,7 +412,7 @@ impl TestProps { } if let Some(flags) = - config.parse_name_value_directive(ln, COMPILE_FLAGS, testfile, line_number) + config.parse_name_value_directive(ln, COMPILE_FLAGS, testfile) { let flags = split_flags(&flags); for flag in &flags { @@ -425,39 +423,28 @@ impl TestProps { self.compile_flags.extend(flags); } if config - .parse_name_value_directive( - ln, - INCORRECT_COMPILER_FLAGS, - testfile, - line_number, - ) + .parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS, testfile) .is_some() { panic!("`compiler-flags` directive should be spelled `compile-flags`"); } - if let Some(edition) = config.parse_edition(ln, testfile, line_number) { + if let Some(edition) = config.parse_edition(ln, testfile) { // The edition is added at the start, since flags from //@compile-flags must // be passed to rustc last. self.compile_flags.insert(0, format!("--edition={}", edition.trim())); has_edition = true; } - config.parse_and_update_revisions( - testfile, - line_number, - ln, - &mut self.revisions, - ); + config.parse_and_update_revisions(testfile, ln, &mut self.revisions); - if let Some(flags) = - config.parse_name_value_directive(ln, RUN_FLAGS, testfile, line_number) + if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS, testfile) { self.run_flags.extend(split_flags(&flags)); } if self.pp_exact.is_none() { - self.pp_exact = config.parse_pp_exact(ln, testfile, line_number); + self.pp_exact = config.parse_pp_exact(ln, testfile); } config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice); @@ -479,9 +466,7 @@ impl TestProps { ); config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic); - if let Some(m) = - config.parse_name_value_directive(ln, PRETTY_MODE, testfile, line_number) - { + if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE, testfile) { self.pretty_mode = m; } @@ -492,13 +477,12 @@ impl TestProps { ); // Call a helper method to deal with aux-related directives. - parse_and_update_aux(config, ln, testfile, line_number, &mut self.aux); + parse_and_update_aux(config, ln, testfile, &mut self.aux); config.push_name_value_directive( ln, EXEC_ENV, testfile, - line_number, &mut self.exec_env, Config::parse_env, ); @@ -506,7 +490,6 @@ impl TestProps { ln, UNSET_EXEC_ENV, testfile, - line_number, &mut self.unset_exec_env, |r| r.trim().to_owned(), ); @@ -514,7 +497,6 @@ impl TestProps { ln, RUSTC_ENV, testfile, - line_number, &mut self.rustc_env, Config::parse_env, ); @@ -522,7 +504,6 @@ impl TestProps { ln, UNSET_RUSTC_ENV, testfile, - line_number, &mut self.unset_rustc_env, |r| r.trim().to_owned(), ); @@ -530,7 +511,6 @@ impl TestProps { ln, FORBID_OUTPUT, testfile, - line_number, &mut self.forbid_output, |r| r, ); @@ -566,7 +546,7 @@ impl TestProps { } if let Some(code) = config - .parse_name_value_directive(ln, FAILURE_STATUS, testfile, line_number) + .parse_name_value_directive(ln, FAILURE_STATUS, testfile) .and_then(|code| code.trim().parse::().ok()) { self.failure_status = Some(code); @@ -588,7 +568,6 @@ impl TestProps { ln, ASSEMBLY_OUTPUT, testfile, - line_number, &mut self.assembly_output, |r| r.trim().to_string(), ); @@ -602,7 +581,7 @@ impl TestProps { // Unlike the other `name_value_directive`s this needs to be handled manually, // because it sets a `bool` flag. if let Some(known_bug) = - config.parse_name_value_directive(ln, KNOWN_BUG, testfile, line_number) + config.parse_name_value_directive(ln, KNOWN_BUG, testfile) { let known_bug = known_bug.trim(); if known_bug == "unknown" @@ -632,24 +611,20 @@ impl TestProps { ln, TEST_MIR_PASS, testfile, - line_number, &mut self.mir_unit_test, |s| s.trim().to_string(), ); config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base); if let Some(flags) = - config.parse_name_value_directive(ln, LLVM_COV_FLAGS, testfile, line_number) + config.parse_name_value_directive(ln, LLVM_COV_FLAGS, testfile) { self.llvm_cov_flags.extend(split_flags(&flags)); } - if let Some(flags) = config.parse_name_value_directive( - ln, - FILECHECK_FLAGS, - testfile, - line_number, - ) { + if let Some(flags) = + config.parse_name_value_directive(ln, FILECHECK_FLAGS, testfile) + { self.filecheck_flags.extend(split_flags(&flags)); } @@ -661,7 +636,6 @@ impl TestProps { ln, directives::CORE_STUBS_COMPILE_FLAGS, testfile, - line_number, ) { let flags = split_flags(&flags); for flag in &flags { @@ -672,12 +646,9 @@ impl TestProps { self.core_stubs_compile_flags.extend(flags); } - if let Some(err_kind) = config.parse_name_value_directive( - ln, - DONT_REQUIRE_ANNOTATIONS, - testfile, - line_number, - ) { + if let Some(err_kind) = + config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS, testfile) + { self.dont_require_annotations .insert(ErrorKind::expect_from_user_str(err_kind.trim())); } @@ -734,7 +705,7 @@ impl TestProps { } } - fn update_fail_mode(&mut self, ln: &str, config: &Config) { + fn update_fail_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) { let check_ui = |mode: &str| { // Mode::Crashes may need build-fail in order to trigger llvm errors or stack overflows if config.mode != TestMode::Ui && config.mode != TestMode::Crashes { @@ -769,7 +740,12 @@ impl TestProps { } } - fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config) { + fn update_pass_mode( + &mut self, + ln: &DirectiveLine<'_>, + revision: Option<&str>, + config: &Config, + ) { let check_no_run = |s| match (config.mode, s) { (TestMode::Ui, _) => (), (TestMode::Crashes, _) => (), @@ -814,7 +790,7 @@ impl TestProps { self.pass_mode } - pub fn update_add_core_stubs(&mut self, ln: &str, config: &Config) { + fn update_add_core_stubs(&mut self, ln: &DirectiveLine<'_>, config: &Config) { let add_core_stubs = config.parse_name_directive(ln, directives::ADD_CORE_STUBS); if add_core_stubs { if !matches!(config.mode, TestMode::Ui | TestMode::Codegen | TestMode::Assembly) { @@ -905,10 +881,12 @@ pub(crate) struct CheckDirectiveResult<'ln> { trailing_directive: Option<&'ln str>, } -pub(crate) fn check_directive<'a>( - directive_ln: &'a str, +fn check_directive<'a>( + directive_ln: &DirectiveLine<'a>, mode: TestMode, ) -> CheckDirectiveResult<'a> { + let &DirectiveLine { raw_directive: directive_ln, .. } = directive_ln; + let (directive_name, post) = directive_ln.split_once([':', ' ']).unwrap_or((directive_ln, "")); let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name) @@ -980,7 +958,7 @@ fn iter_directives( // Perform unknown directive check on Rust files. if testfile.extension() == Some("rs") { let CheckDirectiveResult { is_known_directive, trailing_directive } = - check_directive(directive_line.raw_directive, mode); + check_directive(&directive_line, mode); if !is_known_directive { *poisoned = true; @@ -1014,8 +992,7 @@ impl Config { fn parse_and_update_revisions( &self, testfile: &Utf8Path, - line_number: usize, - line: &str, + line: &DirectiveLine<'_>, existing: &mut Vec, ) { const FORBIDDEN_REVISION_NAMES: [&str; 2] = [ @@ -1028,8 +1005,7 @@ impl Config { const FILECHECK_FORBIDDEN_REVISION_NAMES: [&str; 9] = ["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"]; - if let Some(raw) = self.parse_name_value_directive(line, "revisions", testfile, line_number) - { + if let Some(raw) = self.parse_name_value_directive(line, "revisions", testfile) { if self.mode == TestMode::RunMake { panic!("`run-make` mode tests do not support revisions: {}", testfile); } @@ -1074,13 +1050,8 @@ impl Config { (name.to_owned(), value.to_owned()) } - fn parse_pp_exact( - &self, - line: &str, - testfile: &Utf8Path, - line_number: usize, - ) -> Option { - if let Some(s) = self.parse_name_value_directive(line, "pp-exact", testfile, line_number) { + fn parse_pp_exact(&self, line: &DirectiveLine<'_>, testfile: &Utf8Path) -> Option { + if let Some(s) = self.parse_name_value_directive(line, "pp-exact", testfile) { Some(Utf8PathBuf::from(&s)) } else if self.parse_name_directive(line, "pp-exact") { testfile.file_name().map(Utf8PathBuf::from) @@ -1089,7 +1060,9 @@ impl Config { } } - fn parse_custom_normalization(&self, raw_directive: &str) -> Option { + fn parse_custom_normalization(&self, line: &DirectiveLine<'_>) -> Option { + let &DirectiveLine { raw_directive, .. } = line; + // FIXME(Zalathar): Integrate name/value splitting into `DirectiveLine` // instead of doing it here. let (directive_name, raw_value) = raw_directive.split_once(':')?; @@ -1110,7 +1083,9 @@ impl Config { Some(NormalizeRule { kind, regex, replacement }) } - fn parse_name_directive(&self, line: &str, directive: &str) -> bool { + fn parse_name_directive(&self, line: &DirectiveLine<'_>, directive: &str) -> bool { + let &DirectiveLine { raw_directive: line, .. } = line; + // Ensure the directive is a whole word. Do not match "ignore-x86" when // the line says "ignore-x86_64". line.starts_with(directive) @@ -1119,11 +1094,12 @@ impl Config { fn parse_name_value_directive( &self, - line: &str, + line: &DirectiveLine<'_>, directive: &str, testfile: &Utf8Path, - line_number: usize, ) -> Option { + let &DirectiveLine { line_number, raw_directive: line, .. } = line; + let colon = directive.len(); if line.starts_with(directive) && line.as_bytes().get(colon) == Some(&b':') { let value = line[(colon + 1)..].to_owned(); @@ -1140,42 +1116,37 @@ impl Config { } } - fn parse_edition(&self, line: &str, testfile: &Utf8Path, line_number: usize) -> Option { - self.parse_name_value_directive(line, "edition", testfile, line_number) + fn parse_edition(&self, line: &DirectiveLine<'_>, testfile: &Utf8Path) -> Option { + self.parse_name_value_directive(line, "edition", testfile) } - fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) { + fn set_name_directive(&self, line: &DirectiveLine<'_>, directive: &str, value: &mut bool) { // If the flag is already true, don't bother looking at the directive. *value = *value || self.parse_name_directive(line, directive); } fn set_name_value_directive( &self, - line: &str, + line: &DirectiveLine<'_>, directive: &str, testfile: &Utf8Path, - line_number: usize, value: &mut Option, parse: impl FnOnce(String) -> T, ) { if value.is_none() { - *value = - self.parse_name_value_directive(line, directive, testfile, line_number).map(parse); + *value = self.parse_name_value_directive(line, directive, testfile).map(parse); } } fn push_name_value_directive( &self, - line: &str, + line: &DirectiveLine<'_>, directive: &str, testfile: &Utf8Path, - line_number: usize, values: &mut Vec, parse: impl FnOnce(String) -> T, ) { - if let Some(value) = - self.parse_name_value_directive(line, directive, testfile, line_number).map(parse) - { + if let Some(value) = self.parse_name_value_directive(line, directive, testfile).map(parse) { values.push(value); } } @@ -1468,8 +1439,8 @@ pub(crate) fn make_test_description( &mut local_poisoned, path, src, - &mut |directive @ DirectiveLine { line_number, raw_directive: ln, .. }| { - if !directive.applies_to_test_revision(test_revision) { + &mut |ref ln @ DirectiveLine { line_number, .. }| { + if !ln.applies_to_test_revision(test_revision) { return; } @@ -1493,9 +1464,9 @@ pub(crate) fn make_test_description( decision!(cfg::handle_ignore(config, ln)); decision!(cfg::handle_only(config, ln)); decision!(needs::handle_needs(&cache.needs, config, ln)); - decision!(ignore_llvm(config, path, ln, line_number)); - decision!(ignore_backends(config, path, ln, line_number)); - decision!(needs_backends(config, path, ln, line_number)); + decision!(ignore_llvm(config, path, ln)); + decision!(ignore_backends(config, path, ln)); + decision!(needs_backends(config, path, ln)); decision!(ignore_cdb(config, ln)); decision!(ignore_gdb(config, ln)); decision!(ignore_lldb(config, ln)); @@ -1535,7 +1506,9 @@ pub(crate) fn make_test_description( } } -fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision { +fn ignore_cdb(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { + let &DirectiveLine { raw_directive: line, .. } = line; + if config.debugger != Some(Debugger::Cdb) { return IgnoreDecision::Continue; } @@ -1558,7 +1531,9 @@ fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision { IgnoreDecision::Continue } -fn ignore_gdb(config: &Config, line: &str) -> IgnoreDecision { +fn ignore_gdb(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { + let &DirectiveLine { raw_directive: line, .. } = line; + if config.debugger != Some(Debugger::Gdb) { return IgnoreDecision::Continue; } @@ -1606,7 +1581,9 @@ fn ignore_gdb(config: &Config, line: &str) -> IgnoreDecision { IgnoreDecision::Continue } -fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision { +fn ignore_lldb(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { + let &DirectiveLine { raw_directive: line, .. } = line; + if config.debugger != Some(Debugger::Lldb) { return IgnoreDecision::Continue; } @@ -1628,14 +1605,9 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision { IgnoreDecision::Continue } -fn ignore_backends( - config: &Config, - path: &Utf8Path, - line: &str, - line_number: usize, -) -> IgnoreDecision { +fn ignore_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision { if let Some(backends_to_ignore) = - config.parse_name_value_directive(line, "ignore-backends", path, line_number) + config.parse_name_value_directive(line, "ignore-backends", path) { for backend in backends_to_ignore.split_whitespace().map(|backend| { match CodegenBackend::try_from(backend) { @@ -1655,15 +1627,8 @@ fn ignore_backends( IgnoreDecision::Continue } -fn needs_backends( - config: &Config, - path: &Utf8Path, - line: &str, - line_number: usize, -) -> IgnoreDecision { - if let Some(needed_backends) = - config.parse_name_value_directive(line, "needs-backends", path, line_number) - { +fn needs_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision { + if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends", path) { if !needed_backends .split_whitespace() .map(|backend| match CodegenBackend::try_from(backend) { @@ -1685,9 +1650,9 @@ fn needs_backends( IgnoreDecision::Continue } -fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) -> IgnoreDecision { +fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision { if let Some(needed_components) = - config.parse_name_value_directive(line, "needs-llvm-components", path, line_number) + config.parse_name_value_directive(line, "needs-llvm-components", path) { let components: HashSet<_> = config.llvm_components.split_whitespace().collect(); if let Some(missing_component) = needed_components @@ -1709,7 +1674,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) // Note that these `min` versions will check for not just major versions. if let Some(version_string) = - config.parse_name_value_directive(line, "min-llvm-version", path, line_number) + config.parse_name_value_directive(line, "min-llvm-version", path) { let min_version = extract_llvm_version(&version_string); // Ignore if actual version is smaller than the minimum required version. @@ -1721,7 +1686,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) }; } } else if let Some(version_string) = - config.parse_name_value_directive(line, "max-llvm-major-version", path, line_number) + config.parse_name_value_directive(line, "max-llvm-major-version", path) { let max_version = extract_llvm_version(&version_string); // Ignore if actual major version is larger than the maximum required major version. @@ -1735,7 +1700,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) }; } } else if let Some(version_string) = - config.parse_name_value_directive(line, "min-system-llvm-version", path, line_number) + config.parse_name_value_directive(line, "min-system-llvm-version", path) { let min_version = extract_llvm_version(&version_string); // Ignore if using system LLVM and actual version @@ -1748,7 +1713,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) }; } } else if let Some(version_range) = - config.parse_name_value_directive(line, "ignore-llvm-version", path, line_number) + config.parse_name_value_directive(line, "ignore-llvm-version", path) { // Syntax is: "ignore-llvm-version: [- ]" let (v_min, v_max) = @@ -1774,7 +1739,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) } } } else if let Some(version_string) = - config.parse_name_value_directive(line, "exact-llvm-major-version", path, line_number) + config.parse_name_value_directive(line, "exact-llvm-major-version", path) { // Syntax is "exact-llvm-major-version: " let version = extract_llvm_version(&version_string); diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index 7c1ed2e700624..0675a6feac3f0 100644 --- a/src/tools/compiletest/src/directives/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs @@ -7,6 +7,7 @@ use camino::Utf8Path; use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; use crate::common::Config; +use crate::directives::DirectiveLine; /// Properties parsed from `aux-*` test directives. #[derive(Clone, Debug, Default)] @@ -45,40 +46,28 @@ impl AuxProps { /// and update [`AuxProps`] accordingly. pub(super) fn parse_and_update_aux( config: &Config, - ln: &str, + directive_line: &DirectiveLine<'_>, testfile: &Utf8Path, - line_number: usize, aux: &mut AuxProps, ) { + let &DirectiveLine { raw_directive: ln, .. } = directive_line; + if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) { return; } - config.push_name_value_directive(ln, AUX_BUILD, testfile, line_number, &mut aux.builds, |r| { + let ln = directive_line; + + config.push_name_value_directive(ln, AUX_BUILD, testfile, &mut aux.builds, |r| { r.trim().to_string() }); - config.push_name_value_directive(ln, AUX_BIN, testfile, line_number, &mut aux.bins, |r| { + config + .push_name_value_directive(ln, AUX_BIN, testfile, &mut aux.bins, |r| r.trim().to_string()); + config.push_name_value_directive(ln, AUX_CRATE, testfile, &mut aux.crates, parse_aux_crate); + config.push_name_value_directive(ln, PROC_MACRO, testfile, &mut aux.proc_macros, |r| { r.trim().to_string() }); - config.push_name_value_directive( - ln, - AUX_CRATE, - testfile, - line_number, - &mut aux.crates, - parse_aux_crate, - ); - config.push_name_value_directive( - ln, - PROC_MACRO, - testfile, - line_number, - &mut aux.proc_macros, - |r| r.trim().to_string(), - ); - if let Some(r) = - config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND, testfile, line_number) - { + if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND, testfile) { aux.codegen_backend = Some(r.trim().to_owned()); } } diff --git a/src/tools/compiletest/src/directives/cfg.rs b/src/tools/compiletest/src/directives/cfg.rs index 802a1d63d1f20..62a4b88a33a6e 100644 --- a/src/tools/compiletest/src/directives/cfg.rs +++ b/src/tools/compiletest/src/directives/cfg.rs @@ -1,12 +1,14 @@ use std::collections::HashSet; use crate::common::{CompareMode, Config, Debugger}; -use crate::directives::IgnoreDecision; +use crate::directives::{DirectiveLine, IgnoreDecision}; const EXTRA_ARCHS: &[&str] = &["spirv"]; -pub(super) fn handle_ignore(config: &Config, line: &str) -> IgnoreDecision { +pub(super) fn handle_ignore(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { let parsed = parse_cfg_name_directive(config, line, "ignore"); + let &DirectiveLine { raw_directive: line, .. } = line; + match parsed.outcome { MatchOutcome::NoMatch => IgnoreDecision::Continue, MatchOutcome::Match => IgnoreDecision::Ignore { @@ -21,8 +23,10 @@ pub(super) fn handle_ignore(config: &Config, line: &str) -> IgnoreDecision { } } -pub(super) fn handle_only(config: &Config, line: &str) -> IgnoreDecision { +pub(super) fn handle_only(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { let parsed = parse_cfg_name_directive(config, line, "only"); + let &DirectiveLine { raw_directive: line, .. } = line; + match parsed.outcome { MatchOutcome::Match => IgnoreDecision::Continue, MatchOutcome::NoMatch => IgnoreDecision::Ignore { @@ -43,9 +47,11 @@ pub(super) fn handle_only(config: &Config, line: &str) -> IgnoreDecision { /// or `only-windows`. fn parse_cfg_name_directive<'a>( config: &Config, - line: &'a str, + line: &'a DirectiveLine<'a>, prefix: &str, ) -> ParsedNameDirective<'a> { + let &DirectiveLine { raw_directive: line, .. } = line; + if !line.as_bytes().starts_with(prefix.as_bytes()) { return ParsedNameDirective::not_a_directive(); } diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index 3b7a9478717f4..c8a729d8aab68 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -1,10 +1,10 @@ use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; -use crate::directives::{IgnoreDecision, llvm_has_libzstd}; +use crate::directives::{DirectiveLine, IgnoreDecision, llvm_has_libzstd}; pub(super) fn handle_needs( cache: &CachedNeedsConditions, config: &Config, - ln: &str, + ln: &DirectiveLine<'_>, ) -> IgnoreDecision { // Note that we intentionally still put the needs- prefix here to make the file show up when // grepping for a directive name, even though we could technically strip that. @@ -181,6 +181,8 @@ pub(super) fn handle_needs( }, ]; + let &DirectiveLine { raw_directive: ln, .. } = ln; + let (name, rest) = match ln.split_once([':', ' ']) { Some((name, rest)) => (name, Some(rest)), None => (ln, None),