Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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
  • Loading branch information
folkertdev committed Jul 27, 2024
commit c6a166bac269eda77b595fdc8ff7290e1372c147
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
15 changes: 6 additions & 9 deletions compiler/rustc_error_codes/src/error_codes/E0736.md
Original file line number Diff line number Diff line change
@@ -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:

Expand All @@ -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
14 changes: 0 additions & 14 deletions compiler/rustc_error_codes/src/error_codes/E0798.md

This file was deleted.

1 change: 0 additions & 1 deletion compiler/rustc_error_codes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,6 @@ E0794: 0794,
E0795: 0795,
E0796: 0796,
E0797: 0797,
E0798: 0798,
);
)
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
44 changes: 40 additions & 4 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[target_feature] affects the set of instructions allowed inside inline assembly as well as the exact encoding of certain instructions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I'm going off of #90957 (comment) where @joshtriplett suggests to exclude #[target_feature] initially.

that was 2 years ago though so maybe that should be re-evaluated. Do you have concerns with allowing #[target_feature] now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what a reason for forbidding it would be, and why @joshtriplett thought it would be hard to get right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well a reason to be cautious is that I think to most (me included) it's not 100% clear what #[target_feature] could do. Are we absolutely sure that on no platform, present or future, a target feature would insert additional instructions that violate the assumptions of #[naked]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I said at the time was that it might take some care to get right. If we take that care, and commit to avoiding any potential issues that might arise (e.g. locking down what a given target_feature means for a naked function and never inserting any instructions for it), then supporting the combination seems fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the implementation strategy in #128004 I don't think there is any risk of #[target_feature] inserting instructions. The user's inline assembly block is hoisted to a top-level global asm block, and the function itself becomes effectively an extern fn.

So I've now added target_feature to the allow list in a separate commit that can be reverted if there are any concerns.

// * `#[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;
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/asm/naked-functions-inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
22 changes: 15 additions & 7 deletions tests/ui/asm/naked-functions-inline.stderr
Original file line number Diff line number Diff line change
@@ -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`.
30 changes: 30 additions & 0 deletions tests/ui/asm/naked-functions-instruction-set.rs
Original file line number Diff line number Diff line change
@@ -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));
}
4 changes: 2 additions & 2 deletions tests/ui/asm/naked-functions-target-feature.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/asm/naked-functions-testattrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ use std::arch::asm;

#[test]
#[naked]
//~^ ERROR [E0798]
//~^ ERROR [E0736]
fn test_naked() {
unsafe { asm!("", options(noreturn)) };
}

#[should_panic]
#[test]
#[naked]
//~^ ERROR [E0798]
//~^ ERROR [E0736]
fn test_naked_should_panic() {
unsafe { asm!("", options(noreturn)) };
}

#[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)) };
}
10 changes: 5 additions & 5 deletions tests/ui/asm/naked-functions-testattrs.stderr
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
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]
| ------- function marked with testing attribute here
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]
| ------- function marked with testing attribute here
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]
| ------- function marked with testing attribute here
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]
Expand All @@ -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`.
Loading