Skip to content

Commit

Permalink
Gracefully handle #[target_feature] on statics
Browse files Browse the repository at this point in the history
The was careful around not calling `fn_sig` on not-functions but well,
it wasn't careful enough. This commit makes it a little more careful and
also adds tests for a bunch more item kinds.
  • Loading branch information
Noratrieb committed Mar 13, 2023
1 parent d583342 commit 34be05e
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 36 deletions.
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`.

0 comments on commit 34be05e

Please sign in to comment.