From 9102816bc4deca950b66cce402ea45573acc8fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Mon, 18 Sep 2023 20:11:01 +0200 Subject: [PATCH] Prevent using `#[target_feature]` on lang item functions --- compiler/rustc_passes/messages.ftl | 4 +++ compiler/rustc_passes/src/check_attr.rs | 32 +++++++++++++++++-- compiler/rustc_passes/src/errors.rs | 10 ++++++ .../start_lang_item_with_target_feature.rs | 19 +++++++++++ ...start_lang_item_with_target_feature.stderr | 11 +++++++ .../panic-handler-with-target-feature.rs | 15 +++++++++ .../panic-handler-with-target-feature.stderr | 11 +++++++ 7 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 tests/ui/lang-items/start_lang_item_with_target_feature.rs create mode 100644 tests/ui/lang-items/start_lang_item_with_target_feature.stderr create mode 100644 tests/ui/panic-handler/panic-handler-with-target-feature.rs create mode 100644 tests/ui/panic-handler/panic-handler-with-target-feature.stderr diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 56f4b387df893..4354e40183e92 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -404,6 +404,10 @@ passes_invalid_stability = .label = invalid stability version .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 = `{$name}` language item must be applied to a {$expected_target} .label = attribute should be applied to a {$expected_target}, not a {$actual_target} diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d10bc33db52e0..e0b0916d43285 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -110,7 +110,7 @@ impl CheckAttrVisitor<'_> { sym::coverage => self.check_coverage(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::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::track_caller => { self.check_track_caller(hir_id, attr.span, attrs, span, target) @@ -571,10 +571,36 @@ impl CheckAttrVisitor<'_> { attr: &Attribute, span: Span, target: Target, + attrs: &[Attribute], ) -> bool { match target { - Target::Fn - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + Target::Fn => { + // `#[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 // crates used this, so only emit a warning. Target::Statement => { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8b65e301b7450..2ec6a0b924140 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -808,6 +808,16 @@ pub struct MissingLangItem { 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)] #[diag(passes_lang_item_on_incorrect_target, code = "E0718")] pub struct LangItemOnIncorrectTarget { diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.rs b/tests/ui/lang-items/start_lang_item_with_target_feature.rs new file mode 100644 index 0000000000000..3052b7bb56373 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_with_target_feature.rs @@ -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(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + 0 +} + +fn main() {} diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.stderr b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr new file mode 100644 index 0000000000000..ff55a1365e458 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr @@ -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(_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 + diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.rs b/tests/ui/panic-handler/panic-handler-with-target-feature.rs new file mode 100644 index 0000000000000..8ea0275d7e99a --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-with-target-feature.rs @@ -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!(); +} diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.stderr b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr new file mode 100644 index 0000000000000..4210a4200aee8 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr @@ -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 +