Skip to content

Commit c8bc460

Browse files
committed
Deny using path-segment kw when parsing cfg pred
1 parent 54a8a1d commit c8bc460

21 files changed

+536
-9
lines changed

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ impl<'sess> AttributeParser<'sess, Early> {
118118
target_node_id: NodeId,
119119
features: Option<&'sess Features>,
120120
emit_errors: ShouldEmit,
121+
parsing_cfg: bool,
121122
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>,
122123
template: &AttributeTemplate,
123124
) -> Option<T> {
@@ -133,7 +134,8 @@ impl<'sess> AttributeParser<'sess, Early> {
133134
};
134135
let parts =
135136
normal_attr.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();
136-
let meta_parser = MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors)?;
137+
let meta_parser =
138+
MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors, parsing_cfg)?;
137139
let path = meta_parser.path();
138140
let args = meta_parser.args();
139141
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
@@ -251,6 +253,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
251253
&parts,
252254
&self.sess.psess,
253255
self.stage.should_emit(),
256+
false,
254257
) else {
255258
continue;
256259
};

compiler/rustc_attr_parsing/src/parser.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ impl<'a> ArgParser<'a> {
104104
parts: &[Symbol],
105105
psess: &'sess ParseSess,
106106
should_emit: ShouldEmit,
107+
parsing_cfg: bool,
107108
) -> Option<Self> {
108109
Some(match value {
109110
AttrArgs::Empty => Self::NoArgs,
@@ -124,7 +125,7 @@ impl<'a> ArgParser<'a> {
124125
return None;
125126
}
126127

127-
Self::List(MetaItemListParser::new(args, psess, should_emit)?)
128+
Self::List(MetaItemListParser::new(args, psess, should_emit, parsing_cfg)?)
128129
}
129130
AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
130131
eq_span: *eq_span,
@@ -248,10 +249,17 @@ impl<'a> MetaItemParser<'a> {
248249
parts: &[Symbol],
249250
psess: &'sess ParseSess,
250251
should_emit: ShouldEmit,
252+
parsing_cfg: bool,
251253
) -> Option<Self> {
252254
Some(Self {
253255
path: PathParser(Cow::Borrowed(&attr.item.path)),
254-
args: ArgParser::from_attr_args(&attr.item.args, parts, psess, should_emit)?,
256+
args: ArgParser::from_attr_args(
257+
&attr.item.args,
258+
parts,
259+
psess,
260+
should_emit,
261+
parsing_cfg,
262+
)?,
255263
})
256264
}
257265
}
@@ -425,7 +433,12 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
425433
};
426434
}
427435

428-
let path = self.parser.parse_path(PathStyle::Mod)?;
436+
let path = if self.parser.parse_cfg_pred {
437+
self.parser.parse_cfg_pred = false;
438+
Path::from_ident(self.parser.parse_ident()?)
439+
} else {
440+
self.parser.parse_path(PathStyle::Mod)?
441+
};
429442

430443
// Check style of arguments that this meta item has
431444
let args = if self.parser.check(exp!(OpenParen)) {
@@ -513,8 +526,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
513526
psess: &'sess ParseSess,
514527
span: Span,
515528
should_emit: ShouldEmit,
529+
parsing_cfg: bool,
516530
) -> PResult<'sess, MetaItemListParser<'static>> {
517531
let mut parser = Parser::new(psess, tokens, None);
532+
parser.parse_cfg_pred = parsing_cfg;
533+
518534
let mut this = MetaItemListParserContext { parser: &mut parser, should_emit };
519535

520536
// Presumably, the majority of the time there will only be one attr.
@@ -546,12 +562,14 @@ impl<'a> MetaItemListParser<'a> {
546562
delim: &'a DelimArgs,
547563
psess: &'sess ParseSess,
548564
should_emit: ShouldEmit,
565+
parsing_cfg: bool,
549566
) -> Option<Self> {
550567
match MetaItemListParserContext::parse(
551568
delim.tokens.clone(),
552569
psess,
553570
delim.dspan.entire(),
554571
should_emit,
572+
parsing_cfg,
555573
) {
556574
Ok(s) => Some(s),
557575
Err(e) => {

compiler/rustc_builtin_macros/src/cfg.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ fn parse_cfg<'a>(
4242
tts: TokenStream,
4343
) -> PResult<'a, ast::MetaItemInner> {
4444
let mut p = cx.new_parser_from_tts(tts);
45+
p.parse_cfg_pred = true;
4546

4647
if p.token == token::Eof {
4748
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));

compiler/rustc_expand/src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ impl<'a> StripUnconfigured<'a> {
428428
node,
429429
self.features,
430430
emit_errors,
431+
true,
431432
parse_cfg_attr,
432433
&CFG_TEMPLATE,
433434
) else {

compiler/rustc_interface/src/interface.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,22 @@ 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-
return (ident.name, meta_item.value_str());
86+
87+
if ident.is_reserved()
88+
&& !s.contains(&format!("r#{}", ident.as_str()))
89+
{
90+
error!("argument key must be an identifier");
91+
} else {
92+
return (ident.name, meta_item.value_str());
93+
}
8794
}
8895
}
8996
}
9097
Ok(..) => {}
9198
Err(err) => err.cancel(),
9299
},
93100
Err(errs) => errs.into_iter().for_each(|err| err.cancel()),
94-
}
101+
};
95102

96103
// If the user tried to use a key="value" flag, but is missing the quotes, provide
97104
// a hint about how to resolve this.

compiler/rustc_parse/src/parser/attr.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast as ast;
22
use rustc_ast::token::{self, MetaVarKind};
33
use rustc_ast::tokenstream::ParserRange;
4-
use rustc_ast::{Attribute, attr};
4+
use rustc_ast::{Attribute, Path, attr};
55
use rustc_errors::codes::*;
66
use rustc_errors::{Diag, PResult};
77
use rustc_span::{BytePos, Span};
@@ -381,6 +381,7 @@ impl<'a> Parser<'a> {
381381
pub fn parse_cfg_attr(
382382
&mut self,
383383
) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> {
384+
self.parse_cfg_pred = true;
384385
let cfg_predicate = self.parse_meta_item_inner()?;
385386
self.expect(exp!(Comma))?;
386387

@@ -449,7 +450,13 @@ impl<'a> Parser<'a> {
449450
ast::Safety::Default
450451
};
451452

452-
let path = self.parse_path(PathStyle::Mod)?;
453+
let path = if self.parse_cfg_pred {
454+
self.parse_cfg_pred = false;
455+
Path::from_ident(self.parse_ident()?)
456+
} else {
457+
self.parse_path(PathStyle::Mod)?
458+
};
459+
453460
let kind = self.parse_meta_item_kind()?;
454461
if is_unsafe {
455462
self.expect(exp!(CloseParen))?;

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ pub struct Parser<'a> {
181181
/// The previous token.
182182
pub prev_token: Token,
183183
pub capture_cfg: bool,
184+
pub parse_cfg_pred: bool,
184185
restrictions: Restrictions,
185186
expected_token_types: TokenTypeSet,
186187
token_cursor: TokenCursor,
@@ -372,6 +373,7 @@ impl<'a> Parser<'a> {
372373
},
373374
current_closure: None,
374375
recovery: Recovery::Allowed,
376+
parse_cfg_pred: false,
375377
};
376378

377379
// Make parser point to the first token.

compiler/rustc_span/src/symbol.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3034,7 +3034,9 @@ impl Symbol {
30343034

30353035
/// Returns `true` if this symbol can be a raw identifier.
30363036
pub fn can_be_raw(self) -> bool {
3037-
self != sym::empty && self != kw::Underscore && !self.is_path_segment_keyword()
3037+
self != sym::empty
3038+
&& self != kw::Underscore
3039+
&& !matches!(self, kw::PathRoot | kw::DollarCrate)
30383040
}
30393041

30403042
/// Was this symbol index predefined in the compiler's `symbols!` macro?
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//@ edition: 2024
2+
//@ check-pass
3+
//@ compile-flags: --cfg r#crate --cfg r#super --cfg r#self --cfg r#Self --cfg r#struct --cfg r#enum --cfg r#async --cfg r#impl --cfg r#trait
4+
5+
fn main() {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: invalid `--cfg` argument: `async` (argument key must be an identifier)
2+

0 commit comments

Comments
 (0)