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
This commit is contained in:
Folkert 2024-07-17 10:42:24 +02:00
parent 4d082b77af
commit c6a166bac2
No known key found for this signature in database
GPG Key ID: 1F17F6FFD112B97C
16 changed files with 185 additions and 65 deletions

View File

@ -914,7 +914,7 @@ pub(crate) struct ExpectedItem<'a> {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros_naked_functions_testing_attribute, code = E0798)] #[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)]
pub struct NakedFunctionTestingAttribute { pub struct NakedFunctionTestingAttribute {
#[primary_span] #[primary_span]
#[label(builtin_macros_naked_attribute)] #[label(builtin_macros_naked_attribute)]

View File

@ -1,11 +1,12 @@
Functions marked with the `#[naked]` attribute are restricted in what other 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]` * `#[inline]`
* `#[track_caller]` * `#[track_caller]`
* `#[target_feature]` * `#[target_feature]`
* `#[test]`, `#[ignore]`, `#[should_panic]`
Erroneous code example: Erroneous code example:
@ -18,7 +19,3 @@ fn foo() {}
These incompatibilities are due to the fact that naked functions deliberately These incompatibilities are due to the fact that naked functions deliberately
impose strict restrictions regarding the code that the compiler is impose strict restrictions regarding the code that the compiler is
allowed to produce for this function. 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

View File

@ -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

View File

@ -536,7 +536,6 @@ E0794: 0794,
E0795: 0795, E0795: 0795,
E0796: 0796, E0796: 0796,
E0797: 0797, E0797: 0797,
E0798: 0798,
); );
) )
} }

View File

@ -482,9 +482,9 @@ passes_naked_functions_asm_block =
passes_naked_functions_asm_options = passes_naked_functions_asm_options =
asm options unsupported in naked functions: {$unsupported_options} asm options unsupported in naked functions: {$unsupported_options}
passes_naked_functions_codegen_attribute = passes_naked_functions_incompatible_attribute =
cannot use additional code generation attributes with `#[naked]` attribute incompatible with `#[naked]`
.label = this attribute is incompatible with `#[naked]` .label = the `{$attr}` attribute is incompatible with `#[naked]`
.naked_attribute = function marked with `#[naked]` here .naked_attribute = function marked with `#[naked]` here
passes_naked_functions_must_use_noreturn = passes_naked_functions_must_use_noreturn =

View File

@ -418,17 +418,53 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
target: Target, target: Target,
attrs: &[Attribute], attrs: &[Attribute],
) -> bool { ) -> bool {
const FORBIDDEN: [rustc_span::Symbol; 3] = // many attributes don't make sense in combination with #[naked].
[sym::track_caller, sym::inline, sym::target_feature]; // 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 { match target {
Target::Fn Target::Fn
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
for other_attr in attrs { for other_attr in attrs {
if FORBIDDEN.into_iter().any(|name| other_attr.has_name(name)) { if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) {
self.dcx().emit_err(errors::NakedFunctionCodegenAttribute { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
span: other_attr.span, span: other_attr.span,
naked_span: attr.span, naked_span: attr.span,
attr: other_attr.name_or_empty(),
}); });
return false; return false;

View File

@ -1183,13 +1183,14 @@ pub struct NakedFunctionsMustUseNoreturn {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(passes_naked_functions_codegen_attribute, code = E0736)] #[diag(passes_naked_functions_incompatible_attribute, code = E0736)]
pub struct NakedFunctionCodegenAttribute { pub struct NakedFunctionIncompatibleAttribute {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,
#[label(passes_naked_attribute)] #[label(passes_naked_attribute)]
pub naked_span: Span, pub naked_span: Span,
pub attr: Symbol,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]

View File

@ -29,3 +29,10 @@ pub unsafe extern "C" fn inline_always() {
pub unsafe extern "C" fn inline_never() { pub unsafe extern "C" fn inline_never() {
asm!("", options(noreturn)); asm!("", options(noreturn));
} }
#[naked]
#[cfg_attr(all(), inline(never))]
//~^ ERROR [E0736]
pub unsafe extern "C" fn conditional_inline_never() {
asm!("", options(noreturn));
}

View File

@ -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 --> $DIR/naked-functions-inline.rs:13:1
| |
LL | #[naked] LL | #[naked]
| -------- function marked with `#[naked]` here | -------- function marked with `#[naked]` here
LL | #[inline] 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 --> $DIR/naked-functions-inline.rs:20:1
| |
LL | #[naked] LL | #[naked]
| -------- function marked with `#[naked]` here | -------- function marked with `#[naked]` here
LL | #[inline(always)] 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 --> $DIR/naked-functions-inline.rs:27:1
| |
LL | #[naked] LL | #[naked]
| -------- function marked with `#[naked]` here | -------- function marked with `#[naked]` here
LL | #[inline(never)] 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`. For more information about this error, try `rustc --explain E0736`.

View File

@ -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));
}

View File

@ -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 --> $DIR/naked-functions-target-feature.rs:8:1
| |
LL | #[target_feature(enable = "sse2")] LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `target_feature` attribute is incompatible with `#[naked]`
LL | LL |
LL | #[naked] LL | #[naked]
| -------- function marked with `#[naked]` here | -------- function marked with `#[naked]` here

View File

@ -10,7 +10,7 @@ use std::arch::asm;
#[test] #[test]
#[naked] #[naked]
//~^ ERROR [E0798] //~^ ERROR [E0736]
fn test_naked() { fn test_naked() {
unsafe { asm!("", options(noreturn)) }; unsafe { asm!("", options(noreturn)) };
} }
@ -18,7 +18,7 @@ fn test_naked() {
#[should_panic] #[should_panic]
#[test] #[test]
#[naked] #[naked]
//~^ ERROR [E0798] //~^ ERROR [E0736]
fn test_naked_should_panic() { fn test_naked_should_panic() {
unsafe { asm!("", options(noreturn)) }; unsafe { asm!("", options(noreturn)) };
} }
@ -26,14 +26,14 @@ fn test_naked_should_panic() {
#[ignore] #[ignore]
#[test] #[test]
#[naked] #[naked]
//~^ ERROR [E0798] //~^ ERROR [E0736]
fn test_naked_ignore() { fn test_naked_ignore() {
unsafe { asm!("", options(noreturn)) }; unsafe { asm!("", options(noreturn)) };
} }
#[bench] #[bench]
#[naked] #[naked]
//~^ ERROR [E0798] //~^ ERROR [E0736]
fn bench_naked() { fn bench_naked() {
unsafe { asm!("", options(noreturn)) }; unsafe { asm!("", options(noreturn)) };
} }

View File

@ -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 --> $DIR/naked-functions-testattrs.rs:12:1
| |
LL | #[test] LL | #[test]
@ -6,7 +6,7 @@ LL | #[test]
LL | #[naked] LL | #[naked]
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes | ^^^^^^^^ `#[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 --> $DIR/naked-functions-testattrs.rs:20:1
| |
LL | #[test] LL | #[test]
@ -14,7 +14,7 @@ LL | #[test]
LL | #[naked] LL | #[naked]
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes | ^^^^^^^^ `#[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 --> $DIR/naked-functions-testattrs.rs:28:1
| |
LL | #[test] LL | #[test]
@ -22,7 +22,7 @@ LL | #[test]
LL | #[naked] LL | #[naked]
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes | ^^^^^^^^ `#[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 --> $DIR/naked-functions-testattrs.rs:35:1
| |
LL | #[bench] LL | #[bench]
@ -32,4 +32,4 @@ LL | #[naked]
error: aborting due to 4 previous errors 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`.

View File

@ -3,7 +3,7 @@
//@ ignore-spirv //@ ignore-spirv
#![feature(naked_functions)] #![feature(naked_functions)]
#![feature(asm_const, asm_unwind)] #![feature(asm_const, asm_unwind, linkage)]
#![crate_type = "lib"] #![crate_type = "lib"]
use std::arch::asm; use std::arch::asm;
@ -162,11 +162,6 @@ pub unsafe extern "C" fn valid_att_syntax() {
asm!("", options(noreturn, att_syntax)); asm!("", options(noreturn, att_syntax));
} }
#[naked]
pub unsafe extern "C" fn inline_none() {
asm!("", options(noreturn));
}
#[naked] #[naked]
#[naked] #[naked]
pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 { pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
@ -186,3 +181,64 @@ pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 {
asm!(invalid_syntax) asm!(invalid_syntax)
//~^ ERROR asm template must be a string literal //~^ 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));
}

View File

@ -5,19 +5,19 @@ LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
error: this is a user specified error 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") LL | compile_error!("this is a user specified error")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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"); LL | compile_error!("this is a user specified error");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: asm template must be a string literal error: asm template must be a string literal
--> $DIR/naked-functions.rs:186:10 --> $DIR/naked-functions.rs:181:10
| |
LL | asm!(invalid_syntax) LL | asm!(invalid_syntax)
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^

View File

@ -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 --> $DIR/error-with-naked.rs:6:1
| |
LL | #[track_caller] LL | #[track_caller]
| ^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[naked]`
LL | LL |
LL | #[naked] LL | #[naked]
| -------- function marked with `#[naked]` here | -------- 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 --> $DIR/error-with-naked.rs:18:5
| |
LL | #[track_caller] LL | #[track_caller]
| ^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]` | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[naked]`
LL | LL |
LL | #[naked] LL | #[naked]
| -------- function marked with `#[naked]` here | -------- function marked with `#[naked]` here