@@ -6,6 +6,7 @@ use rustc_hir::def::DefKind;
6
6
use rustc_hir:: def_id:: { LocalDefId , LocalModDefId } ;
7
7
use rustc_hir:: intravisit:: Visitor ;
8
8
use rustc_hir:: { ExprKind , HirIdSet , InlineAsmOperand , StmtKind } ;
9
+ use rustc_middle:: hir:: nested_filter:: OnlyBodies ;
9
10
use rustc_middle:: query:: Providers ;
10
11
use rustc_middle:: ty:: TyCtxt ;
11
12
use rustc_session:: lint:: builtin:: UNDEFINED_NAKED_FUNCTION_ABI ;
@@ -14,8 +15,9 @@ use rustc_span::Span;
14
15
use rustc_target:: spec:: abi:: Abi ;
15
16
16
17
use crate :: errors:: {
17
- NakedFunctionsAsmBlock , NakedFunctionsAsmOptions , NakedFunctionsMustUseNoreturn ,
18
- NakedFunctionsOperands , NoPatterns , ParamsNotAllowed , UndefinedNakedFunctionAbi ,
18
+ NakedAsmOutsideNakedFn , NakedFunctionsAsmBlock , NakedFunctionsAsmOptions ,
19
+ NakedFunctionsMustUseNoreturn , NakedFunctionsOperands , NoPatterns , ParamsNotAllowed ,
20
+ UndefinedNakedFunctionAbi ,
19
21
} ;
20
22
21
23
pub ( crate ) fn provide ( providers : & mut Providers ) {
@@ -29,11 +31,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
29
31
continue ;
30
32
}
31
33
32
- let naked = tcx. has_attr ( def_id, sym:: naked) ;
33
- if !naked {
34
- continue ;
35
- }
36
-
37
34
let ( fn_header, body_id) = match tcx. hir_node_by_def_id ( def_id) {
38
35
hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Fn ( sig, _, body_id) , .. } )
39
36
| hir:: Node :: TraitItem ( hir:: TraitItem {
@@ -48,10 +45,17 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
48
45
} ;
49
46
50
47
let body = tcx. hir ( ) . body ( body_id) ;
51
- check_abi ( tcx, def_id, fn_header. abi ) ;
52
- check_no_patterns ( tcx, body. params ) ;
53
- check_no_parameters_use ( tcx, body) ;
54
- check_asm ( tcx, def_id, body) ;
48
+
49
+ if tcx. has_attr ( def_id, sym:: naked) {
50
+ check_abi ( tcx, def_id, fn_header. abi ) ;
51
+ check_no_patterns ( tcx, body. params ) ;
52
+ check_no_parameters_use ( tcx, body) ;
53
+ check_asm ( tcx, def_id, body) ;
54
+ } else {
55
+ // `naked_asm!` is not allowed outside of functions marked as `#[naked]`
56
+ let mut visitor = CheckNakedAsmInNakedFn { tcx } ;
57
+ visitor. visit_body ( body) ;
58
+ }
55
59
}
56
60
}
57
61
@@ -276,3 +280,25 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> {
276
280
self . check_expr ( expr, expr. span ) ;
277
281
}
278
282
}
283
+
284
+ struct CheckNakedAsmInNakedFn < ' tcx > {
285
+ tcx : TyCtxt < ' tcx > ,
286
+ }
287
+
288
+ impl < ' tcx > Visitor < ' tcx > for CheckNakedAsmInNakedFn < ' tcx > {
289
+ type NestedFilter = OnlyBodies ;
290
+
291
+ fn nested_visit_map ( & mut self ) -> Self :: Map {
292
+ self . tcx . hir ( )
293
+ }
294
+
295
+ fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
296
+ if let ExprKind :: InlineAsm ( inline_asm) = expr. kind {
297
+ if let rustc_ast:: AsmMacro :: NakedAsm = inline_asm. asm_macro {
298
+ self . tcx . dcx ( ) . emit_err ( NakedAsmOutsideNakedFn { span : expr. span } ) ;
299
+ }
300
+ }
301
+
302
+ hir:: intravisit:: walk_expr ( self , expr) ;
303
+ }
304
+ }
0 commit comments