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

Gracefully handle #[target_feature] on statics #109088

Merged
merged 1 commit into from
Mar 14, 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
45 changes: 25 additions & 20 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {

let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);

// In some cases, attribute are only valid on functions, but it's the `check_attr`
// pass that check that they aren't used anywhere else, rather this module.
// In these cases, we bail from performing further checks that are only meaningful for
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
// report a delayed bug, just in case `check_attr` isn't doing its job.
let validate_fn_only_attr = |attr_sp| -> bool {
let def_kind = tcx.def_kind(did);
if let DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) = def_kind {
true
} else {
tcx.sess.delay_span_bug(attr_sp, "this attribute can only be applied to functions");
false
}
};

let mut inline_span = None;
let mut link_ordinal_span = None;
let mut no_sanitize_span = None;

for attr in attrs.iter() {
// In some cases, attribute are only valid on functions, but it's the `check_attr`
// pass that check that they aren't used anywhere else, rather this module.
// In these cases, we bail from performing further checks that are only meaningful for
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
// report a delayed bug, just in case `check_attr` isn't doing its job.
let fn_sig = || {
use DefKind::*;

let def_kind = tcx.def_kind(did);
if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
Some(tcx.fn_sig(did))
} else {
tcx.sess
.delay_span_bug(attr.span, "this attribute can only be applied to functions");
None
}
};

if attr.has_name(sym::cold) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
} else if attr.has_name(sym::rustc_allocator) {
Expand Down Expand Up @@ -169,8 +173,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
}
}
} else if attr.has_name(sym::cmse_nonsecure_entry) {
if validate_fn_only_attr(attr.span)
&& !matches!(tcx.fn_sig(did).skip_binder().abi(), abi::Abi::C { .. })
if let Some(fn_sig) = fn_sig()
&& !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
{
struct_span_err!(
tcx.sess,
Expand All @@ -189,8 +193,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
} else if attr.has_name(sym::track_caller) {
if !tcx.is_closure(did.to_def_id())
&& validate_fn_only_attr(attr.span)
&& tcx.fn_sig(did).skip_binder().abi() != abi::Abi::Rust
&& let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().abi() != abi::Abi::Rust
{
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
.emit();
Expand Down Expand Up @@ -222,7 +226,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
}
} else if attr.has_name(sym::target_feature) {
if !tcx.is_closure(did.to_def_id())
&& tcx.fn_sig(did).skip_binder().unsafety() == hir::Unsafety::Normal
&& let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
{
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
// The `#[target_feature]` attribute is allowed on
Expand Down
35 changes: 35 additions & 0 deletions tests/ui/target-feature/invalid-attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@

#![warn(unused_attributes)]

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
extern crate alloc;
//~^ NOTE not a function

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
use alloc::alloc::alloc;
//~^ NOTE not a function

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
extern "Rust" {}
//~^ NOTE not a function

#[target_feature = "+sse2"]
//~^ ERROR malformed `target_feature` attribute
#[target_feature(enable = "foo")]
Expand Down Expand Up @@ -59,6 +74,11 @@ union Qux {
f2: u16,
}

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
type Uwu = ();
//~^ NOTE not a function

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
trait Baz {}
Expand All @@ -69,6 +89,21 @@ trait Baz {}
#[target_feature(enable = "sse2")]
unsafe fn test() {}

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
static A: () = ();
//~^ NOTE not a function

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
impl Quux for u8 {}
//~^ NOTE not a function

#[target_feature(enable = "sse2")]
//~^ ERROR attribute should be applied to a function
impl Foo {}
//~^ NOTE not a function

trait Quux {
fn foo();
}
Expand Down
95 changes: 79 additions & 16 deletions tests/ui/target-feature/invalid-attribute.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:17:1
--> $DIR/invalid-attribute.rs:32:1
|
LL | #[target_feature = "+sse2"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]`

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:34:1
--> $DIR/invalid-attribute.rs:17:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | extern crate alloc;
| ------------------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:22:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | use alloc::alloc::alloc;
| ------------------------ not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:27:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | extern "Rust" {}
| ---------------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:49:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -14,7 +41,7 @@ LL | mod another {}
| -------------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:39:1
--> $DIR/invalid-attribute.rs:54:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -23,7 +50,7 @@ LL | const FOO: usize = 7;
| --------------------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:44:1
--> $DIR/invalid-attribute.rs:59:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -32,7 +59,7 @@ LL | struct Foo;
| ----------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:49:1
--> $DIR/invalid-attribute.rs:64:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -41,7 +68,7 @@ LL | enum Bar {}
| ----------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:54:1
--> $DIR/invalid-attribute.rs:69:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -54,7 +81,16 @@ LL | | }
| |_- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:62:1
--> $DIR/invalid-attribute.rs:77:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | type Uwu = ();
| -------------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:82:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -63,7 +99,34 @@ LL | trait Baz {}
| ------------ not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:85:5
--> $DIR/invalid-attribute.rs:92:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | static A: () = ();
| ------------------ not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:97:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | impl Quux for u8 {}
| ------------------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:102:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | impl Foo {}
| ----------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:120:5
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -75,7 +138,7 @@ LL | | }
| |_____- not a function definition

error: attribute should be applied to a function definition
--> $DIR/invalid-attribute.rs:93:5
--> $DIR/invalid-attribute.rs:128:5
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -84,25 +147,25 @@ LL | || {};
| ----- not a function definition

error: the feature named `foo` is not valid for this target
--> $DIR/invalid-attribute.rs:19:18
--> $DIR/invalid-attribute.rs:34:18
|
LL | #[target_feature(enable = "foo")]
| ^^^^^^^^^^^^^^ `foo` is not valid for this target

error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:22:18
--> $DIR/invalid-attribute.rs:37:18
|
LL | #[target_feature(bar)]
| ^^^ help: must be of the form: `enable = ".."`

error: malformed `target_feature` attribute input
--> $DIR/invalid-attribute.rs:24:18
--> $DIR/invalid-attribute.rs:39:18
|
LL | #[target_feature(disable = "baz")]
| ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`

error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
--> $DIR/invalid-attribute.rs:28:1
--> $DIR/invalid-attribute.rs:43:1
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -114,13 +177,13 @@ LL | fn bar() {}
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable

error: cannot use `#[inline(always)]` with `#[target_feature]`
--> $DIR/invalid-attribute.rs:67:1
--> $DIR/invalid-attribute.rs:87:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^

error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
--> $DIR/invalid-attribute.rs:77:5
--> $DIR/invalid-attribute.rs:112:5
|
LL | #[target_feature(enable = "sse2")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -131,6 +194,6 @@ LL | fn foo() {}
= note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable

error: aborting due to 15 previous errors
error: aborting due to 22 previous errors

For more information about this error, try `rustc --explain E0658`.