@@ -7,6 +7,7 @@ use rustc_middle::ty::{self, TyCtxt};
77use rustc_session:: lint:: builtin:: { UNSAFE_OP_IN_UNSAFE_FN , UNUSED_UNSAFE } ;
88use rustc_session:: lint:: Level ;
99use rustc_span:: def_id:: { DefId , LocalDefId } ;
10+ use rustc_span:: symbol:: Symbol ;
1011use rustc_span:: Span ;
1112
1213struct UnsafetyVisitor < ' a , ' tcx > {
@@ -19,6 +20,9 @@ struct UnsafetyVisitor<'a, 'tcx> {
1920 /// `unsafe` block, and whether it has been used.
2021 safety_context : SafetyContext ,
2122 body_unsafety : BodyUnsafety ,
23+ /// The `#[target_feature]` attributes of the body. Used for checking
24+ /// calls to functions with `#[target_feature]` (RFC 2396).
25+ body_target_features : & ' tcx Vec < Symbol > ,
2226}
2327
2428impl < ' tcx > UnsafetyVisitor < ' _ , ' tcx > {
@@ -148,11 +152,28 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
148152 ExprKind :: Call { fun, ty : _, args : _, from_hir_call : _, fn_span : _ } => {
149153 if self . thir [ fun] . ty . fn_sig ( self . tcx ) . unsafety ( ) == hir:: Unsafety :: Unsafe {
150154 self . requires_unsafe ( expr. span , CallToUnsafeFunction ) ;
155+ } else if let & ty:: FnDef ( func_did, _) = self . thir [ fun] . ty . kind ( ) {
156+ // If the called function has target features the calling function hasn't,
157+ // the call requires `unsafe`.
158+ if !self
159+ . tcx
160+ . codegen_fn_attrs ( func_did)
161+ . target_features
162+ . iter ( )
163+ . all ( |feature| self . body_target_features . contains ( feature) )
164+ {
165+ self . requires_unsafe ( expr. span , CallToFunctionWith ) ;
166+ }
151167 }
152168 }
153169 ExprKind :: InlineAsm { .. } | ExprKind :: LlvmInlineAsm { .. } => {
154170 self . requires_unsafe ( expr. span , UseOfInlineAssembly ) ;
155171 }
172+ ExprKind :: Deref { arg } => {
173+ if self . thir [ arg] . ty . is_unsafe_ptr ( ) {
174+ self . requires_unsafe ( expr. span , DerefOfRawPointer ) ;
175+ }
176+ }
156177 _ => { }
157178 }
158179
@@ -203,7 +224,6 @@ enum UnsafeOpKind {
203224 UseOfMutableStatic ,
204225 #[ allow( dead_code) ] // FIXME
205226 UseOfExternStatic ,
206- #[ allow( dead_code) ] // FIXME
207227 DerefOfRawPointer ,
208228 #[ allow( dead_code) ] // FIXME
209229 AssignToDroppingUnionField ,
@@ -213,7 +233,6 @@ enum UnsafeOpKind {
213233 MutationOfLayoutConstrainedField ,
214234 #[ allow( dead_code) ] // FIXME
215235 BorrowOfLayoutConstrainedField ,
216- #[ allow( dead_code) ] // FIXME
217236 CallToFunctionWith ,
218237}
219238
@@ -287,6 +306,7 @@ pub fn check_unsafety<'tcx>(
287306 tcx : TyCtxt < ' tcx > ,
288307 thir : & Thir < ' tcx > ,
289308 expr : ExprId ,
309+ def_id : LocalDefId ,
290310 hir_id : hir:: HirId ,
291311) {
292312 let body_unsafety = tcx. hir ( ) . fn_sig_by_hir_id ( hir_id) . map_or ( BodyUnsafety :: Safe , |fn_sig| {
@@ -296,10 +316,17 @@ pub fn check_unsafety<'tcx>(
296316 BodyUnsafety :: Safe
297317 }
298318 } ) ;
319+ let body_target_features = & tcx. codegen_fn_attrs ( def_id) . target_features ;
299320 let safety_context =
300321 if body_unsafety. is_unsafe ( ) { SafetyContext :: UnsafeFn } else { SafetyContext :: Safe } ;
301- let mut visitor =
302- UnsafetyVisitor { tcx, thir, safety_context, hir_context : hir_id, body_unsafety } ;
322+ let mut visitor = UnsafetyVisitor {
323+ tcx,
324+ thir,
325+ safety_context,
326+ hir_context : hir_id,
327+ body_unsafety,
328+ body_target_features,
329+ } ;
303330 visitor. visit_expr ( & thir[ expr] ) ;
304331}
305332
@@ -311,7 +338,7 @@ crate fn thir_check_unsafety_inner<'tcx>(
311338 let body_id = tcx. hir ( ) . body_owned_by ( hir_id) ;
312339 let body = tcx. hir ( ) . body ( body_id) ;
313340 let ( thir, expr) = cx:: build_thir ( tcx, def, & body. value ) ;
314- check_unsafety ( tcx, & thir, expr, hir_id) ;
341+ check_unsafety ( tcx, & thir, expr, def . did , hir_id) ;
315342}
316343
317344crate fn thir_check_unsafety < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) {
0 commit comments