Prevent using #[target_feature] on lang item functions

This commit is contained in:
Eduardo Sánchez Muñoz 2023-09-18 20:11:01 +02:00
parent cdd182cbb2
commit 9102816bc4
7 changed files with 99 additions and 3 deletions

View File

@ -404,6 +404,10 @@ passes_invalid_stability =
.label = invalid stability version .label = invalid stability version
.item = the stability attribute annotates this item .item = the stability attribute annotates this item
passes_lang_item_fn_with_target_feature =
`{$name}` language item function is not allowed to have `#[target_feature]`
.label = `{$name}` language item function is not allowed to have `#[target_feature]`
passes_lang_item_on_incorrect_target = passes_lang_item_on_incorrect_target =
`{$name}` language item must be applied to a {$expected_target} `{$name}` language item must be applied to a {$expected_target}
.label = attribute should be applied to a {$expected_target}, not a {$actual_target} .label = attribute should be applied to a {$expected_target}, not a {$actual_target}

View File

@ -110,7 +110,7 @@ fn check_attributes(
sym::coverage => self.check_coverage(hir_id, attr, span, target), sym::coverage => self.check_coverage(hir_id, attr, span, target),
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
sym::marker => self.check_marker(hir_id, attr, span, target), sym::marker => self.check_marker(hir_id, attr, span, target),
sym::target_feature => self.check_target_feature(hir_id, attr, span, target), sym::target_feature => self.check_target_feature(hir_id, attr, span, target, attrs),
sym::thread_local => self.check_thread_local(attr, span, target), sym::thread_local => self.check_thread_local(attr, span, target),
sym::track_caller => { sym::track_caller => {
self.check_track_caller(hir_id, attr.span, attrs, span, target) self.check_track_caller(hir_id, attr.span, attrs, span, target)
@ -571,10 +571,36 @@ fn check_target_feature(
attr: &Attribute, attr: &Attribute,
span: Span, span: Span,
target: Target, target: Target,
attrs: &[Attribute],
) -> bool { ) -> bool {
match target { match target {
Target::Fn Target::Fn => {
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, // `#[target_feature]` is not allowed in language items.
if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
// Calling functions with `#[target_feature]` is
// not unsafe on WASM, see #84988
&& !self.tcx.sess.target.is_like_wasm
&& !self.tcx.sess.opts.actually_rustdoc
{
let hir::Node::Item(item) = self.tcx.hir().get(hir_id) else {
unreachable!();
};
let hir::ItemKind::Fn(sig, _, _) = item.kind else {
// target is `Fn`
unreachable!();
};
self.tcx.sess.emit_err(errors::LangItemWithTargetFeature {
attr_span: attr.span,
name: lang_item,
sig_span: sig.span,
});
false
} else {
true
}
}
Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
// FIXME: #[target_feature] was previously erroneously allowed on statements and some // FIXME: #[target_feature] was previously erroneously allowed on statements and some
// crates used this, so only emit a warning. // crates used this, so only emit a warning.
Target::Statement => { Target::Statement => {

View File

@ -808,6 +808,16 @@ pub struct MissingLangItem {
pub name: Symbol, pub name: Symbol,
} }
#[derive(Diagnostic)]
#[diag(passes_lang_item_fn_with_target_feature)]
pub struct LangItemWithTargetFeature {
#[primary_span]
pub attr_span: Span,
pub name: Symbol,
#[label]
pub sig_span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(passes_lang_item_on_incorrect_target, code = "E0718")] #[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
pub struct LangItemOnIncorrectTarget { pub struct LangItemOnIncorrectTarget {

View File

@ -0,0 +1,19 @@
// only-x86_64
// check-fail
#![feature(lang_items, no_core, target_feature_11)]
#![no_core]
#[lang = "copy"]
pub trait Copy {}
#[lang = "sized"]
pub trait Sized {}
#[lang = "start"]
#[target_feature(enable = "avx2")]
//~^ ERROR `start` language item function is not allowed to have `#[target_feature]`
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
0
}
fn main() {}

View File

@ -0,0 +1,11 @@
error: `start` language item function is not allowed to have `#[target_feature]`
--> $DIR/start_lang_item_with_target_feature.rs:13:1
|
LL | #[target_feature(enable = "avx2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
| ------------------------------------------------------------------------------------------- `start` language item function is not allowed to have `#[target_feature]`
error: aborting due to previous error

View File

@ -0,0 +1,15 @@
// compile-flags:-C panic=abort
// only-x86_64
#![feature(target_feature_11)]
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[panic_handler]
#[target_feature(enable = "avx2")]
//~^ ERROR `panic_impl` language item function is not allowed to have `#[target_feature]`
fn panic(info: &PanicInfo) -> ! {
unimplemented!();
}

View File

@ -0,0 +1,11 @@
error: `panic_impl` language item function is not allowed to have `#[target_feature]`
--> $DIR/panic-handler-with-target-feature.rs:11:1
|
LL | #[target_feature(enable = "avx2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | fn panic(info: &PanicInfo) -> ! {
| ------------------------------- `panic_impl` language item function is not allowed to have `#[target_feature]`
error: aborting due to previous error