Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent using #[target_feature] on lang item functions #115910

Merged
merged 1 commit into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
32 changes: 29 additions & 3 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 => {
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/lang-items/start_lang_item_with_target_feature.rs
Original file line number Diff line number Diff line change
@@ -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() {}
11 changes: 11 additions & 0 deletions tests/ui/lang-items/start_lang_item_with_target_feature.stderr
Original file line number Diff line number Diff line change
@@ -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

15 changes: 15 additions & 0 deletions tests/ui/panic-handler/panic-handler-with-target-feature.rs
Original file line number Diff line number Diff line change
@@ -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!();
}
11 changes: 11 additions & 0 deletions tests/ui/panic-handler/panic-handler-with-target-feature.stderr
Original file line number Diff line number Diff line change
@@ -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

Loading