Skip to content

Commit

Permalink
Auto merge of #115910 - eduardosm:lang-fns-target-features, r=cjgillot
Browse files Browse the repository at this point in the history
Prevent using `#[target_feature]` on lang item functions

Fixes #109411 and also prevents from using `#[target_feature]` on other `fn` lang items to mitigate the concerns from #109411 (comment).
  • Loading branch information
bors committed Sep 22, 2023
2 parents b757318 + 9102816 commit aace2df
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 3 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,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 @@ -118,7 +118,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 @@ -591,10 +591,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

0 comments on commit aace2df

Please sign in to comment.