From ceec6ddf9e2d4a41828fce4587180029588ae8eb Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 16 Jul 2024 22:06:34 +0200 Subject: [PATCH 1/7] update text for E0736 and E0739 --- .../src/error_codes/E0736.md | 20 ++++++++++++++----- .../src/error_codes/E0739.md | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0736.md b/compiler/rustc_error_codes/src/error_codes/E0736.md index 0f3d41ba66d..08aa85e705d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0736.md +++ b/compiler/rustc_error_codes/src/error_codes/E0736.md @@ -1,14 +1,24 @@ -`#[track_caller]` and `#[naked]` cannot both be applied to the same function. +Functions marked with the `#[naked]` attribute are restricted in what other +code generation attributes they may be marked with. + +The following code generation attributes are incompatible with `#[naked]`: + + * `#[inline]` + * `#[track_caller]` + * `#[target_feature]` Erroneous code example: ```compile_fail,E0736 +#[inline] #[naked] -#[track_caller] fn foo() {} ``` -This is primarily due to ABI incompatibilities between the two attributes. -See [RFC 2091] for details on this and other limitations. +These incompatibilities are due to the fact that naked functions deliberately +impose strict restrictions regarding the code that the compiler is +allowed to produce for this function. -[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md +See [the reference page for codegen attributes] for more information. + +[the reference page for codegen attributes]: https://doc.rust-lang.org/reference/attributes/codegen.html diff --git a/compiler/rustc_error_codes/src/error_codes/E0739.md b/compiler/rustc_error_codes/src/error_codes/E0739.md index 8d9039bef93..406d3d52779 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0739.md +++ b/compiler/rustc_error_codes/src/error_codes/E0739.md @@ -1,4 +1,4 @@ -`#[track_caller]` can not be applied on struct. +`#[track_caller]` must be applied to a function Erroneous code example: From 4bd36324b6a19afdbcb53de1d41e65b0060a6dbb Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 16 Jul 2024 23:03:13 +0200 Subject: [PATCH 2/7] improve error message when `#[naked]` is used with `#[inline]` --- compiler/rustc_passes/messages.ftl | 11 +++-- compiler/rustc_passes/src/check_attr.rs | 33 +++++++++++---- compiler/rustc_passes/src/errors.rs | 24 +++++------ compiler/rustc_passes/src/naked_functions.rs | 14 +------ tests/ui/asm/naked-functions-inline.rs | 31 ++++++++++++++ tests/ui/asm/naked-functions-inline.stderr | 27 ++++++++++++ tests/ui/asm/naked-functions.rs | 31 -------------- tests/ui/asm/naked-functions.stderr | 44 ++------------------ 8 files changed, 104 insertions(+), 111 deletions(-) create mode 100644 tests/ui/asm/naked-functions-inline.rs create mode 100644 tests/ui/asm/naked-functions-inline.stderr diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 1d93cbaddd6..2b6841181a7 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -69,9 +69,6 @@ passes_break_non_loop = .suggestion = use `break` on its own without a value inside this `{$kind}` loop .break_expr_suggestion = alternatively, you might have meant to use the available loop label -passes_cannot_inline_naked_function = - naked functions cannot be inlined - passes_cannot_stabilize_deprecated = an API can't be stabilized after it is deprecated .label = invalid version @@ -485,6 +482,11 @@ passes_naked_functions_asm_block = passes_naked_functions_asm_options = asm options unsupported in naked functions: {$unsupported_options} +passes_naked_functions_codegen_attribute = + cannot use additional code generation attributes with `#[naked]` + .label = this attribute is incompatible with `#[naked]` + .label2 = function marked with `#[naked]` here + passes_naked_functions_must_use_noreturn = asm in naked functions must use `noreturn` option .suggestion = consider specifying that the asm block is responsible for returning from the function @@ -492,9 +494,6 @@ passes_naked_functions_must_use_noreturn = passes_naked_functions_operands = only `const` and `sym` operands are supported in naked functions -passes_naked_tracked_caller = - cannot use `#[track_caller]` with `#[naked]` - passes_no_link = attribute should be applied to an `extern crate` item .label = not an `extern crate` item diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ce2fa83810f..739847d73d3 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -155,7 +155,7 @@ fn check_attributes( [sym::rustc_std_internal_symbol] => { self.check_rustc_std_internal_symbol(attr, span, target) } - [sym::naked] => self.check_naked(hir_id, attr, span, target), + [sym::naked] => self.check_naked(hir_id, attr, span, target, attrs), [sym::rustc_never_returns_null_ptr] => { self.check_applied_to_fn_or_method(hir_id, attr, span, target) } @@ -410,12 +410,33 @@ fn check_generic_attr( } /// Checks if `#[naked]` is applied to a function definition. - fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_naked( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + attrs: &[Attribute], + ) -> bool { + const FORBIDDEN: [rustc_span::Symbol; 3] = + [sym::track_caller, sym::inline, sym::target_feature]; + + for other_attr in attrs { + if FORBIDDEN.into_iter().any(|name| other_attr.has_name(name)) { + self.dcx().emit_err(errors::NakedFunctionCodegenAttribute { + span: other_attr.span, + naked_span: attr.span, + }); + + return false; + } + } + match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[allow_internal_unstable]` attribute with just a lint, because we previously + // `#[naked]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { @@ -488,7 +509,7 @@ fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target) } } - /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid. + /// Checks if a `#[track_caller]` is applied to a function. Returns `true` if valid. fn check_track_caller( &self, hir_id: HirId, @@ -498,10 +519,6 @@ fn check_track_caller( target: Target, ) -> bool { match target { - _ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => { - self.dcx().emit_err(errors::NakedTrackedCaller { attr_span }); - false - } Target::Fn => { // `#[track_caller]` is not valid on weak lang items because they are called via // `extern` declarations and `#[track_caller]` would alter their ABI. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 58d27d5b4bb..03105795bfc 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -79,13 +79,6 @@ pub struct AttrShouldBeAppliedToFn { pub on_crate: bool, } -#[derive(Diagnostic)] -#[diag(passes_naked_tracked_caller, code = E0736)] -pub struct NakedTrackedCaller { - #[primary_span] - pub attr_span: Span, -} - #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn, code = E0739)] pub struct TrackedCallerWrongLocation { @@ -1124,13 +1117,6 @@ pub struct UnlabeledCfInWhileCondition<'a> { pub cf_type: &'a str, } -#[derive(Diagnostic)] -#[diag(passes_cannot_inline_naked_function)] -pub struct CannotInlineNakedFunction { - #[primary_span] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_undefined_naked_function_abi)] pub struct UndefinedNakedFunctionAbi; @@ -1196,6 +1182,16 @@ pub struct NakedFunctionsMustUseNoreturn { pub last_span: Span, } +#[derive(Diagnostic)] +#[diag(passes_naked_functions_codegen_attribute, code = E0736)] +pub struct NakedFunctionCodegenAttribute { + #[primary_span] + #[label] + pub span: Span, + #[label(passes_label2)] + pub naked_span: Span, +} + #[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] pub struct AttrOnlyInFunctions { diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index d45ee32a624..4040fbd182e 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -14,9 +14,8 @@ use rustc_target::spec::abi::Abi; use crate::errors::{ - CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, - NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, - UndefinedNakedFunctionAbi, + NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn, + NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi, }; pub(crate) fn provide(providers: &mut Providers) { @@ -53,15 +52,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { check_no_patterns(tcx, body.params); check_no_parameters_use(tcx, body); check_asm(tcx, def_id, body); - check_inline(tcx, def_id); - } -} - -/// Check that the function isn't inlined. -fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let attrs = tcx.get_attrs(def_id, sym::inline); - for attr in attrs { - tcx.dcx().emit_err(CannotInlineNakedFunction { span: attr.span }); } } diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs new file mode 100644 index 00000000000..9a4f7547518 --- /dev/null +++ b/tests/ui/asm/naked-functions-inline.rs @@ -0,0 +1,31 @@ +//@ needs-asm-support +#![feature(naked_functions)] +#![crate_type = "lib"] + +use std::arch::asm; + +#[naked] +pub unsafe extern "C" fn inline_none() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline] +//~^ ERROR [E0736] +pub unsafe extern "C" fn inline_hint() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline(always)] +//~^ ERROR [E0736] +pub unsafe extern "C" fn inline_always() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline(never)] +//~^ ERROR [E0736] +pub unsafe extern "C" fn inline_never() { + asm!("", options(noreturn)); +} diff --git a/tests/ui/asm/naked-functions-inline.stderr b/tests/ui/asm/naked-functions-inline.stderr new file mode 100644 index 00000000000..2496e942b17 --- /dev/null +++ b/tests/ui/asm/naked-functions-inline.stderr @@ -0,0 +1,27 @@ +error[E0736]: cannot use additional code generation attributes with `#[naked]` + --> $DIR/naked-functions-inline.rs:13:1 + | +LL | #[naked] + | -------- function marked with `#[naked]` here +LL | #[inline] + | ^^^^^^^^^ this attribute is incompatible with `#[naked]` + +error[E0736]: cannot use additional code generation attributes with `#[naked]` + --> $DIR/naked-functions-inline.rs:20:1 + | +LL | #[naked] + | -------- function marked with `#[naked]` here +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` + +error[E0736]: cannot use additional code generation attributes with `#[naked]` + --> $DIR/naked-functions-inline.rs:27:1 + | +LL | #[naked] + | -------- function marked with `#[naked]` here +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0736`. diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 1619ebfcf39..e6633ddd4f3 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -168,37 +168,6 @@ pub extern "C" fn valid_b() { } #[naked] -#[inline] -//~^ ERROR naked functions cannot be inlined -pub unsafe extern "C" fn inline_hint() { - asm!("", options(noreturn)); -} - -#[naked] -#[inline(always)] -//~^ ERROR naked functions cannot be inlined -pub unsafe extern "C" fn inline_always() { - asm!("", options(noreturn)); -} - -#[naked] -#[inline(never)] -//~^ ERROR naked functions cannot be inlined -pub unsafe extern "C" fn inline_never() { - asm!("", options(noreturn)); -} - -#[naked] -#[inline] -//~^ ERROR naked functions cannot be inlined -#[inline(always)] -//~^ ERROR naked functions cannot be inlined -#[inline(never)] -//~^ ERROR naked functions cannot be inlined -pub unsafe extern "C" fn inline_all() { - asm!("", options(noreturn)); -} - #[naked] pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 { compile_error!("this is a user specified error") diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 77bc80a101f..736de85765e 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -5,19 +5,19 @@ LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:204:5 + --> $DIR/naked-functions.rs:173:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:210:5 + --> $DIR/naked-functions.rs:179:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:217:10 + --> $DIR/naked-functions.rs:186:10 | LL | asm!(invalid_syntax) | ^^^^^^^^^^^^^^ @@ -249,42 +249,6 @@ warning: Rust ABI is unsupported in naked functions LL | pub unsafe fn rust_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:171:1 - | -LL | #[inline] - | ^^^^^^^^^ - -error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:178:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - -error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:185:1 - | -LL | #[inline(never)] - | ^^^^^^^^^^^^^^^^ - -error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:192:1 - | -LL | #[inline] - | ^^^^^^^^^ - -error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:194:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - -error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:196:1 - | -LL | #[inline(never)] - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 33 previous errors; 2 warnings emitted +error: aborting due to 27 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0787`. From 7e6c083873b7b98aa52d47896107af11560aeaf5 Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 16 Jul 2024 23:35:02 +0200 Subject: [PATCH 3/7] improve error message when `#[naked]` is used with `#[track-caller] and `#[target-feature]`` --- compiler/rustc_passes/messages.ftl | 2 +- compiler/rustc_passes/src/check_attr.rs | 26 ++++++++++--------- compiler/rustc_passes/src/errors.rs | 2 +- .../ui/asm/naked-functions-target-feature.rs | 13 ++++++++++ .../asm/naked-functions-target-feature.stderr | 12 +++++++++ .../rfc-2091-track-caller/error-with-naked.rs | 4 +-- .../error-with-naked.stderr | 14 +++++++--- 7 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 tests/ui/asm/naked-functions-target-feature.rs create mode 100644 tests/ui/asm/naked-functions-target-feature.stderr diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 2b6841181a7..8dec24feeba 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -485,7 +485,7 @@ passes_naked_functions_asm_options = passes_naked_functions_codegen_attribute = cannot use additional code generation attributes with `#[naked]` .label = this attribute is incompatible with `#[naked]` - .label2 = function marked with `#[naked]` here + .naked_attribute = function marked with `#[naked]` here passes_naked_functions_must_use_noreturn = asm in naked functions must use `noreturn` option diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 739847d73d3..311c11a0388 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -421,20 +421,22 @@ fn check_naked( const FORBIDDEN: [rustc_span::Symbol; 3] = [sym::track_caller, sym::inline, sym::target_feature]; - for other_attr in attrs { - if FORBIDDEN.into_iter().any(|name| other_attr.has_name(name)) { - self.dcx().emit_err(errors::NakedFunctionCodegenAttribute { - span: other_attr.span, - naked_span: attr.span, - }); - - return false; - } - } - match target { Target::Fn - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { + for other_attr in attrs { + if FORBIDDEN.into_iter().any(|name| other_attr.has_name(name)) { + self.dcx().emit_err(errors::NakedFunctionCodegenAttribute { + span: other_attr.span, + naked_span: attr.span, + }); + + return false; + } + } + + true + } // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[naked]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 03105795bfc..b6be096b43b 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1188,7 +1188,7 @@ pub struct NakedFunctionCodegenAttribute { #[primary_span] #[label] pub span: Span, - #[label(passes_label2)] + #[label(passes_naked_attribute)] pub naked_span: Span, } diff --git a/tests/ui/asm/naked-functions-target-feature.rs b/tests/ui/asm/naked-functions-target-feature.rs new file mode 100644 index 00000000000..264e7e0976b --- /dev/null +++ b/tests/ui/asm/naked-functions-target-feature.rs @@ -0,0 +1,13 @@ +//@ only-x86_64 +//@ needs-asm-support +#![feature(naked_functions)] +#![crate_type = "lib"] + +use std::arch::asm; + +#[target_feature(enable = "sse2")] +//~^ ERROR [E0736] +#[naked] +pub unsafe extern "C" fn naked_target_feature() { + asm!("", options(noreturn)); +} diff --git a/tests/ui/asm/naked-functions-target-feature.stderr b/tests/ui/asm/naked-functions-target-feature.stderr new file mode 100644 index 00000000000..1a8b59f61fe --- /dev/null +++ b/tests/ui/asm/naked-functions-target-feature.stderr @@ -0,0 +1,12 @@ +error[E0736]: cannot use additional code generation attributes with `#[naked]` + --> $DIR/naked-functions-target-feature.rs:8:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` +LL | +LL | #[naked] + | -------- function marked with `#[naked]` here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0736`. diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs index 6eaa7d4d9bc..0c73b9abf35 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs @@ -3,7 +3,7 @@ use std::arch::asm; -#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` +#[track_caller] //~ ERROR [E0736] //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn f() { @@ -15,7 +15,7 @@ extern "C" fn f() { struct S; impl S { - #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` + #[track_caller] //~ ERROR [E0736] //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn g() { diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr index 04c5c649d7f..7ab9f8b39eb 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr @@ -1,14 +1,20 @@ -error[E0736]: cannot use `#[track_caller]` with `#[naked]` +error[E0736]: cannot use additional code generation attributes with `#[naked]` --> $DIR/error-with-naked.rs:6:1 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` +LL | +LL | #[naked] + | -------- function marked with `#[naked]` here -error[E0736]: cannot use `#[track_caller]` with `#[naked]` +error[E0736]: cannot use additional code generation attributes with `#[naked]` --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` +LL | +LL | #[naked] + | -------- function marked with `#[naked]` here error[E0737]: `#[track_caller]` requires Rust ABI --> $DIR/error-with-naked.rs:6:1 From 4d082b77af1f714df6c407785e1961a9dddd554c Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 17 Jul 2024 00:03:33 +0200 Subject: [PATCH 4/7] add error message when `#[naked]` is used with `#[test]` --- compiler/rustc_builtin_macros/messages.ftl | 5 +++ compiler/rustc_builtin_macros/src/errors.rs | 10 +++++ compiler/rustc_builtin_macros/src/test.rs | 8 ++++ .../src/error_codes/E0798.md | 14 +++++++ compiler/rustc_error_codes/src/lib.rs | 1 + tests/ui/asm/naked-functions-testattrs.rs | 39 +++++++++++++++++++ tests/ui/asm/naked-functions-testattrs.stderr | 35 +++++++++++++++++ 7 files changed, 112 insertions(+) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0798.md create mode 100644 tests/ui/asm/naked-functions-testattrs.rs create mode 100644 tests/ui/asm/naked-functions-testattrs.stderr diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index b56bfa98357..21c0f0802f7 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -216,6 +216,11 @@ builtin_macros_multiple_defaults = multiple declared defaults .note = only one variant can be default .suggestion = make `{$ident}` default +builtin_macros_naked_functions_testing_attribute = + cannot use `#[naked]` with testing attributes + .label = function marked with testing attribute here + .naked_attribute = `#[naked]` is incompatible with testing attributes + builtin_macros_no_default_variant = no default declared .help = make a unit variant default by placing `#[default]` above it .suggestion = make `{$ident}` default diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 49d640436c2..24706a3b054 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -912,3 +912,13 @@ pub(crate) struct ExpectedItem<'a> { pub span: Span, pub token: &'a str, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_naked_functions_testing_attribute, code = E0798)] +pub struct NakedFunctionTestingAttribute { + #[primary_span] + #[label(builtin_macros_naked_attribute)] + pub naked_span: Span, + #[label] + pub testing_span: Span, +} diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index c0310a2f4b0..bb00c8de1b8 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -133,6 +133,14 @@ pub(crate) fn expand_test_or_bench( }; }; + if let Some(attr) = attr::find_by_name(&item.attrs, sym::naked) { + cx.dcx().emit_err(errors::NakedFunctionTestingAttribute { + testing_span: attr_sp, + naked_span: attr.span, + }); + return vec![Annotatable::Item(item)]; + } + // check_*_signature will report any errors in the type so compilation // will fail. We shouldn't try to expand in this case because the errors // would be spurious. diff --git a/compiler/rustc_error_codes/src/error_codes/E0798.md b/compiler/rustc_error_codes/src/error_codes/E0798.md new file mode 100644 index 00000000000..96f25eb4f0e --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0798.md @@ -0,0 +1,14 @@ +Testing attributes cannot be applied to functions marked with `#[naked]`. + +Erroneous code example: + +```ignore (requires test runner) +#[test] +#[should_panic] +#[naked] +fn foo() {} +``` + +See [the reference page for testing attributes] for more information. + +[the reference page for testing attributes]: https://doc.rust-lang.org/reference/attributes/testing.html diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index d13d5e1bca2..2a7bc2501c0 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -536,6 +536,7 @@ macro_rules! error_codes { E0795: 0795, E0796: 0796, E0797: 0797, +E0798: 0798, ); ) } diff --git a/tests/ui/asm/naked-functions-testattrs.rs b/tests/ui/asm/naked-functions-testattrs.rs new file mode 100644 index 00000000000..593cf3ad459 --- /dev/null +++ b/tests/ui/asm/naked-functions-testattrs.rs @@ -0,0 +1,39 @@ +//@ needs-asm-support +//@ compile-flags: --test + +#![allow(undefined_naked_function_abi)] +#![feature(naked_functions)] +#![feature(test)] +#![crate_type = "lib"] + +use std::arch::asm; + +#[test] +#[naked] +//~^ ERROR [E0798] +fn test_naked() { + unsafe { asm!("", options(noreturn)) }; +} + +#[should_panic] +#[test] +#[naked] +//~^ ERROR [E0798] +fn test_naked_should_panic() { + unsafe { asm!("", options(noreturn)) }; +} + +#[ignore] +#[test] +#[naked] +//~^ ERROR [E0798] +fn test_naked_ignore() { + unsafe { asm!("", options(noreturn)) }; +} + +#[bench] +#[naked] +//~^ ERROR [E0798] +fn bench_naked() { + unsafe { asm!("", options(noreturn)) }; +} diff --git a/tests/ui/asm/naked-functions-testattrs.stderr b/tests/ui/asm/naked-functions-testattrs.stderr new file mode 100644 index 00000000000..87647b0ca37 --- /dev/null +++ b/tests/ui/asm/naked-functions-testattrs.stderr @@ -0,0 +1,35 @@ +error[E0798]: cannot use `#[naked]` with testing attributes + --> $DIR/naked-functions-testattrs.rs:12:1 + | +LL | #[test] + | ------- function marked with testing attribute here +LL | #[naked] + | ^^^^^^^^ `#[naked]` is incompatible with testing attributes + +error[E0798]: cannot use `#[naked]` with testing attributes + --> $DIR/naked-functions-testattrs.rs:20:1 + | +LL | #[test] + | ------- function marked with testing attribute here +LL | #[naked] + | ^^^^^^^^ `#[naked]` is incompatible with testing attributes + +error[E0798]: cannot use `#[naked]` with testing attributes + --> $DIR/naked-functions-testattrs.rs:28:1 + | +LL | #[test] + | ------- function marked with testing attribute here +LL | #[naked] + | ^^^^^^^^ `#[naked]` is incompatible with testing attributes + +error[E0798]: cannot use `#[naked]` with testing attributes + --> $DIR/naked-functions-testattrs.rs:35:1 + | +LL | #[bench] + | -------- function marked with testing attribute here +LL | #[naked] + | ^^^^^^^^ `#[naked]` is incompatible with testing attributes + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0798`. From c6a166bac269eda77b595fdc8ff7290e1372c147 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 17 Jul 2024 10:42:24 +0200 Subject: [PATCH 5/7] switch to an allowlist approach - merge error codes - use attribute name that is incompatible in error message - add test for conditional incompatible attribute - add `linkage` to the allowlist --- compiler/rustc_builtin_macros/src/errors.rs | 2 +- .../src/error_codes/E0736.md | 15 ++-- .../src/error_codes/E0798.md | 14 ---- compiler/rustc_error_codes/src/lib.rs | 1 - compiler/rustc_passes/messages.ftl | 6 +- compiler/rustc_passes/src/check_attr.rs | 44 ++++++++++-- compiler/rustc_passes/src/errors.rs | 5 +- tests/ui/asm/naked-functions-inline.rs | 7 ++ tests/ui/asm/naked-functions-inline.stderr | 22 ++++-- .../ui/asm/naked-functions-instruction-set.rs | 30 ++++++++ .../asm/naked-functions-target-feature.stderr | 4 +- tests/ui/asm/naked-functions-testattrs.rs | 8 +-- tests/ui/asm/naked-functions-testattrs.stderr | 10 +-- tests/ui/asm/naked-functions.rs | 68 +++++++++++++++++-- tests/ui/asm/naked-functions.stderr | 6 +- .../error-with-naked.stderr | 8 +-- 16 files changed, 185 insertions(+), 65 deletions(-) delete mode 100644 compiler/rustc_error_codes/src/error_codes/E0798.md create mode 100644 tests/ui/asm/naked-functions-instruction-set.rs diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 24706a3b054..daf40df46c3 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -914,7 +914,7 @@ pub(crate) struct ExpectedItem<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_naked_functions_testing_attribute, code = E0798)] +#[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)] pub struct NakedFunctionTestingAttribute { #[primary_span] #[label(builtin_macros_naked_attribute)] diff --git a/compiler/rustc_error_codes/src/error_codes/E0736.md b/compiler/rustc_error_codes/src/error_codes/E0736.md index 08aa85e705d..4660d610744 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0736.md +++ b/compiler/rustc_error_codes/src/error_codes/E0736.md @@ -1,11 +1,12 @@ Functions marked with the `#[naked]` attribute are restricted in what other -code generation attributes they may be marked with. +attributes they may be marked with. -The following code generation attributes are incompatible with `#[naked]`: +Notable attributes that are incompatible with `#[naked]` are: - * `#[inline]` - * `#[track_caller]` - * `#[target_feature]` +* `#[inline]` +* `#[track_caller]` +* `#[target_feature]` +* `#[test]`, `#[ignore]`, `#[should_panic]` Erroneous code example: @@ -18,7 +19,3 @@ fn foo() {} These incompatibilities are due to the fact that naked functions deliberately impose strict restrictions regarding the code that the compiler is allowed to produce for this function. - -See [the reference page for codegen attributes] for more information. - -[the reference page for codegen attributes]: https://doc.rust-lang.org/reference/attributes/codegen.html diff --git a/compiler/rustc_error_codes/src/error_codes/E0798.md b/compiler/rustc_error_codes/src/error_codes/E0798.md deleted file mode 100644 index 96f25eb4f0e..00000000000 --- a/compiler/rustc_error_codes/src/error_codes/E0798.md +++ /dev/null @@ -1,14 +0,0 @@ -Testing attributes cannot be applied to functions marked with `#[naked]`. - -Erroneous code example: - -```ignore (requires test runner) -#[test] -#[should_panic] -#[naked] -fn foo() {} -``` - -See [the reference page for testing attributes] for more information. - -[the reference page for testing attributes]: https://doc.rust-lang.org/reference/attributes/testing.html diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 2a7bc2501c0..d13d5e1bca2 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -536,7 +536,6 @@ macro_rules! error_codes { E0795: 0795, E0796: 0796, E0797: 0797, -E0798: 0798, ); ) } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 8dec24feeba..bfe0d54e645 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -482,9 +482,9 @@ passes_naked_functions_asm_block = passes_naked_functions_asm_options = asm options unsupported in naked functions: {$unsupported_options} -passes_naked_functions_codegen_attribute = - cannot use additional code generation attributes with `#[naked]` - .label = this attribute is incompatible with `#[naked]` +passes_naked_functions_incompatible_attribute = + attribute incompatible with `#[naked]` + .label = the `{$attr}` attribute is incompatible with `#[naked]` .naked_attribute = function marked with `#[naked]` here passes_naked_functions_must_use_noreturn = diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 311c11a0388..ba0dbfbac12 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -418,17 +418,53 @@ fn check_naked( target: Target, attrs: &[Attribute], ) -> bool { - const FORBIDDEN: [rustc_span::Symbol; 3] = - [sym::track_caller, sym::inline, sym::target_feature]; + // many attributes don't make sense in combination with #[naked]. + // Notable attributes that are incompatible with `#[naked]` are: + // + // * `#[inline]` + // * `#[track_caller]` + // * `#[target_feature]` + // * `#[test]`, `#[ignore]`, `#[should_panic]` + // + // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate + const ALLOW_LIST: &[rustc_span::Symbol] = &[ + // conditional compilation + sym::cfg, + sym::cfg_attr, + // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`) + sym::test, + sym::ignore, + sym::should_panic, + sym::bench, + // diagnostics + sym::allow, + sym::warn, + sym::deny, + sym::forbid, + sym::deprecated, + sym::must_use, + // abi, linking and FFI + sym::export_name, + sym::link_section, + sym::linkage, + sym::no_mangle, + sym::naked, + sym::instruction_set, + // code generation + sym::cold, + // documentation + sym::doc, + ]; match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { for other_attr in attrs { - if FORBIDDEN.into_iter().any(|name| other_attr.has_name(name)) { - self.dcx().emit_err(errors::NakedFunctionCodegenAttribute { + if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) { + self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: other_attr.span, naked_span: attr.span, + attr: other_attr.name_or_empty(), }); return false; diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index b6be096b43b..b195ba973ce 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1183,13 +1183,14 @@ pub struct NakedFunctionsMustUseNoreturn { } #[derive(Diagnostic)] -#[diag(passes_naked_functions_codegen_attribute, code = E0736)] -pub struct NakedFunctionCodegenAttribute { +#[diag(passes_naked_functions_incompatible_attribute, code = E0736)] +pub struct NakedFunctionIncompatibleAttribute { #[primary_span] #[label] pub span: Span, #[label(passes_naked_attribute)] pub naked_span: Span, + pub attr: Symbol, } #[derive(Diagnostic)] diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs index 9a4f7547518..cfb38f2e738 100644 --- a/tests/ui/asm/naked-functions-inline.rs +++ b/tests/ui/asm/naked-functions-inline.rs @@ -29,3 +29,10 @@ pub unsafe extern "C" fn inline_never() { asm!("", options(noreturn)); } + +#[naked] +#[cfg_attr(all(), inline(never))] +//~^ ERROR [E0736] +pub unsafe extern "C" fn conditional_inline_never() { + asm!("", options(noreturn)); +} diff --git a/tests/ui/asm/naked-functions-inline.stderr b/tests/ui/asm/naked-functions-inline.stderr index 2496e942b17..84a688f6f53 100644 --- a/tests/ui/asm/naked-functions-inline.stderr +++ b/tests/ui/asm/naked-functions-inline.stderr @@ -1,27 +1,35 @@ -error[E0736]: cannot use additional code generation attributes with `#[naked]` +error[E0736]: attribute incompatible with `#[naked]` --> $DIR/naked-functions-inline.rs:13:1 | LL | #[naked] | -------- function marked with `#[naked]` here LL | #[inline] - | ^^^^^^^^^ this attribute is incompatible with `#[naked]` + | ^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]` -error[E0736]: cannot use additional code generation attributes with `#[naked]` +error[E0736]: attribute incompatible with `#[naked]` --> $DIR/naked-functions-inline.rs:20:1 | LL | #[naked] | -------- function marked with `#[naked]` here LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` + | ^^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]` -error[E0736]: cannot use additional code generation attributes with `#[naked]` +error[E0736]: attribute incompatible with `#[naked]` --> $DIR/naked-functions-inline.rs:27:1 | LL | #[naked] | -------- function marked with `#[naked]` here LL | #[inline(never)] - | ^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` + | ^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]` -error: aborting due to 3 previous errors +error[E0736]: attribute incompatible with `#[naked]` + --> $DIR/naked-functions-inline.rs:34:19 + | +LL | #[naked] + | -------- function marked with `#[naked]` here +LL | #[cfg_attr(all(), inline(never))] + | ^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0736`. diff --git a/tests/ui/asm/naked-functions-instruction-set.rs b/tests/ui/asm/naked-functions-instruction-set.rs new file mode 100644 index 00000000000..b81b65cff74 --- /dev/null +++ b/tests/ui/asm/naked-functions-instruction-set.rs @@ -0,0 +1,30 @@ +//@ compile-flags: --target armv5te-unknown-linux-gnueabi +//@ needs-llvm-components: arm +//@ needs-asm-support +//@ build-pass + +#![crate_type = "lib"] +#![feature(no_core, lang_items, rustc_attrs, naked_functions)] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +#[naked] +#[instruction_set(arm::t32)] +unsafe extern "C" fn test_thumb() { + asm!("bx lr", options(noreturn)); +} + +#[no_mangle] +#[naked] +#[instruction_set(arm::t32)] +unsafe extern "C" fn test_arm() { + asm!("bx lr", options(noreturn)); +} diff --git a/tests/ui/asm/naked-functions-target-feature.stderr b/tests/ui/asm/naked-functions-target-feature.stderr index 1a8b59f61fe..f215f99ab79 100644 --- a/tests/ui/asm/naked-functions-target-feature.stderr +++ b/tests/ui/asm/naked-functions-target-feature.stderr @@ -1,8 +1,8 @@ -error[E0736]: cannot use additional code generation attributes with `#[naked]` +error[E0736]: attribute incompatible with `#[naked]` --> $DIR/naked-functions-target-feature.rs:8:1 | LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `target_feature` attribute is incompatible with `#[naked]` LL | LL | #[naked] | -------- function marked with `#[naked]` here diff --git a/tests/ui/asm/naked-functions-testattrs.rs b/tests/ui/asm/naked-functions-testattrs.rs index 593cf3ad459..12943ac0378 100644 --- a/tests/ui/asm/naked-functions-testattrs.rs +++ b/tests/ui/asm/naked-functions-testattrs.rs @@ -10,7 +10,7 @@ #[test] #[naked] -//~^ ERROR [E0798] +//~^ ERROR [E0736] fn test_naked() { unsafe { asm!("", options(noreturn)) }; } @@ -18,7 +18,7 @@ fn test_naked() { #[should_panic] #[test] #[naked] -//~^ ERROR [E0798] +//~^ ERROR [E0736] fn test_naked_should_panic() { unsafe { asm!("", options(noreturn)) }; } @@ -26,14 +26,14 @@ fn test_naked_should_panic() { #[ignore] #[test] #[naked] -//~^ ERROR [E0798] +//~^ ERROR [E0736] fn test_naked_ignore() { unsafe { asm!("", options(noreturn)) }; } #[bench] #[naked] -//~^ ERROR [E0798] +//~^ ERROR [E0736] fn bench_naked() { unsafe { asm!("", options(noreturn)) }; } diff --git a/tests/ui/asm/naked-functions-testattrs.stderr b/tests/ui/asm/naked-functions-testattrs.stderr index 87647b0ca37..4dabe41964a 100644 --- a/tests/ui/asm/naked-functions-testattrs.stderr +++ b/tests/ui/asm/naked-functions-testattrs.stderr @@ -1,4 +1,4 @@ -error[E0798]: cannot use `#[naked]` with testing attributes +error[E0736]: cannot use `#[naked]` with testing attributes --> $DIR/naked-functions-testattrs.rs:12:1 | LL | #[test] @@ -6,7 +6,7 @@ LL | #[test] LL | #[naked] | ^^^^^^^^ `#[naked]` is incompatible with testing attributes -error[E0798]: cannot use `#[naked]` with testing attributes +error[E0736]: cannot use `#[naked]` with testing attributes --> $DIR/naked-functions-testattrs.rs:20:1 | LL | #[test] @@ -14,7 +14,7 @@ LL | #[test] LL | #[naked] | ^^^^^^^^ `#[naked]` is incompatible with testing attributes -error[E0798]: cannot use `#[naked]` with testing attributes +error[E0736]: cannot use `#[naked]` with testing attributes --> $DIR/naked-functions-testattrs.rs:28:1 | LL | #[test] @@ -22,7 +22,7 @@ LL | #[test] LL | #[naked] | ^^^^^^^^ `#[naked]` is incompatible with testing attributes -error[E0798]: cannot use `#[naked]` with testing attributes +error[E0736]: cannot use `#[naked]` with testing attributes --> $DIR/naked-functions-testattrs.rs:35:1 | LL | #[bench] @@ -32,4 +32,4 @@ LL | #[naked] error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0798`. +For more information about this error, try `rustc --explain E0736`. diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index e6633ddd4f3..23d5789ea8c 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -3,7 +3,7 @@ //@ ignore-spirv #![feature(naked_functions)] -#![feature(asm_const, asm_unwind)] +#![feature(asm_const, asm_unwind, linkage)] #![crate_type = "lib"] use std::arch::asm; @@ -162,11 +162,6 @@ pub extern "C" fn valid_b() { asm!("", options(noreturn, att_syntax)); } -#[naked] -pub unsafe extern "C" fn inline_none() { - asm!("", options(noreturn)); -} - #[naked] #[naked] pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 { @@ -186,3 +181,64 @@ pub extern "C" fn valid_b() { asm!(invalid_syntax) //~^ ERROR asm template must be a string literal } + +#[cfg(target_arch = "x86_64")] +#[cfg_attr(target_pointer_width = "64", no_mangle)] +#[naked] +pub unsafe extern "C" fn compatible_cfg_attributes() { + asm!("", options(noreturn, att_syntax)); +} + +#[allow(dead_code)] +#[warn(dead_code)] +#[deny(dead_code)] +#[forbid(dead_code)] +#[naked] +pub unsafe extern "C" fn compatible_diagnostic_attributes() { + asm!("", options(noreturn, att_syntax)); +} + +#[deprecated = "test"] +#[naked] +pub unsafe extern "C" fn compatible_deprecated_attributes() { + asm!("", options(noreturn, att_syntax)); +} + +#[cfg(target_arch = "x86_64")] +#[must_use] +#[naked] +pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 { + asm!( + " + mov rax, 42 + ret + ", + options(noreturn) + ) +} + +#[export_name = "exported_function_name"] +#[link_section = ".custom_section"] +#[no_mangle] +#[naked] +pub unsafe extern "C" fn compatible_ffi_attributes_1() { + asm!("", options(noreturn, att_syntax)); +} + +#[cold] +#[naked] +pub unsafe extern "C" fn compatible_codegen_attributes() { + asm!("", options(noreturn, att_syntax)); +} + +#[doc = "foo bar baz"] +#[naked] +pub unsafe extern "C" fn compatible_doc_attributes() { + asm!("", options(noreturn, att_syntax)); +} + +#[linkage = "external"] +#[naked] +pub unsafe extern "C" fn compatible_linkage() { + asm!("", options(noreturn, att_syntax)); +} diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 736de85765e..357c3654794 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -5,19 +5,19 @@ LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:173:5 + --> $DIR/naked-functions.rs:168:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:179:5 + --> $DIR/naked-functions.rs:174:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:186:10 + --> $DIR/naked-functions.rs:181:10 | LL | asm!(invalid_syntax) | ^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr index 7ab9f8b39eb..0625ed1183b 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr @@ -1,17 +1,17 @@ -error[E0736]: cannot use additional code generation attributes with `#[naked]` +error[E0736]: attribute incompatible with `#[naked]` --> $DIR/error-with-naked.rs:6:1 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` + | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[naked]` LL | LL | #[naked] | -------- function marked with `#[naked]` here -error[E0736]: cannot use additional code generation attributes with `#[naked]` +error[E0736]: attribute incompatible with `#[naked]` --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` + | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[naked]` LL | LL | #[naked] | -------- function marked with `#[naked]` here From a3bb0104ff929674e9d315d9ebec8324f88f367f Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 23 Jul 2024 16:02:32 +0200 Subject: [PATCH 6/7] allow `#[target_feature]` on `#[naked]` functions --- compiler/rustc_error_codes/src/error_codes/E0736.md | 1 - compiler/rustc_passes/src/check_attr.rs | 2 +- tests/ui/asm/naked-functions-target-feature.rs | 13 ------------- tests/ui/asm/naked-functions-target-feature.stderr | 12 ------------ tests/ui/asm/naked-functions.rs | 6 ++++++ 5 files changed, 7 insertions(+), 27 deletions(-) delete mode 100644 tests/ui/asm/naked-functions-target-feature.rs delete mode 100644 tests/ui/asm/naked-functions-target-feature.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0736.md b/compiler/rustc_error_codes/src/error_codes/E0736.md index 4660d610744..cb7633b7068 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0736.md +++ b/compiler/rustc_error_codes/src/error_codes/E0736.md @@ -5,7 +5,6 @@ Notable attributes that are incompatible with `#[naked]` are: * `#[inline]` * `#[track_caller]` -* `#[target_feature]` * `#[test]`, `#[ignore]`, `#[should_panic]` Erroneous code example: diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ba0dbfbac12..879cae7a94c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -423,7 +423,6 @@ fn check_naked( // // * `#[inline]` // * `#[track_caller]` - // * `#[target_feature]` // * `#[test]`, `#[ignore]`, `#[should_panic]` // // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate @@ -452,6 +451,7 @@ fn check_naked( sym::instruction_set, // code generation sym::cold, + sym::target_feature, // documentation sym::doc, ]; diff --git a/tests/ui/asm/naked-functions-target-feature.rs b/tests/ui/asm/naked-functions-target-feature.rs deleted file mode 100644 index 264e7e0976b..00000000000 --- a/tests/ui/asm/naked-functions-target-feature.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ only-x86_64 -//@ needs-asm-support -#![feature(naked_functions)] -#![crate_type = "lib"] - -use std::arch::asm; - -#[target_feature(enable = "sse2")] -//~^ ERROR [E0736] -#[naked] -pub unsafe extern "C" fn naked_target_feature() { - asm!("", options(noreturn)); -} diff --git a/tests/ui/asm/naked-functions-target-feature.stderr b/tests/ui/asm/naked-functions-target-feature.stderr deleted file mode 100644 index f215f99ab79..00000000000 --- a/tests/ui/asm/naked-functions-target-feature.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0736]: attribute incompatible with `#[naked]` - --> $DIR/naked-functions-target-feature.rs:8:1 - | -LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `target_feature` attribute is incompatible with `#[naked]` -LL | -LL | #[naked] - | -------- function marked with `#[naked]` here - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0736`. diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 23d5789ea8c..33cdbd1adb6 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -231,6 +231,12 @@ pub extern "C" fn valid_b() { asm!("", options(noreturn, att_syntax)); } +#[target_feature(enable = "sse2")] +#[naked] +pub unsafe extern "C" fn compatible_target_feature() { + asm!("", options(noreturn)); +} + #[doc = "foo bar baz"] #[naked] pub unsafe extern "C" fn compatible_doc_attributes() { From c7e688eccd60ab05a00dea56ac9d984397a2d02e Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 27 Jul 2024 19:18:11 +0200 Subject: [PATCH 7/7] fix `tests/ui/asm/naked-functions.rs` for aarch64 --- tests/ui/asm/naked-functions.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 33cdbd1adb6..b1f6e5d4fa9 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -195,13 +195,13 @@ pub extern "C" fn valid_b() { #[forbid(dead_code)] #[naked] pub unsafe extern "C" fn compatible_diagnostic_attributes() { - asm!("", options(noreturn, att_syntax)); + asm!("", options(noreturn, raw)); } #[deprecated = "test"] #[naked] pub unsafe extern "C" fn compatible_deprecated_attributes() { - asm!("", options(noreturn, att_syntax)); + asm!("", options(noreturn, raw)); } #[cfg(target_arch = "x86_64")] @@ -222,15 +222,16 @@ pub extern "C" fn valid_b() { #[no_mangle] #[naked] pub unsafe extern "C" fn compatible_ffi_attributes_1() { - asm!("", options(noreturn, att_syntax)); + asm!("", options(noreturn, raw)); } #[cold] #[naked] pub unsafe extern "C" fn compatible_codegen_attributes() { - asm!("", options(noreturn, att_syntax)); + asm!("", options(noreturn, raw)); } +#[cfg(target_arch = "x86_64")] #[target_feature(enable = "sse2")] #[naked] pub unsafe extern "C" fn compatible_target_feature() { @@ -240,11 +241,11 @@ pub extern "C" fn valid_b() { #[doc = "foo bar baz"] #[naked] pub unsafe extern "C" fn compatible_doc_attributes() { - asm!("", options(noreturn, att_syntax)); + asm!("", options(noreturn, raw)); } #[linkage = "external"] #[naked] pub unsafe extern "C" fn compatible_linkage() { - asm!("", options(noreturn, att_syntax)); + asm!("", options(noreturn, raw)); }