diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 633c15b54b9ef..80c89b9ff3826 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -812,8 +812,7 @@ default_test!(Incremental { default_test!(Debuginfo { path: "src/test/debuginfo", - // What this runs varies depending on the native platform being apple - mode: "debuginfo-XXX", + mode: "debuginfo", suite: "debuginfo" }); @@ -950,18 +949,11 @@ impl Step for Compiletest { return; } - if mode == "debuginfo-XXX" { - return if builder.config.build.contains("apple") { - builder.ensure(Compiletest { - mode: "debuginfo-lldb", - ..self - }); - } else { - builder.ensure(Compiletest { - mode: "debuginfo-gdb", - ..self - }); - }; + if mode == "debuginfo" { + return builder.ensure(Compiletest { + mode: "debuginfo-both", + ..self + }); } builder.ensure(dist::DebuggerScripts { diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs index 4e88f65ad1d00..d11a42bb0ed13 100644 --- a/src/test/debuginfo/lexical-scope-with-macro.rs +++ b/src/test/debuginfo/lexical-scope-with-macro.rs @@ -9,7 +9,7 @@ // except according to those terms. // min-lldb-version: 310 -// ignore-macos FIXME #48807 +// ignore-lldb FIXME #48807 // compile-flags:-g -Zdebug-macros diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 7006fb9427e1c..fab2ea7ba6c36 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -25,6 +25,7 @@ pub enum Mode { RunPass, RunPassValgrind, Pretty, + DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Codegen, @@ -60,6 +61,7 @@ impl FromStr for Mode { "run-pass" => Ok(RunPass), "run-pass-valgrind" => Ok(RunPassValgrind), "pretty" => Ok(Pretty), + "debuginfo-both" => Ok(DebugInfoBoth), "debuginfo-lldb" => Ok(DebugInfoLldb), "debuginfo-gdb" => Ok(DebugInfoGdb), "codegen" => Ok(Codegen), @@ -83,6 +85,7 @@ impl fmt::Display for Mode { RunPass => "run-pass", RunPassValgrind => "run-pass-valgrind", Pretty => "pretty", + DebugInfoBoth => "debuginfo-both", DebugInfoGdb => "debuginfo-gdb", DebugInfoLldb => "debuginfo-lldb", Codegen => "codegen", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 688f2babe6e8c..06eeef61a194d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -19,10 +19,62 @@ use util; use extract_gdb_version; +/// Whether to ignore the test. +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum Ignore { + /// Run it. + Run, + /// Ignore it totally. + Ignore, + /// Ignore only the gdb test, but run the lldb test. + IgnoreGdb, + /// Ignore only the lldb test, but run the gdb test. + IgnoreLldb, +} + +impl Ignore { + pub fn can_run_gdb(&self) -> bool { + *self == Ignore::Run || *self == Ignore::IgnoreLldb + } + + pub fn can_run_lldb(&self) -> bool { + *self == Ignore::Run || *self == Ignore::IgnoreGdb + } + + pub fn no_gdb(&self) -> Ignore { + match *self { + Ignore::Run => Ignore::IgnoreGdb, + Ignore::IgnoreGdb => Ignore::IgnoreGdb, + _ => Ignore::Ignore, + } + } + + pub fn no_lldb(&self) -> Ignore { + match *self { + Ignore::Run => Ignore::IgnoreLldb, + Ignore::IgnoreLldb => Ignore::IgnoreLldb, + _ => Ignore::Ignore, + } + } +} + +/// The result of parse_cfg_name_directive. +#[derive(Clone, Copy, PartialEq, Debug)] +enum ParsedNameDirective { + /// No match. + NoMatch, + /// Match. + Match, + /// Mode was DebugInfoBoth and this matched gdb. + MatchGdb, + /// Mode was DebugInfoBoth and this matched lldb. + MatchLldb, +} + /// Properties which must be known very early, before actually running /// the test. pub struct EarlyProps { - pub ignore: bool, + pub ignore: Ignore, pub should_fail: bool, pub aux: Vec, pub revisions: Vec, @@ -31,20 +83,55 @@ pub struct EarlyProps { impl EarlyProps { pub fn from_file(config: &Config, testfile: &Path) -> Self { let mut props = EarlyProps { - ignore: false, + ignore: Ignore::Run, should_fail: false, aux: Vec::new(), revisions: vec![], }; + if config.mode == common::DebugInfoBoth { + if config.lldb_python_dir.is_none() { + props.ignore = props.ignore.no_lldb(); + } + if config.gdb_version.is_none() { + props.ignore = props.ignore.no_gdb(); + } + } + iter_header(testfile, None, &mut |ln| { // we should check if any only- exists and if it exists // and does not matches the current platform, skip the test - props.ignore = props.ignore || config.parse_cfg_name_directive(ln, "ignore") - || (config.has_cfg_prefix(ln, "only") - && !config.parse_cfg_name_directive(ln, "only")) - || ignore_gdb(config, ln) || ignore_lldb(config, ln) - || ignore_llvm(config, ln); + if props.ignore != Ignore::Ignore { + props.ignore = match config.parse_cfg_name_directive(ln, "ignore") { + ParsedNameDirective::Match => Ignore::Ignore, + ParsedNameDirective::NoMatch => props.ignore, + ParsedNameDirective::MatchGdb => props.ignore.no_gdb(), + ParsedNameDirective::MatchLldb => props.ignore.no_lldb(), + }; + + if config.has_cfg_prefix(ln, "only") { + props.ignore = match config.parse_cfg_name_directive(ln, "only") { + ParsedNameDirective::Match => props.ignore, + ParsedNameDirective::NoMatch => Ignore::Ignore, + ParsedNameDirective::MatchLldb => props.ignore.no_gdb(), + ParsedNameDirective::MatchGdb => props.ignore.no_lldb(), + }; + } + + if ignore_llvm(config, ln) { + props.ignore = Ignore::Ignore; + } + } + + if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoBoth) && + props.ignore.can_run_gdb() && ignore_gdb(config, ln) { + props.ignore = props.ignore.no_gdb(); + } + + if (config.mode == common::DebugInfoLldb || config.mode == common::DebugInfoBoth) && + props.ignore.can_run_lldb() && ignore_lldb(config, ln) { + props.ignore = props.ignore.no_lldb(); + } if let Some(s) = config.parse_aux_build(ln) { props.aux.push(s); @@ -60,10 +147,6 @@ impl EarlyProps { return props; fn ignore_gdb(config: &Config, line: &str) -> bool { - if config.mode != common::DebugInfoGdb { - return false; - } - if let Some(actual_version) = config.gdb_version { if line.starts_with("min-gdb-version") { let (start_ver, end_ver) = extract_gdb_version_range(line); @@ -120,10 +203,6 @@ impl EarlyProps { } fn ignore_lldb(config: &Config, line: &str) -> bool { - if config.mode != common::DebugInfoLldb { - return false; - } - if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { let min_version = line.trim_right() @@ -604,7 +683,7 @@ impl Config { } fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { - if self.parse_cfg_name_directive(line, prefix) { + if self.parse_cfg_name_directive(line, prefix) == ParsedNameDirective::Match { let from = match parse_normalization_string(&mut line) { Some(s) => s, None => return None, @@ -620,35 +699,59 @@ impl Config { } /// Parses a name-value directive which contains config-specific information, e.g. `ignore-x86` - /// or `normalize-stderr-32bit`. Returns `true` if the line matches it. - fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> bool { + /// or `normalize-stderr-32bit`. + fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective { if line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-') { let name = line[prefix.len() + 1..] .split(&[':', ' '][..]) .next() .unwrap(); - name == "test" || + if name == "test" || util::matches_os(&self.target, name) || // target name == util::get_arch(&self.target) || // architecture name == util::get_pointer_width(&self.target) || // pointer width name == self.stage_id.split('-').next().unwrap() || // stage Some(name) == util::get_env(&self.target) || // env - match self.mode { - common::DebugInfoGdb => name == "gdb", - common::DebugInfoLldb => name == "lldb", - common::Pretty => name == "pretty", - _ => false, - } || (self.target != self.host && name == "cross-compile") || match self.compare_mode { Some(CompareMode::Nll) => name == "compare-mode-nll", Some(CompareMode::Polonius) => name == "compare-mode-polonius", None => false, } || - (cfg!(debug_assertions) && name == "debug") + (cfg!(debug_assertions) && name == "debug") { + ParsedNameDirective::Match + } else { + match self.mode { + common::DebugInfoBoth => { + if name == "gdb" { + ParsedNameDirective::MatchGdb + } else if name == "lldb" { + ParsedNameDirective::MatchLldb + } else { + ParsedNameDirective::NoMatch + } + }, + common::DebugInfoGdb => if name == "gdb" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, + common::DebugInfoLldb => if name == "lldb" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, + common::Pretty => if name == "pretty" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, + _ => ParsedNameDirective::NoMatch, + } + } } else { - false + ParsedNameDirective::NoMatch } } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index f46e031d768bd..c931d3c0e30b7 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -32,7 +32,7 @@ extern crate rustfix; use common::CompareMode; use common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; use common::{Config, TestPaths}; -use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; +use common::{DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; use filetime::FileTime; use getopts::Options; use std::env; @@ -44,7 +44,7 @@ use std::process::Command; use test::ColorConfig; use util::logv; -use self::header::EarlyProps; +use self::header::{EarlyProps, Ignore}; pub mod common; pub mod errors; @@ -425,7 +425,7 @@ pub fn opt_str2(maybestr: Option) -> String { pub fn run_tests(config: &Config) { if config.target.contains("android") { - if let DebugInfoGdb = config.mode { + if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { println!( "{} debug-info test uses tcp 5039 port.\ please reserve it", @@ -443,7 +443,9 @@ pub fn run_tests(config: &Config) { } match config.mode { - DebugInfoLldb => { + // Note that we don't need to emit the gdb warning when + // DebugInfoBoth, so it is ok to list that here. + DebugInfoBoth | DebugInfoLldb => { if let Some(lldb_version) = config.lldb_version.as_ref() { if is_blacklisted_lldb_version(&lldb_version[..]) { println!( @@ -647,15 +649,18 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec Vec, ) -> test::TestFn { - let config = config.clone(); + let mut config = config.clone(); + if config.mode == DebugInfoBoth { + // If both gdb and lldb were ignored, then the test as a whole + // would be ignored. + if !ignore.can_run_gdb() { + config.mode = DebugInfoLldb; + } else if !ignore.can_run_lldb() { + config.mode = DebugInfoGdb; + } + } + let testpaths = testpaths.clone(); let revision = revision.cloned(); test::DynTestFn(Box::new(move || { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4cb6f6b83bdd1..153c9907b0c19 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -11,7 +11,7 @@ use common::CompareMode; use common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; use common::{output_base_dir, output_base_name, output_testname_unique}; -use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc}; +use common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc}; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Config, TestPaths}; use common::{Incremental, MirOpt, RunMake, Ui}; @@ -225,19 +225,20 @@ pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) { pub fn compute_stamp_hash(config: &Config) -> String { let mut hash = DefaultHasher::new(); config.stage_id.hash(&mut hash); - match config.mode { - DebugInfoGdb => match config.gdb { + + if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { + match config.gdb { None => env::var_os("PATH").hash(&mut hash), Some(ref s) if s.is_empty() => env::var_os("PATH").hash(&mut hash), Some(ref s) => s.hash(&mut hash), - }, - DebugInfoLldb => { - env::var_os("PATH").hash(&mut hash); - env::var_os("PYTHONPATH").hash(&mut hash); - }, + }; + } + + if config.mode == DebugInfoLldb || config.mode == DebugInfoBoth { + env::var_os("PATH").hash(&mut hash); + env::var_os("PYTHONPATH").hash(&mut hash); + } - _ => {}, - }; format!("{:x}", hash.finish()) } @@ -268,6 +269,10 @@ impl<'test> TestCx<'test> { RunFail => self.run_rfail_test(), RunPassValgrind => self.run_valgrind_test(), Pretty => self.run_pretty_test(), + DebugInfoBoth => { + self.run_debuginfo_gdb_test(); + self.run_debuginfo_lldb_test(); + }, DebugInfoGdb => self.run_debuginfo_gdb_test(), DebugInfoLldb => self.run_debuginfo_lldb_test(), Codegen => self.run_codegen_test(), @@ -640,6 +645,7 @@ impl<'test> TestCx<'test> { let config = Config { target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), + mode: DebugInfoGdb, ..self.config.clone() }; @@ -910,6 +916,7 @@ impl<'test> TestCx<'test> { let config = Config { target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), + mode: DebugInfoLldb, ..self.config.clone() }; @@ -1774,7 +1781,7 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } - RunFail | RunPassValgrind | Pretty | DebugInfoGdb | DebugInfoLldb + RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits => { // do not use JSON output }