From ead0a60f8cc3f20ddb7432cfa6366a061a2b3af2 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 27 Apr 2025 12:32:28 +0200 Subject: [PATCH 1/7] add `asm_cfg` feature gate --- compiler/rustc_builtin_macros/messages.ftl | 3 ++ compiler/rustc_builtin_macros/src/asm.rs | 38 +++++++++++++-- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + .../ui/feature-gates/feature-gate-asm_cfg.rs | 34 ++++++++++++++ .../feature-gates/feature-gate-asm_cfg.stderr | 47 +++++++++++++++++++ 6 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-asm_cfg.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_cfg.stderr diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 73be954cefd76..336425e4f6940 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -1,6 +1,9 @@ builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function builtin_macros_alloc_must_statics = allocators must be statics +builtin_macros_asm_cfg = + attributes on assembly are unstable + builtin_macros_asm_clobber_abi = clobber_abi builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs builtin_macros_asm_clobber_outputs = generic outputs diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 3e8ddb8abd43f..7ce9818bdd51c 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -10,13 +10,14 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_parse::exp; use rustc_parse::parser::{ExpKeywordPair, Parser}; use rustc_session::lint; -use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw}; +use rustc_session::parse::feature_err; +use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw, sym}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; use {rustc_ast as ast, rustc_parse_format as parse}; -use crate::errors; use crate::util::{ExprToSpannedString, expr_to_spanned_string}; +use crate::{errors, fluent_generated as fluent}; pub struct AsmArgs { pub templates: Vec>, @@ -59,6 +60,33 @@ fn eat_operand_keyword<'a>( } } +/// A parsed list of attributes that is not attached to any item. +/// Used to check whether `asm!` arguments are configured out. +struct AsmAttrList(ast::AttrVec); + +impl AsmAttrList { + fn parse<'a>(ecx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Self> { + let span_start = p.token.span; + + let mut attributes = ast::AttrVec::new(); + loop { + if p.token != token::Pound { + break; + } + + let attr = p.parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted)?; + attributes.push(attr); + } + + if !attributes.is_empty() && !ecx.ecfg.features.asm_cfg() { + let span = span_start.to(p.prev_token.span); + feature_err(ecx.sess, sym::asm_cfg, span, fluent::builtin_macros_asm_cfg).emit(); + } + + Ok(Self(attributes)) + } +} + fn parse_args<'a>( ecx: &ExtCtxt<'a>, sp: Span, @@ -66,12 +94,13 @@ fn parse_args<'a>( asm_macro: AsmMacro, ) -> PResult<'a, AsmArgs> { let mut p = ecx.new_parser_from_tts(tts); - parse_asm_args(&mut p, sp, asm_macro) + parse_asm_args(ecx, &mut p, sp, asm_macro) } // Primarily public for rustfmt consumption. // Internal consumers should continue to leverage `expand_asm`/`expand__global_asm` pub fn parse_asm_args<'a>( + ecx: &ExtCtxt<'a>, p: &mut Parser<'a>, sp: Span, asm_macro: AsmMacro, @@ -82,6 +111,7 @@ pub fn parse_asm_args<'a>( return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp })); } + let _attributes = AsmAttrList::parse(ecx, p)?; let first_template = p.parse_expr()?; let mut args = AsmArgs { templates: vec![first_template], @@ -108,6 +138,8 @@ pub fn parse_asm_args<'a>( break; } // accept trailing commas + let _attributes = AsmAttrList::parse(ecx, p)?; + // Parse clobber_abi if p.eat_keyword(exp!(ClobberAbi)) { parse_clobber_abi(p, &mut args)?; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index cbc121e3632a6..d8e0be0c36142 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -370,6 +370,8 @@ declare_features! ( /// Allows inherent and trait methods with arbitrary self types that are raw pointers. (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), /// Enables experimental inline assembly support for additional architectures. + (unstable, asm_cfg, "CURRENT_RUSTC_VERSION", None), + /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Enables experimental register support in inline assembly. (unstable, asm_experimental_reg, "1.85.0", Some(133416)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 32a5aff0cb327..9740e0ce09096 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -472,6 +472,7 @@ symbols! { as_ref, as_str, asm, + asm_cfg, asm_const, asm_experimental_arch, asm_experimental_reg, diff --git a/tests/ui/feature-gates/feature-gate-asm_cfg.rs b/tests/ui/feature-gates/feature-gate-asm_cfg.rs new file mode 100644 index 0000000000000..042364d190295 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_cfg.rs @@ -0,0 +1,34 @@ +//@ only-x86_64 +#![crate_type = "lib"] + +use std::arch::{asm, global_asm, naked_asm}; + +global_asm!( + "nop", + #[cfg(false)] //~ ERROR attributes on assembly are unstable + "nop" +); + +#[unsafe(naked)] +#[no_mangle] +extern "C" fn naked() { + naked_asm!( + "mov rax, 5", + #[cfg(false)] //~ ERROR attributes on assembly are unstable + "mov rax, {a}", + "ret", + #[cfg(false)] //~ ERROR attributes on assembly are unstable + a = const 10, + ) +} + +fn asm() { + unsafe { + asm!( + "nop", + #[cfg(false)] //~ ERROR attributes on assembly are unstable + clobber_abi("C"), + clobber_abi("C"), //~ ERROR `C` ABI specified multiple times + ); + } +} diff --git a/tests/ui/feature-gates/feature-gate-asm_cfg.stderr b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr new file mode 100644 index 0000000000000..a7f4db300e292 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr @@ -0,0 +1,47 @@ +error[E0658]: attributes on assembly are unstable + --> $DIR/feature-gate-asm_cfg.rs:8:5 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(asm_cfg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: attributes on assembly are unstable + --> $DIR/feature-gate-asm_cfg.rs:17:9 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(asm_cfg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: attributes on assembly are unstable + --> $DIR/feature-gate-asm_cfg.rs:20:9 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(asm_cfg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: attributes on assembly are unstable + --> $DIR/feature-gate-asm_cfg.rs:29:13 + | +LL | #[cfg(false)] + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(asm_cfg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: `C` ABI specified multiple times + --> $DIR/feature-gate-asm_cfg.rs:31:13 + | +LL | clobber_abi("C"), + | ---------------- previously specified here +LL | clobber_abi("C"), + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. From b4fb021be6b8704301d4247144348ee7d4f02469 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 27 Apr 2025 13:32:36 +0200 Subject: [PATCH 2/7] handle cfg on `clobber_abi` --- compiler/rustc_builtin_macros/src/asm.rs | 59 +++++++++++++++++------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 7ce9818bdd51c..b6c998a91a631 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -62,9 +62,9 @@ fn eat_operand_keyword<'a>( /// A parsed list of attributes that is not attached to any item. /// Used to check whether `asm!` arguments are configured out. -struct AsmAttrList(ast::AttrVec); +struct AsmAttrVec(ast::AttrVec); -impl AsmAttrList { +impl AsmAttrVec { fn parse<'a>(ecx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Self> { let span_start = p.token.span; @@ -86,6 +86,28 @@ impl AsmAttrList { Ok(Self(attributes)) } } +impl ast::HasAttrs for AsmAttrVec { + // Follows `ast::Expr`. + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false; + + fn attrs(&self) -> &[rustc_ast::Attribute] { + &self.0 + } + + fn visit_attrs(&mut self, f: impl FnOnce(&mut rustc_ast::AttrVec)) { + f(&mut self.0) + } +} + +impl ast::HasTokens for AsmAttrVec { + fn tokens(&self) -> Option<&rustc_ast::tokenstream::LazyAttrTokenStream> { + None + } + + fn tokens_mut(&mut self) -> Option<&mut Option> { + None + } +} fn parse_args<'a>( ecx: &ExtCtxt<'a>, @@ -107,11 +129,18 @@ pub fn parse_asm_args<'a>( ) -> PResult<'a, AsmArgs> { let dcx = p.dcx(); + let strip_unconfigured = rustc_expand::config::StripUnconfigured { + sess: ecx.sess, + features: Some(ecx.ecfg.features), + config_tokens: false, + lint_node_id: ecx.current_expansion.lint_node_id, + }; + if p.token == token::Eof { return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp })); } - let _attributes = AsmAttrList::parse(ecx, p)?; + let _attributes = AsmAttrVec::parse(ecx, p)?; let first_template = p.parse_expr()?; let mut args = AsmArgs { templates: vec![first_template], @@ -138,12 +167,16 @@ pub fn parse_asm_args<'a>( break; } // accept trailing commas - let _attributes = AsmAttrList::parse(ecx, p)?; + let attributes = AsmAttrVec::parse(ecx, p)?; + let is_configured_out = strip_unconfigured.configure(attributes).is_none(); // Parse clobber_abi if p.eat_keyword(exp!(ClobberAbi)) { - parse_clobber_abi(p, &mut args)?; - allow_templates = false; + let new_abis = parse_clobber_abi(p)?; + if !is_configured_out { + args.clobber_abis.extend(new_abis); + allow_templates = false; + } continue; } @@ -466,7 +499,7 @@ fn parse_options<'a>( Ok(()) } -fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, ()> { +fn parse_clobber_abi<'a>(p: &mut Parser<'a>) -> PResult<'a, Vec<(Symbol, Span)>> { let span_start = p.prev_token.span; p.expect(exp!(OpenParen))?; @@ -497,17 +530,9 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, let full_span = span_start.to(p.prev_token.span); match &new_abis[..] { - // should have errored above during parsing - [] => unreachable!(), - [(abi, _span)] => args.clobber_abis.push((*abi, full_span)), - abis => { - for (abi, span) in abis { - args.clobber_abis.push((*abi, *span)); - } - } + [(abi, _span)] => Ok(vec![(*abi, full_span)]), + _ => Ok(new_abis), } - - Ok(()) } fn parse_reg<'a>( From f8e2002a54ee4f5abb1b8a95a69661642b7dd8f6 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 27 Apr 2025 13:41:54 +0200 Subject: [PATCH 3/7] apply cfg everywhere except for the first template element --- compiler/rustc_builtin_macros/src/asm.rs | 30 +++++-- tests/ui/asm/cfg.rs | 103 +++++++++++++++++++++++ 2 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 tests/ui/asm/cfg.rs diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index b6c998a91a631..39aeed6740022 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -182,8 +182,10 @@ pub fn parse_asm_args<'a>( // Parse options if p.eat_keyword(exp!(Options)) { - parse_options(p, &mut args, asm_macro)?; - allow_templates = false; + parse_options(p, &mut args, asm_macro, is_configured_out)?; + if !is_configured_out { + allow_templates = false; + } continue; } @@ -194,7 +196,9 @@ pub fn parse_asm_args<'a>( let (ident, _) = p.token.ident().unwrap(); p.bump(); p.expect(exp!(Eq))?; - allow_templates = false; + if !is_configured_out { + allow_templates = false; + } Some(ident.name) } else { None @@ -265,6 +269,11 @@ pub fn parse_asm_args<'a>( ast::InlineAsmOperand::Sym { sym } } else if allow_templates { let template = p.parse_expr()?; + + if is_configured_out { + continue; + } + // If it can't possibly expand to a string, provide diagnostics here to include other // things it could have been. match template.kind { @@ -288,6 +297,10 @@ pub fn parse_asm_args<'a>( p.unexpected_any()? }; + if is_configured_out { + continue; + } + allow_templates = false; let span = span_start.to(p.prev_token.span); let slot = args.operands.len(); @@ -451,6 +464,7 @@ fn parse_options<'a>( p: &mut Parser<'a>, args: &mut AsmArgs, asm_macro: AsmMacro, + is_configured_out: bool, ) -> PResult<'a, ()> { let span_start = p.prev_token.span; @@ -478,7 +492,9 @@ fn parse_options<'a>( }; if kw_matched { - try_set_option(p, args, asm_macro, exp.kw, option); + if !is_configured_out { + try_set_option(p, args, asm_macro, exp.kw, option); + } break 'blk; } } @@ -493,8 +509,10 @@ fn parse_options<'a>( p.expect(exp!(Comma))?; } - let new_span = span_start.to(p.prev_token.span); - args.options_spans.push(new_span); + if !is_configured_out { + let new_span = span_start.to(p.prev_token.span); + args.options_spans.push(new_span); + } Ok(()) } diff --git a/tests/ui/asm/cfg.rs b/tests/ui/asm/cfg.rs new file mode 100644 index 0000000000000..1fd2cb5e5ba8e --- /dev/null +++ b/tests/ui/asm/cfg.rs @@ -0,0 +1,103 @@ +// Check that `cfg` and `cfg_attr` work as expected. +// +//@ revisions: reva revb +//@ only-x86_64 +//@ run-pass +#![feature(asm_cfg, cfg_match)] + +use std::arch::{asm, naked_asm}; + +#[unsafe(naked)] +extern "C" fn ignore_const_operand() -> u64 { + naked_asm!( + "mov rax, 5", + #[cfg(revb)] + "mov rax, {a}", + "ret", + #[cfg(revb)] + a = const 10, + ) +} + +#[unsafe(naked)] +extern "C" fn ignore_const_operand_cfg_attr() -> u64 { + naked_asm!( + "mov rax, 5", + #[cfg_attr(true, cfg(revb))] + "mov rax, {a}", + "ret", + #[cfg_attr(true, cfg(revb))] + a = const 10, + ) +} + +#[unsafe(naked)] +extern "C" fn const_operand() -> u64 { + naked_asm!( + "mov rax, {a}", + "ret", + #[cfg(reva)] + a = const 5, + #[cfg(revb)] + a = const 10, + ) +} + +fn options() { + // Without the cfg, this throws an error that the `noreturn` option is provided twice. + unsafe { + asm!( + "nop", + #[cfg(false)] + options(att_syntax), + options(att_syntax) + ) + } +} + +fn clobber_abi() { + // Without the cfg, this throws an error that the "C" abi is provided twice. + unsafe { + asm!( + "nop", + #[cfg(false)] + clobber_abi("C"), + clobber_abi("C"), + ); + } +} + +fn template_allowed() { + // Without the cfg, templates are not allowed after operands. + unsafe { + asm!( + "nop", + #[cfg(false)] + clobber_abi("C"), + #[cfg(false)] + options(att_syntax), + #[cfg(false)] + a = out(reg) x, + "nop", + ); + } +} + +pub fn main() { + std::cfg_match! { + reva => { + assert_eq!(const_operand(), 5); + assert_eq!(ignore_const_operand_cfg_attr(), 5); + assert_eq!(ignore_const_operand(), 5); + + } + revb => { + assert_eq!(const_operand(), 10); + assert_eq!(ignore_const_operand_cfg_attr(), 10); + assert_eq!(ignore_const_operand(), 10); + } + } + options(); + clobber_abi(); + template_allowed(); +} From 56a9de89da924575b7dea978d73108441aea1b57 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 27 Apr 2025 13:46:49 +0200 Subject: [PATCH 4/7] don't configure anything out if the feature is not enabled --- compiler/rustc_builtin_macros/src/asm.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 39aeed6740022..2e74400cb2d1a 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -168,7 +168,8 @@ pub fn parse_asm_args<'a>( } // accept trailing commas let attributes = AsmAttrVec::parse(ecx, p)?; - let is_configured_out = strip_unconfigured.configure(attributes).is_none(); + let is_configured_out = + ecx.ecfg.features.asm_cfg() && strip_unconfigured.configure(attributes).is_none(); // Parse clobber_abi if p.eat_keyword(exp!(ClobberAbi)) { From 3e00278221b76baf8de7107a7cbbc90e9e8fa96e Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 27 Apr 2025 15:10:52 +0200 Subject: [PATCH 5/7] accept cfg on the first template --- compiler/rustc_builtin_macros/src/asm.rs | 19 +++++++++++++++++-- tests/ui/asm/cfg.rs | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 2e74400cb2d1a..7c2fc17b8f5d2 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -140,8 +140,23 @@ pub fn parse_asm_args<'a>( return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp })); } - let _attributes = AsmAttrVec::parse(ecx, p)?; - let first_template = p.parse_expr()?; + let first_template = loop { + let attributes = AsmAttrVec::parse(ecx, p)?; + let is_configured_out = + ecx.ecfg.features.asm_cfg() && strip_unconfigured.configure(attributes).is_none(); + + let template = p.parse_expr()?; + + if !is_configured_out { + break template; + } + + if !p.eat(exp!(Comma)) { + // After a template string, we always expect *only* a comma... + return Err(dcx.create_err(errors::AsmExpectedComma { span: p.token.span })); + } + }; + let mut args = AsmArgs { templates: vec![first_template], operands: vec![], diff --git a/tests/ui/asm/cfg.rs b/tests/ui/asm/cfg.rs index 1fd2cb5e5ba8e..944bf9579cf01 100644 --- a/tests/ui/asm/cfg.rs +++ b/tests/ui/asm/cfg.rs @@ -83,18 +83,32 @@ fn template_allowed() { } } +#[unsafe(naked)] +extern "C" fn first_template() -> u64 { + naked_asm!( + #[cfg(reva)] + "mov rax, 5", + #[cfg(revb)] + "mov rax, 10", + "ret", + ) +} + pub fn main() { std::cfg_match! { reva => { assert_eq!(const_operand(), 5); assert_eq!(ignore_const_operand_cfg_attr(), 5); assert_eq!(ignore_const_operand(), 5); + assert_eq!(first_template(), 5); } revb => { assert_eq!(const_operand(), 10); assert_eq!(ignore_const_operand_cfg_attr(), 10); assert_eq!(ignore_const_operand(), 10); + assert_eq!(first_template(), 10); + } } options(); From c7b63c86f93ac9e3ef67253f704585d1f801b129 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 27 Apr 2025 15:28:55 +0200 Subject: [PATCH 6/7] fix tracking issue number --- compiler/rustc_feature/src/unstable.rs | 4 ++-- tests/ui/feature-gates/feature-gate-asm_cfg.stderr | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index d8e0be0c36142..9c0a6733d5294 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -369,8 +369,8 @@ declare_features! ( (unstable, arbitrary_self_types, "1.23.0", Some(44874)), /// Allows inherent and trait methods with arbitrary self types that are raw pointers. (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), - /// Enables experimental inline assembly support for additional architectures. - (unstable, asm_cfg, "CURRENT_RUSTC_VERSION", None), + /// Allows #[cfg(...)] on inline assembly templates and operands. + (unstable, asm_cfg, "CURRENT_RUSTC_VERSION", Some(140364)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Enables experimental register support in inline assembly. diff --git a/tests/ui/feature-gates/feature-gate-asm_cfg.stderr b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr index a7f4db300e292..f78a3dbeaa1d7 100644 --- a/tests/ui/feature-gates/feature-gate-asm_cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr @@ -4,6 +4,7 @@ error[E0658]: attributes on assembly are unstable LL | #[cfg(false)] | ^^^^^^^^^^^^^ | + = note: see issue #140364 for more information = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -13,6 +14,7 @@ error[E0658]: attributes on assembly are unstable LL | #[cfg(false)] | ^^^^^^^^^^^^^ | + = note: see issue #140364 for more information = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -22,6 +24,7 @@ error[E0658]: attributes on assembly are unstable LL | #[cfg(false)] | ^^^^^^^^^^^^^ | + = note: see issue #140364 for more information = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -31,6 +34,7 @@ error[E0658]: attributes on assembly are unstable LL | #[cfg(false)] | ^^^^^^^^^^^^^ | + = note: see issue #140364 for more information = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date From 5cfd71aec24ee87b5116c863d623f8752c272e53 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 27 Apr 2025 15:58:31 +0200 Subject: [PATCH 7/7] error on non-cfg attributes on assembly --- compiler/rustc_builtin_macros/messages.ftl | 5 +++- compiler/rustc_builtin_macros/src/asm.rs | 16 ++++++++++--- compiler/rustc_builtin_macros/src/errors.rs | 7 ++++++ .../ui/feature-gates/feature-gate-asm_cfg.rs | 22 +++++++++++++---- .../feature-gates/feature-gate-asm_cfg.stderr | 24 ++++++++++++------- 5 files changed, 57 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 336425e4f6940..cb6bf184ceae2 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -1,8 +1,11 @@ builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function builtin_macros_alloc_must_statics = allocators must be statics +builtin_macros_asm_attribute_not_supported = + this attribute is not supported on assembly + builtin_macros_asm_cfg = - attributes on assembly are unstable + the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable builtin_macros_asm_clobber_abi = clobber_abi builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 7c2fc17b8f5d2..a09c84de06ea8 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -78,9 +78,19 @@ impl AsmAttrVec { attributes.push(attr); } - if !attributes.is_empty() && !ecx.ecfg.features.asm_cfg() { - let span = span_start.to(p.prev_token.span); - feature_err(ecx.sess, sym::asm_cfg, span, fluent::builtin_macros_asm_cfg).emit(); + for attr in attributes.iter() { + match attr.name() { + Some(sym::cfg | sym::cfg_attr) => { + if !ecx.ecfg.features.asm_cfg() { + let span = span_start.to(p.prev_token.span); + feature_err(ecx.sess, sym::asm_cfg, span, fluent::builtin_macros_asm_cfg) + .emit(); + } + } + _ => { + ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() }); + } + } } Ok(Self(attributes)) diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index d14ad8f40144c..012815db318d1 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -795,6 +795,13 @@ pub(crate) struct AsmRequiresTemplate { pub(crate) span: Span, } +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_attribute_not_supported)] +pub(crate) struct AsmAttributeNotSupported { + #[primary_span] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag(builtin_macros_asm_expected_comma)] pub(crate) struct AsmExpectedComma { diff --git a/tests/ui/feature-gates/feature-gate-asm_cfg.rs b/tests/ui/feature-gates/feature-gate-asm_cfg.rs index 042364d190295..ef8bf75b6929d 100644 --- a/tests/ui/feature-gates/feature-gate-asm_cfg.rs +++ b/tests/ui/feature-gates/feature-gate-asm_cfg.rs @@ -5,7 +5,8 @@ use std::arch::{asm, global_asm, naked_asm}; global_asm!( "nop", - #[cfg(false)] //~ ERROR attributes on assembly are unstable + #[cfg(false)] + //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable "nop" ); @@ -14,10 +15,12 @@ global_asm!( extern "C" fn naked() { naked_asm!( "mov rax, 5", - #[cfg(false)] //~ ERROR attributes on assembly are unstable + #[cfg(false)] + //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable "mov rax, {a}", "ret", - #[cfg(false)] //~ ERROR attributes on assembly are unstable + #[cfg(false)] + //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable a = const 10, ) } @@ -26,9 +29,20 @@ fn asm() { unsafe { asm!( "nop", - #[cfg(false)] //~ ERROR attributes on assembly are unstable + #[cfg(false)] + //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable clobber_abi("C"), clobber_abi("C"), //~ ERROR `C` ABI specified multiple times ); } } + +fn bad_attribute() { + unsafe { + asm!( + #[inline] + //~^ ERROR this attribute is not supported on assembly + "nop" + ) + }; +} diff --git a/tests/ui/feature-gates/feature-gate-asm_cfg.stderr b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr index f78a3dbeaa1d7..e92d1e8c48747 100644 --- a/tests/ui/feature-gates/feature-gate-asm_cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr @@ -1,4 +1,4 @@ -error[E0658]: attributes on assembly are unstable +error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable --> $DIR/feature-gate-asm_cfg.rs:8:5 | LL | #[cfg(false)] @@ -8,8 +8,8 @@ LL | #[cfg(false)] = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: attributes on assembly are unstable - --> $DIR/feature-gate-asm_cfg.rs:17:9 +error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable + --> $DIR/feature-gate-asm_cfg.rs:18:9 | LL | #[cfg(false)] | ^^^^^^^^^^^^^ @@ -18,8 +18,8 @@ LL | #[cfg(false)] = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: attributes on assembly are unstable - --> $DIR/feature-gate-asm_cfg.rs:20:9 +error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable + --> $DIR/feature-gate-asm_cfg.rs:22:9 | LL | #[cfg(false)] | ^^^^^^^^^^^^^ @@ -28,8 +28,8 @@ LL | #[cfg(false)] = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: attributes on assembly are unstable - --> $DIR/feature-gate-asm_cfg.rs:29:13 +error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable + --> $DIR/feature-gate-asm_cfg.rs:32:13 | LL | #[cfg(false)] | ^^^^^^^^^^^^^ @@ -38,14 +38,20 @@ LL | #[cfg(false)] = help: add `#![feature(asm_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: this attribute is not supported on assembly + --> $DIR/feature-gate-asm_cfg.rs:43:13 + | +LL | #[inline] + | ^^^^^^^^^ + error: `C` ABI specified multiple times - --> $DIR/feature-gate-asm_cfg.rs:31:13 + --> $DIR/feature-gate-asm_cfg.rs:35:13 | LL | clobber_abi("C"), | ---------------- previously specified here LL | clobber_abi("C"), | ^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`.