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)]
#[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)]

View File

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

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,
E0796: 0796,
E0797: 0797,
E0798: 0798,
);
)
}

View File

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

View File

@ -418,17 +418,53 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
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;

View File

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

View File

@ -29,3 +29,10 @@ pub unsafe extern "C" fn inline_always() {
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));
}

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
|
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`.

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

View File

@ -10,7 +10,7 @@ use std::arch::asm;
#[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)) };
}

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
|
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`.

View File

@ -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 unsafe extern "C" fn valid_att_syntax() {
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 unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 {
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));
}

View File

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

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