Emit warning when there is no space between -o and confusing arg
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
@@ -1237,9 +1237,55 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
warn_on_confusing_output_filename_flag(early_dcx, &matches, args);
|
||||||
|
|
||||||
Some(matches)
|
Some(matches)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Warn if `-o` is used without a space between the flag name and the value
|
||||||
|
/// and the value is a high-value confusables,
|
||||||
|
/// e.g. `-optimize` instead of `-o optimize`, see issue #142812.
|
||||||
|
fn warn_on_confusing_output_filename_flag(
|
||||||
|
early_dcx: &EarlyDiagCtxt,
|
||||||
|
matches: &getopts::Matches,
|
||||||
|
args: &[String],
|
||||||
|
) {
|
||||||
|
fn eq_ignore_separators(s1: &str, s2: &str) -> bool {
|
||||||
|
let s1 = s1.replace('-', "_");
|
||||||
|
let s2 = s2.replace('-', "_");
|
||||||
|
s1 == s2
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(name) = matches.opt_str("o")
|
||||||
|
&& let Some(suspect) = args.iter().find(|arg| arg.starts_with("-o") && *arg != "-o")
|
||||||
|
{
|
||||||
|
let filename = suspect.strip_prefix("-").unwrap_or(suspect);
|
||||||
|
let optgroups = config::rustc_optgroups();
|
||||||
|
let fake_args = ["optimize", "o0", "o1", "o2", "o3", "ofast", "og", "os", "oz"];
|
||||||
|
|
||||||
|
// Check if provided filename might be confusing in conjunction with `-o` flag,
|
||||||
|
// i.e. consider `-o{filename}` such as `-optimize` with `filename` being `ptimize`.
|
||||||
|
// There are high-value confusables, for example:
|
||||||
|
// - Long name of flags, e.g. `--out-dir` vs `-out-dir`
|
||||||
|
// - C compiler flag, e.g. `optimize`, `o0`, `o1`, `o2`, `o3`, `ofast`.
|
||||||
|
// - Codegen flags, e.g. `pt-level` of `-opt-level`.
|
||||||
|
if optgroups.iter().any(|option| eq_ignore_separators(option.long_name(), filename))
|
||||||
|
|| config::CG_OPTIONS.iter().any(|option| eq_ignore_separators(option.name(), filename))
|
||||||
|
|| fake_args.iter().any(|arg| eq_ignore_separators(arg, filename))
|
||||||
|
{
|
||||||
|
early_dcx.early_warn(
|
||||||
|
"option `-o` has no space between flag name and value, which can be confusing",
|
||||||
|
);
|
||||||
|
early_dcx.early_note(format!(
|
||||||
|
"output filename `-o {name}` is applied instead of a flag named `o{name}`"
|
||||||
|
));
|
||||||
|
early_dcx.early_help(format!(
|
||||||
|
"insert a space between `-o` and `{name}` if this is intentional: `-o {name}`"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
|
fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
|
||||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
||||||
|
|||||||
@@ -1653,6 +1653,11 @@ impl RustcOptGroup {
|
|||||||
OptionKind::FlagMulti => options.optflagmulti(short_name, long_name, desc),
|
OptionKind::FlagMulti => options.optflagmulti(short_name, long_name, desc),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is for diagnostics-only.
|
||||||
|
pub fn long_name(&self) -> &str {
|
||||||
|
self.long_name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_opt(
|
pub fn make_opt(
|
||||||
|
|||||||
1
tests/run-make/option-output-no-space/main.rs
Normal file
1
tests/run-make/option-output-no-space/main.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
fn main() {}
|
||||||
95
tests/run-make/option-output-no-space/rmake.rs
Normal file
95
tests/run-make/option-output-no-space/rmake.rs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// This test is to check if the warning is emitted when no space
|
||||||
|
// between `-o` and arg is applied, see issue #142812
|
||||||
|
|
||||||
|
//@ ignore-cross-compile
|
||||||
|
use run_make_support::rustc;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// test fake args
|
||||||
|
rustc()
|
||||||
|
.input("main.rs")
|
||||||
|
.arg("-optimize")
|
||||||
|
.run()
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"warning: option `-o` has no space between flag name and value, which can be confusing",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"note: output filename `-o ptimize` is applied instead of a flag named `optimize`",
|
||||||
|
);
|
||||||
|
rustc()
|
||||||
|
.input("main.rs")
|
||||||
|
.arg("-o0")
|
||||||
|
.run()
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"warning: option `-o` has no space between flag name and value, which can be confusing",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"note: output filename `-o 0` is applied instead of a flag named `o0`",
|
||||||
|
);
|
||||||
|
rustc().input("main.rs").arg("-o1").run();
|
||||||
|
// test real args by iter optgroups
|
||||||
|
rustc()
|
||||||
|
.input("main.rs")
|
||||||
|
.arg("-out-dir")
|
||||||
|
.run()
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"warning: option `-o` has no space between flag name and value, which can be confusing",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"note: output filename `-o ut-dir` is applied instead of a flag named `out-dir`",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"help: insert a space between `-o` and `ut-dir` if this is intentional: `-o ut-dir`",
|
||||||
|
);
|
||||||
|
// test real args by iter CG_OPTIONS
|
||||||
|
rustc()
|
||||||
|
.input("main.rs")
|
||||||
|
.arg("-opt_level")
|
||||||
|
.run()
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"warning: option `-o` has no space between flag name and value, which can be confusing",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"note: output filename `-o pt_level` is applied instead of a flag named `opt_level`",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"help: insert a space between `-o` and `pt_level` if this is intentional: `-o pt_level`"
|
||||||
|
);
|
||||||
|
// separater in-sensitive
|
||||||
|
rustc()
|
||||||
|
.input("main.rs")
|
||||||
|
.arg("-opt-level")
|
||||||
|
.run()
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"warning: option `-o` has no space between flag name and value, which can be confusing",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"note: output filename `-o pt-level` is applied instead of a flag named `opt-level`",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"help: insert a space between `-o` and `pt-level` if this is intentional: `-o pt-level`"
|
||||||
|
);
|
||||||
|
rustc()
|
||||||
|
.input("main.rs")
|
||||||
|
.arg("-overflow-checks")
|
||||||
|
.run()
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"warning: option `-o` has no space between flag name and value, which can be confusing",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"note: output filename `-o verflow-checks` \
|
||||||
|
is applied instead of a flag named `overflow-checks`",
|
||||||
|
)
|
||||||
|
.assert_stderr_contains(
|
||||||
|
"help: insert a space between `-o` and `verflow-checks` \
|
||||||
|
if this is intentional: `-o verflow-checks`",
|
||||||
|
);
|
||||||
|
|
||||||
|
// No warning for Z_OPTIONS
|
||||||
|
rustc().input("main.rs").arg("-oom").run().assert_stderr_equals("");
|
||||||
|
|
||||||
|
// test no warning when there is space between `-o` and arg
|
||||||
|
rustc().input("main.rs").arg("-o").arg("ptimize").run().assert_stderr_equals("");
|
||||||
|
rustc().input("main.rs").arg("--out-dir").arg("xxx").run().assert_stderr_equals("");
|
||||||
|
rustc().input("main.rs").arg("-o").arg("out-dir").run().assert_stderr_equals("");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user