Check for calls to functions with #[target_feature]
in THIR unsafeck
This commit is contained in:
parent
27fe959c2c
commit
d7787bbaef
9 changed files with 180 additions and 48 deletions
|
@ -7,6 +7,7 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
|
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
|
||||||
use rustc_session::lint::Level;
|
use rustc_session::lint::Level;
|
||||||
use rustc_span::def_id::{DefId, LocalDefId};
|
use rustc_span::def_id::{DefId, LocalDefId};
|
||||||
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
struct UnsafetyVisitor<'a, 'tcx> {
|
struct UnsafetyVisitor<'a, 'tcx> {
|
||||||
|
@ -19,6 +20,9 @@ struct UnsafetyVisitor<'a, 'tcx> {
|
||||||
/// `unsafe` block, and whether it has been used.
|
/// `unsafe` block, and whether it has been used.
|
||||||
safety_context: SafetyContext,
|
safety_context: SafetyContext,
|
||||||
body_unsafety: BodyUnsafety,
|
body_unsafety: BodyUnsafety,
|
||||||
|
/// The `#[target_feature]` attributes of the body. Used for checking
|
||||||
|
/// calls to functions with `#[target_feature]` (RFC 2396).
|
||||||
|
body_target_features: &'tcx Vec<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
||||||
|
@ -148,6 +152,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||||
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
|
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
|
||||||
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
|
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
|
||||||
self.requires_unsafe(expr.span, CallToUnsafeFunction);
|
self.requires_unsafe(expr.span, CallToUnsafeFunction);
|
||||||
|
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
|
||||||
|
// If the called function has target features the calling function hasn't,
|
||||||
|
// the call requires `unsafe`.
|
||||||
|
if !self
|
||||||
|
.tcx
|
||||||
|
.codegen_fn_attrs(func_did)
|
||||||
|
.target_features
|
||||||
|
.iter()
|
||||||
|
.all(|feature| self.body_target_features.contains(feature))
|
||||||
|
{
|
||||||
|
self.requires_unsafe(expr.span, CallToFunctionWith);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
|
ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
|
||||||
|
@ -217,7 +233,6 @@ enum UnsafeOpKind {
|
||||||
MutationOfLayoutConstrainedField,
|
MutationOfLayoutConstrainedField,
|
||||||
#[allow(dead_code)] // FIXME
|
#[allow(dead_code)] // FIXME
|
||||||
BorrowOfLayoutConstrainedField,
|
BorrowOfLayoutConstrainedField,
|
||||||
#[allow(dead_code)] // FIXME
|
|
||||||
CallToFunctionWith,
|
CallToFunctionWith,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +306,7 @@ pub fn check_unsafety<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
thir: &Thir<'tcx>,
|
thir: &Thir<'tcx>,
|
||||||
expr: ExprId,
|
expr: ExprId,
|
||||||
|
def_id: LocalDefId,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
) {
|
) {
|
||||||
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
|
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
|
||||||
|
@ -300,10 +316,17 @@ pub fn check_unsafety<'tcx>(
|
||||||
BodyUnsafety::Safe
|
BodyUnsafety::Safe
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
let body_target_features = &tcx.codegen_fn_attrs(def_id).target_features;
|
||||||
let safety_context =
|
let safety_context =
|
||||||
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
|
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
|
||||||
let mut visitor =
|
let mut visitor = UnsafetyVisitor {
|
||||||
UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety };
|
tcx,
|
||||||
|
thir,
|
||||||
|
safety_context,
|
||||||
|
hir_context: hir_id,
|
||||||
|
body_unsafety,
|
||||||
|
body_target_features,
|
||||||
|
};
|
||||||
visitor.visit_expr(&thir[expr]);
|
visitor.visit_expr(&thir[expr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +338,7 @@ crate fn thir_check_unsafety_inner<'tcx>(
|
||||||
let body_id = tcx.hir().body_owned_by(hir_id);
|
let body_id = tcx.hir().body_owned_by(hir_id);
|
||||||
let body = tcx.hir().body(body_id);
|
let body = tcx.hir().body(body_id);
|
||||||
let (thir, expr) = cx::build_thir(tcx, def, &body.value);
|
let (thir, expr) = cx::build_thir(tcx, def, &body.value);
|
||||||
check_unsafety(tcx, &thir, expr, hir_id);
|
check_unsafety(tcx, &thir, expr, def.did, hir_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
|
crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
// check-pass
|
// check-pass
|
||||||
// only-x86_64
|
// only-x86_64
|
||||||
|
// revisions: mir thir
|
||||||
|
// [thir]compile-flags: -Z thir-unsafeck
|
||||||
|
|
||||||
#![feature(target_feature_11)]
|
#![feature(target_feature_11)]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Tests #73631: closures inherit `#[target_feature]` annotations
|
// Tests #73631: closures inherit `#[target_feature]` annotations
|
||||||
|
|
||||||
// check-pass
|
// check-pass
|
||||||
|
// revisions: mir thir
|
||||||
|
// [thir]compile-flags: -Z thir-unsafeck
|
||||||
// only-x86_64
|
// only-x86_64
|
||||||
|
|
||||||
#![feature(target_feature_11)]
|
#![feature(target_feature_11)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/fn-ptr.rs:9:21
|
--> $DIR/fn-ptr.rs:11:21
|
||||||
|
|
|
|
||||||
LL | #[target_feature(enable = "sse2")]
|
LL | #[target_feature(enable = "sse2")]
|
||||||
| ---------------------------------- `#[target_feature]` added here
|
| ---------------------------------- `#[target_feature]` added here
|
|
@ -1,3 +1,5 @@
|
||||||
|
// revisions: mir thir
|
||||||
|
// [thir]compile-flags: -Z thir-unsafeck
|
||||||
// only-x86_64
|
// only-x86_64
|
||||||
|
|
||||||
#![feature(target_feature_11)]
|
#![feature(target_feature_11)]
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/fn-ptr.rs:11:21
|
||||||
|
|
|
||||||
|
LL | #[target_feature(enable = "sse2")]
|
||||||
|
| ---------------------------------- `#[target_feature]` added here
|
||||||
|
...
|
||||||
|
LL | let foo: fn() = foo;
|
||||||
|
| ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected fn pointer `fn()`
|
||||||
|
found fn item `fn() {foo}`
|
||||||
|
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -1,69 +1,69 @@
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/safe-calls.rs:21:5
|
|
||||||
|
|
|
||||||
LL | sse2();
|
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
|
||||||
|
|
|
||||||
= note: can only be called if the required target features are available
|
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/safe-calls.rs:22:5
|
|
||||||
|
|
|
||||||
LL | avx_bmi2();
|
|
||||||
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
|
||||||
|
|
|
||||||
= note: can only be called if the required target features are available
|
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:23:5
|
--> $DIR/safe-calls.rs:23:5
|
||||||
|
|
|
|
||||||
LL | Quux.avx_bmi2();
|
|
||||||
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
|
||||||
|
|
|
||||||
= note: can only be called if the required target features are available
|
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/safe-calls.rs:28:5
|
|
||||||
|
|
|
||||||
LL | avx_bmi2();
|
|
||||||
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
|
||||||
|
|
|
||||||
= note: can only be called if the required target features are available
|
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/safe-calls.rs:29:5
|
|
||||||
|
|
|
||||||
LL | Quux.avx_bmi2();
|
|
||||||
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
|
||||||
|
|
|
||||||
= note: can only be called if the required target features are available
|
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/safe-calls.rs:34:5
|
|
||||||
|
|
|
||||||
LL | sse2();
|
LL | sse2();
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
|
||||||
= note: can only be called if the required target features are available
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:35:5
|
--> $DIR/safe-calls.rs:24:5
|
||||||
|
|
|
|
||||||
LL | avx_bmi2();
|
LL | avx_bmi2();
|
||||||
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
|
||||||
= note: can only be called if the required target features are available
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:25:5
|
||||||
|
|
|
||||||
|
LL | Quux.avx_bmi2();
|
||||||
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:30:5
|
||||||
|
|
|
||||||
|
LL | avx_bmi2();
|
||||||
|
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:31:5
|
||||||
|
|
|
||||||
|
LL | Quux.avx_bmi2();
|
||||||
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:36:5
|
--> $DIR/safe-calls.rs:36:5
|
||||||
|
|
|
|
||||||
|
LL | sse2();
|
||||||
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:37:5
|
||||||
|
|
|
||||||
|
LL | avx_bmi2();
|
||||||
|
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:38:5
|
||||||
|
|
|
||||||
LL | Quux.avx_bmi2();
|
LL | Quux.avx_bmi2();
|
||||||
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
|
||||||
= note: can only be called if the required target features are available
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:42:5
|
--> $DIR/safe-calls.rs:44:5
|
||||||
|
|
|
|
||||||
LL | sse2();
|
LL | sse2();
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
|
@ -71,7 +71,7 @@ LL | sse2();
|
||||||
= note: can only be called if the required target features are available
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
--> $DIR/safe-calls.rs:45:18
|
--> $DIR/safe-calls.rs:47:18
|
||||||
|
|
|
|
||||||
LL | const name: () = sse2();
|
LL | const name: () = sse2();
|
||||||
| ^^^^^^ call to function with `#[target_feature]`
|
| ^^^^^^ call to function with `#[target_feature]`
|
|
@ -1,3 +1,5 @@
|
||||||
|
// revisions: mir thir
|
||||||
|
// [thir]compile-flags: -Z thir-unsafeck
|
||||||
// only-x86_64
|
// only-x86_64
|
||||||
|
|
||||||
#![feature(target_feature_11)]
|
#![feature(target_feature_11)]
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:23:5
|
||||||
|
|
|
||||||
|
LL | sse2();
|
||||||
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:24:5
|
||||||
|
|
|
||||||
|
LL | avx_bmi2();
|
||||||
|
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:25:5
|
||||||
|
|
|
||||||
|
LL | Quux.avx_bmi2();
|
||||||
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:30:5
|
||||||
|
|
|
||||||
|
LL | avx_bmi2();
|
||||||
|
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:31:5
|
||||||
|
|
|
||||||
|
LL | Quux.avx_bmi2();
|
||||||
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:36:5
|
||||||
|
|
|
||||||
|
LL | sse2();
|
||||||
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:37:5
|
||||||
|
|
|
||||||
|
LL | avx_bmi2();
|
||||||
|
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:38:5
|
||||||
|
|
|
||||||
|
LL | Quux.avx_bmi2();
|
||||||
|
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:44:5
|
||||||
|
|
|
||||||
|
LL | sse2();
|
||||||
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/safe-calls.rs:47:18
|
||||||
|
|
|
||||||
|
LL | const name: () = sse2();
|
||||||
|
| ^^^^^^ call to function with `#[target_feature]`
|
||||||
|
|
|
||||||
|
= note: can only be called if the required target features are available
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0133`.
|
Loading…
Add table
Reference in a new issue