Skip to content

Commit 590be65

Browse files
authored
Emit error when using path-segment keyword as cfg pred
1 parent 5f9dd05 commit 590be65

File tree

38 files changed

+875
-29
lines changed

38 files changed

+875
-29
lines changed

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ pub fn parse_cfg_entry<S: Stage>(
8282
}
8383
},
8484
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
85-
let Some(name) = meta.path().word_sym() else {
85+
let Some(name) = meta.path().word_sym().filter(|s| !s.is_path_segment_keyword())
86+
else {
8687
return Err(cx.expected_identifier(meta.path().span()));
8788
};
8889
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
@@ -158,7 +159,7 @@ fn parse_cfg_entry_target<S: Stage>(
158159
};
159160

160161
// Then, parse it as a name-value item
161-
let Some(name) = sub_item.path().word_sym() else {
162+
let Some(name) = sub_item.path().word_sym().filter(|s| !s.is_path_segment_keyword()) else {
162163
return Err(cx.expected_identifier(sub_item.path().span()));
163164
};
164165
let name = Symbol::intern(&format!("target_{name}"));

compiler/rustc_attr_parsing/src/attributes/cfg_old.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ pub fn eval_condition(
220220
}
221221
}
222222
}
223-
MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
223+
MetaItemKind::Word | MetaItemKind::NameValue(..)
224+
if cfg.path.segments.len() != 1
225+
|| cfg.path.segments[0].ident.is_path_segment_keyword() =>
226+
{
224227
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
225228
true
226229
}

compiler/rustc_interface/src/interface.rs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
6363
#[allow(rustc::untranslatable_diagnostic)]
6464
#[allow(rustc::diagnostic_outside_of_impl)]
6565
dcx.fatal(format!(
66-
concat!("invalid `--cfg` argument: `{}` (", $reason, ")"),
67-
s
66+
concat!("invalid `--cfg` argument: `{}` ({})"),
67+
s, $reason,
6868
));
6969
};
7070
}
@@ -83,6 +83,19 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
8383
}
8484
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
8585
let ident = meta_item.ident().expect("multi-segment cfg key");
86+
87+
if ident.is_reserved() {
88+
if !ident.name.can_be_raw() {
89+
if s.trim().starts_with(&format!("r#{}", ident.as_str())) {
90+
error!(format!("argument key must be an identifier, but `{}` cannot be a raw identifier", ident.name));
91+
} else {
92+
error!(format!("argument key must be an identifier but found keyword `{}`", ident.name));
93+
}
94+
} else if !s.trim().starts_with(&ident.to_string()) {
95+
error!(format!("argument key must be an identifier but found keyword `{}`, escape it using `{}`", ident.as_str(), ident));
96+
}
97+
}
98+
8699
return (ident.name, meta_item.value_str());
87100
}
88101
}
@@ -91,7 +104,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
91104
Err(err) => err.cancel(),
92105
},
93106
Err(errs) => errs.into_iter().for_each(|err| err.cancel()),
94-
}
107+
};
95108

96109
// If the user tried to use a key="value" flag, but is missing the quotes, provide
97110
// a hint about how to resolve this.
@@ -202,18 +215,54 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
202215
let mut values_specified = false;
203216
let mut values_any_specified = false;
204217

218+
let arg_strs = s
219+
.trim()
220+
.trim_start_matches("cfg(")
221+
.trim_end_matches(')')
222+
.split(',')
223+
.collect::<Vec<_>>();
224+
205225
for arg in args {
206226
if arg.is_word()
207227
&& let Some(ident) = arg.ident()
208228
{
209229
if values_specified {
210230
error!("`cfg()` names cannot be after values");
211231
}
232+
233+
if ident.is_reserved() {
234+
if !ident.name.can_be_raw() {
235+
if arg_strs[names.len()].starts_with(&format!("r#{}", ident.as_str())) {
236+
error!(format!(
237+
"argument key must be an identifier, but `{}` cannot be a raw identifier",
238+
ident.name
239+
));
240+
} else {
241+
error!(format!(
242+
"argument key must be an identifier but found keyword `{}`",
243+
ident.name
244+
));
245+
}
246+
} else if !arg_strs[names.len()].starts_with(&ident.to_string()) {
247+
error!(format!(
248+
"argument key must be an identifier but found keyword `{}`, escape it using `{}`",
249+
ident.as_str(),
250+
ident
251+
));
252+
}
253+
}
254+
212255
names.push(ident);
213256
} else if let Some(boolean) = arg.boolean_literal() {
214257
if values_specified {
215258
error!("`cfg()` names cannot be after values");
216259
}
260+
261+
let lit_str = arg_strs[names.len()];
262+
if !lit_str.starts_with("r#") {
263+
error!(in arg, format!("`cfg()` names must be identifiers but found keyword `{lit_str}`, escape it using `r#{lit_str}`"));
264+
}
265+
217266
names.push(rustc_span::Ident::new(
218267
if boolean { rustc_span::kw::True } else { rustc_span::kw::False },
219268
arg.span(),

tests/codegen-llvm/cf-protection.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Test that the correct module flags are emitted with different control-flow protection flags.
22

33
//@ add-minicore
4-
//@ revisions: undefined none branch return full
4+
//@ revisions: undefined none branch return_ full
55
//@ needs-llvm-components: x86
66
// [undefined] no extra compile-flags
77
//@ [none] compile-flags: -Z cf-protection=none
88
//@ [branch] compile-flags: -Z cf-protection=branch
9-
//@ [return] compile-flags: -Z cf-protection=return
9+
//@ [return_] compile-flags: -Z cf-protection=return
1010
//@ [full] compile-flags: -Z cf-protection=full
1111
//@ compile-flags: --target x86_64-unknown-linux-gnu
1212

@@ -30,9 +30,9 @@ pub fn test() {}
3030
// branch: !"cf-protection-branch", i32 1
3131
// branch-NOT: !"cf-protection-return"
3232

33-
// return-NOT: !"cf-protection-branch"
34-
// return: !"cf-protection-return", i32 1
35-
// return-NOT: !"cf-protection-branch"
33+
// return_-NOT: !"cf-protection-branch"
34+
// return_: !"cf-protection-return", i32 1
35+
// return_-NOT: !"cf-protection-branch"
3636

3737
// full: !"cf-protection-branch", i32 1
3838
// full: !"cf-protection-return", i32 1

tests/ui/cfg/cmdline-false.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/// Test that `--cfg false` doesn't cause `cfg(false)` to evaluate to `true`
2-
//@ compile-flags: --cfg false
2+
//@ compile-flags: --cfg r#false
33

44
#[cfg(false)]
55
fn foo() {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid `--cfg` argument: `crate` (argument key must be an identifier but found keyword `crate`)
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid `--cfg` argument: `priv` (argument key must be an identifier but found keyword `priv`, escape it using `r#priv`)
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid `--cfg` argument: `r#crate` (argument key must be an identifier, but `crate` cannot be a raw identifier)
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid `--cfg` argument: `r#self` (argument key must be an identifier, but `self` cannot be a raw identifier)
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid `--cfg` argument: `r#Self` (argument key must be an identifier, but `Self` cannot be a raw identifier)
2+

0 commit comments

Comments
 (0)