Auto merge of #103298 - ferrocene:pa-compile-flags-last, r=jyn514

Ensure that compile-flags arguments are the last in UI tests

Before this PR, compiletest would add `-L path/to/aux` at the end of the rustc flags, even after the custom ones set with the compile-flags header comment. This made it impossible to check how rustc would behave when a flag requiring an argument was passed without the argument, because the argument would become `-L`.

This PR fixes that by adding the `-L path/to/aux` before the arguments defined in compile-flags, at least for UI tests. Other test suites might either be fixed as well by this change, or still present the old behavior (`-L` is now always passed before, but other tests suites might add additional flags after the custom ones).
This commit is contained in:
bors 2022-11-04 22:24:46 +00:00
commit 81ff7e7385
5 changed files with 80 additions and 39 deletions

View File

@ -0,0 +1,7 @@
// Check that the arguments provided through `// compile-flags` are added last to the command line
// in UI tests. To ensure that we invoke rustc with a flag that expects an argument withut actually
// providing it. If the compile-flags are not last, the test will fail as rustc will interpret the
// next flag as the argument of this flag.
//
// compile-flags: --cap-lints
// error-pattern: Argument to option 'cap-lints' missing

View File

@ -0,0 +1,2 @@
error: Argument to option 'cap-lints' missing

View File

@ -208,11 +208,13 @@ enum WillExecute {
Disabled,
}
/// Should `--emit metadata` be used?
/// What value should be passed to `--emit`?
#[derive(Copy, Clone)]
enum EmitMetadata {
Yes,
No,
enum Emit {
None,
Metadata,
LlvmIr,
Asm,
}
impl<'test> TestCx<'test> {
@ -412,7 +414,7 @@ fn run_valgrind_test(&self) {
}
let should_run = self.run_if_enabled();
let mut proc_res = self.compile_test(should_run, EmitMetadata::No);
let mut proc_res = self.compile_test(should_run, Emit::None);
if !proc_res.status.success() {
self.fatal_proc_rec("compilation failed!", &proc_res);
@ -658,7 +660,7 @@ fn run_debuginfo_cdb_test_no_opt(&self) {
// compile test file (it should have 'compile-flags:-g' in the header)
let should_run = self.run_if_enabled();
let compile_result = self.compile_test(should_run, EmitMetadata::No);
let compile_result = self.compile_test(should_run, Emit::None);
if !compile_result.status.success() {
self.fatal_proc_rec("compilation failed!", &compile_result);
}
@ -778,7 +780,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
// compile test file (it should have 'compile-flags:-g' in the header)
let should_run = self.run_if_enabled();
let compiler_run_result = self.compile_test(should_run, EmitMetadata::No);
let compiler_run_result = self.compile_test(should_run, Emit::None);
if !compiler_run_result.status.success() {
self.fatal_proc_rec("compilation failed!", &compiler_run_result);
}
@ -1010,7 +1012,7 @@ fn run_debuginfo_lldb_test(&self) {
fn run_debuginfo_lldb_test_no_opt(&self) {
// compile test file (it should have 'compile-flags:-g' in the header)
let should_run = self.run_if_enabled();
let compile_result = self.compile_test(should_run, EmitMetadata::No);
let compile_result = self.compile_test(should_run, Emit::None);
if !compile_result.status.success() {
self.fatal_proc_rec("compilation failed!", &compile_result);
}
@ -1426,21 +1428,21 @@ fn is_unexpected_compiler_message(
}
}
fn should_emit_metadata(&self, pm: Option<PassMode>) -> EmitMetadata {
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
match (pm, self.props.fail_mode, self.config.mode) {
(Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => EmitMetadata::Yes,
_ => EmitMetadata::No,
(Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => Emit::Metadata,
_ => Emit::None,
}
}
fn compile_test(&self, will_execute: WillExecute, emit_metadata: EmitMetadata) -> ProcRes {
self.compile_test_general(will_execute, emit_metadata, self.props.local_pass_mode())
fn compile_test(&self, will_execute: WillExecute, emit: Emit) -> ProcRes {
self.compile_test_general(will_execute, emit, self.props.local_pass_mode())
}
fn compile_test_general(
&self,
will_execute: WillExecute,
emit_metadata: EmitMetadata,
emit: Emit,
local_pm: Option<PassMode>,
) -> ProcRes {
// Only use `make_exe_name` when the test ends up being executed.
@ -1472,10 +1474,13 @@ fn compile_test_general(
_ => AllowUnused::No,
};
let mut rustc =
self.make_compile_args(&self.testpaths.file, output_file, emit_metadata, allow_unused);
rustc.arg("-L").arg(&self.aux_output_dir_name());
let rustc = self.make_compile_args(
&self.testpaths.file,
output_file,
emit,
allow_unused,
LinkToAux::Yes,
);
self.compose_and_run_compiler(rustc, None)
}
@ -1702,8 +1707,13 @@ fn build_auxiliary(&self, source_path: &str, aux_dir: &Path) -> bool {
// Create the directory for the stdout/stderr files.
create_dir_all(aux_cx.output_base_dir()).unwrap();
let input_file = &aux_testpaths.file;
let mut aux_rustc =
aux_cx.make_compile_args(input_file, aux_output, EmitMetadata::No, AllowUnused::No);
let mut aux_rustc = aux_cx.make_compile_args(
input_file,
aux_output,
Emit::None,
AllowUnused::No,
LinkToAux::No,
);
for key in &aux_props.unset_rustc_env {
aux_rustc.env_remove(key);
@ -1831,8 +1841,9 @@ fn make_compile_args(
&self,
input_file: &Path,
output_file: TargetLocation,
emit_metadata: EmitMetadata,
emit: Emit,
allow_unused: AllowUnused,
link_to_aux: LinkToAux,
) -> Command {
let is_aux = input_file.components().map(|c| c.as_os_str()).any(|c| c == "auxiliary");
let is_rustdoc = self.is_rustdoc() && !is_aux;
@ -1947,8 +1958,18 @@ fn make_compile_args(
}
}
if let (false, EmitMetadata::Yes) = (is_rustdoc, emit_metadata) {
rustc.args(&["--emit", "metadata"]);
match emit {
Emit::None => {}
Emit::Metadata if is_rustdoc => {}
Emit::Metadata => {
rustc.args(&["--emit", "metadata"]);
}
Emit::LlvmIr => {
rustc.args(&["--emit", "llvm-ir"]);
}
Emit::Asm => {
rustc.args(&["--emit", "asm"]);
}
}
if !is_rustdoc {
@ -2014,6 +2035,10 @@ fn make_compile_args(
rustc.arg("-Ctarget-feature=-crt-static");
}
if let LinkToAux::Yes = link_to_aux {
rustc.arg("-L").arg(self.aux_output_dir_name());
}
rustc.args(&self.props.compile_flags);
rustc
@ -2205,13 +2230,15 @@ fn fatal_proc_rec_with_ctx(
// codegen tests (using FileCheck)
fn compile_test_and_save_ir(&self) -> ProcRes {
let aux_dir = self.aux_output_dir_name();
let output_file = TargetLocation::ThisDirectory(self.output_base_dir());
let input_file = &self.testpaths.file;
let mut rustc =
self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No);
rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir");
let rustc = self.make_compile_args(
input_file,
output_file,
Emit::LlvmIr,
AllowUnused::No,
LinkToAux::Yes,
);
self.compose_and_run_compiler(rustc, None)
}
@ -2223,14 +2250,11 @@ fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
let output_file = TargetLocation::ThisFile(output_path.clone());
let input_file = &self.testpaths.file;
let mut rustc =
self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No);
rustc.arg("-L").arg(self.aux_output_dir_name());
let mut emit = Emit::None;
match self.props.assembly_output.as_ref().map(AsRef::as_ref) {
Some("emit-asm") => {
rustc.arg("--emit=asm");
emit = Emit::Asm;
}
Some("ptx-linker") => {
@ -2241,6 +2265,9 @@ fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
None => self.fatal("missing 'assembly-output' header"),
}
let rustc =
self.make_compile_args(input_file, output_file, emit, AllowUnused::No, LinkToAux::Yes);
(self.compose_and_run_compiler(rustc, None), output_path)
}
@ -2365,10 +2392,10 @@ fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
let mut rustc = new_rustdoc.make_compile_args(
&new_rustdoc.testpaths.file,
output_file,
EmitMetadata::No,
Emit::None,
AllowUnused::Yes,
LinkToAux::Yes,
);
rustc.arg("-L").arg(&new_rustdoc.aux_output_dir_name());
new_rustdoc.build_all_auxiliary(&mut rustc);
let proc_res = new_rustdoc.document(&compare_dir);
@ -2641,7 +2668,7 @@ fn check_rustdoc_test_option(&self, res: ProcRes) {
fn run_codegen_units_test(&self) {
assert!(self.revision.is_none(), "revisions not relevant here");
let proc_res = self.compile_test(WillExecute::No, EmitMetadata::No);
let proc_res = self.compile_test(WillExecute::No, Emit::None);
if !proc_res.status.success() {
self.fatal_proc_rec("compilation failed!", &proc_res);
@ -3154,7 +3181,7 @@ fn run_ui_test(&self) {
if let Some(FailMode::Build) = self.props.fail_mode {
// Make sure a build-fail test cannot fail due to failing analysis (e.g. typeck).
let pm = Some(PassMode::Check);
let proc_res = self.compile_test_general(WillExecute::No, EmitMetadata::Yes, pm);
let proc_res = self.compile_test_general(WillExecute::No, Emit::Metadata, pm);
self.check_if_test_should_compile(&proc_res, pm);
}
@ -3312,13 +3339,13 @@ fn run_ui_test(&self) {
if self.props.run_rustfix && self.config.compare_mode.is_none() {
// And finally, compile the fixed code and make sure it both
// succeeds and has no diagnostics.
let mut rustc = self.make_compile_args(
let rustc = self.make_compile_args(
&self.testpaths.file.with_extension(UI_FIXED),
TargetLocation::ThisFile(self.make_exe_name()),
emit_metadata,
AllowUnused::No,
LinkToAux::Yes,
);
rustc.arg("-L").arg(&self.aux_output_dir_name());
let res = self.compose_and_run_compiler(rustc, None);
if !res.status.success() {
self.fatal_proc_rec("failed to compile fixed code", &res);
@ -3852,3 +3879,8 @@ enum AllowUnused {
Yes,
No,
}
enum LinkToAux {
Yes,
No,
}