about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFolkert <folkert@folkertdev.nl>2024-07-17 10:42:24 +0200
committerFolkert <folkert@folkertdev.nl>2024-07-27 12:55:39 +0200
commitc6a166bac269eda77b595fdc8ff7290e1372c147 (patch)
tree46b7764813f597d7df6c2de3e89bb8a319b3ed24
parent4d082b77af1f714df6c407785e1961a9dddd554c (diff)
downloadrust-c6a166bac269eda77b595fdc8ff7290e1372c147.tar.gz
rust-c6a166bac269eda77b595fdc8ff7290e1372c147.zip
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
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0736.md15
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0798.md14
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_passes/messages.ftl6
-rw-r--r--compiler/rustc_passes/src/check_attr.rs44
-rw-r--r--compiler/rustc_passes/src/errors.rs5
-rw-r--r--tests/ui/asm/naked-functions-inline.rs7
-rw-r--r--tests/ui/asm/naked-functions-inline.stderr22
-rw-r--r--tests/ui/asm/naked-functions-instruction-set.rs30
-rw-r--r--tests/ui/asm/naked-functions-target-feature.stderr4
-rw-r--r--tests/ui/asm/naked-functions-testattrs.rs8
-rw-r--r--tests/ui/asm/naked-functions-testattrs.stderr10
-rw-r--r--tests/ui/asm/naked-functions.rs68
-rw-r--r--tests/ui/asm/naked-functions.stderr6
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr8
16 files changed, 185 insertions, 65 deletions
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 @@ E0794: 0794,
 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 @@ 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;
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_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));
+}
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 @@ 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)) };
 }
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;
@@ -163,11 +163,6 @@ pub unsafe extern "C" fn valid_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 {
     compile_error!("this is a user specified error")
@@ -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));
+}
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