Skip to content

Commit a6f1c6a

Browse files
committed
Auto merge of #49425 - alexcrichton:disallow-inline-always, r=petrochenkov
rustc: Forbid #[inline(always)] with #[target_feature] Once a target feature is enabled for a function that means that it in general can't be inlined into other functions which don't have that target feature enabled. This can cause both safety and LLVM issues if we were to actually inline it, so `#[inline(always)]` both can't be respected and would be an error if we did so! Today LLVM doesn't inline functions with different `#[target_feature]` annotations, but it turns out that if one is tagged with `#[inline(always)]` it'll override this and cause scary LLVM error to arise! This commit fixes this issue by forbidding these two attributes to be used in conjunction with one another. Closes rust-lang/stdarch#404
2 parents 4379c86 + 38d48ef commit a6f1c6a

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

src/librustc_typeck/collect.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,7 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
17691769

17701770
let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
17711771

1772+
let mut inline_span = None;
17721773
for attr in attrs.iter() {
17731774
if attr.check_name("cold") {
17741775
trans_fn_attrs.flags |= TransFnAttrFlags::COLD;
@@ -1800,6 +1801,7 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
18001801
}
18011802
MetaItemKind::List(ref items) => {
18021803
mark_used(attr);
1804+
inline_span = Some(attr.span);
18031805
if items.len() != 1 {
18041806
span_err!(tcx.sess.diagnostic(), attr.span, E0534,
18051807
"expected one argument");
@@ -1855,5 +1857,18 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
18551857
}
18561858
}
18571859

1860+
// If a function uses #[target_feature] it can't be inlined into general
1861+
// purpose functions as they wouldn't have the right target features
1862+
// enabled. For that reason we also forbid #[inline(always)] as it can't be
1863+
// respected.
1864+
if trans_fn_attrs.target_features.len() > 0 {
1865+
if trans_fn_attrs.inline == InlineAttr::Always {
1866+
if let Some(span) = inline_span {
1867+
tcx.sess.span_err(span, "cannot use #[inline(always)] with \
1868+
#[target_feature]");
1869+
}
1870+
}
1871+
}
1872+
18581873
trans_fn_attrs
18591874
}

src/test/ui/target-feature-wrong.rs

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ fn bar() {}
3333
//~^ ERROR: should be applied to a function
3434
mod another {}
3535

36+
#[inline(always)]
37+
//~^ ERROR: cannot use #[inline(always)]
38+
#[target_feature(enable = "sse2")]
39+
unsafe fn test() {}
40+
3641
fn main() {
3742
unsafe {
3843
foo();

src/test/ui/target-feature-wrong.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,11 @@ LL | //~^ ERROR: should be applied to a function
3737
LL | mod another {}
3838
| -------------- not a function
3939

40-
error: aborting due to 5 previous errors
40+
error: cannot use #[inline(always)] with #[target_feature]
41+
--> $DIR/target-feature-wrong.rs:36:1
42+
|
43+
LL | #[inline(always)]
44+
| ^^^^^^^^^^^^^^^^^
45+
46+
error: aborting due to 6 previous errors
4147

0 commit comments

Comments
 (0)