|
1 | 1 | //! Checks validity of naked functions. |
2 | 2 |
|
3 | 3 | use rustc_hir as hir; |
4 | | -use rustc_hir::def::DefKind; |
5 | | -use rustc_hir::def_id::{LocalDefId, LocalModDefId}; |
| 4 | +use rustc_hir::def_id::LocalDefId; |
6 | 5 | use rustc_hir::intravisit::Visitor; |
7 | 6 | use rustc_hir::{ExprKind, HirIdSet, StmtKind}; |
8 | | -use rustc_middle::hir::nested_filter::OnlyBodies; |
9 | | -use rustc_middle::query::Providers; |
10 | 7 | use rustc_middle::span_bug; |
11 | 8 | use rustc_middle::ty::TyCtxt; |
12 | 9 | use rustc_span::{Span, sym}; |
13 | 10 |
|
14 | 11 | use crate::errors::{ |
15 | | - NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns, |
16 | | - ParamsNotAllowed, |
| 12 | + NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns, ParamsNotAllowed, |
17 | 13 | }; |
18 | 14 |
|
19 | | -pub(crate) fn provide(providers: &mut Providers) { |
20 | | - *providers = Providers { check_mod_naked_functions, ..*providers }; |
21 | | -} |
22 | | - |
23 | | -fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { |
24 | | - let items = tcx.hir_module_items(module_def_id); |
25 | | - for def_id in items.definitions() { |
26 | | - if !matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) { |
27 | | - continue; |
28 | | - } |
29 | | - |
30 | | - let body = match tcx.hir_node_by_def_id(def_id) { |
31 | | - hir::Node::Item(hir::Item { |
32 | | - kind: hir::ItemKind::Fn { body: body_id, .. }, .. |
33 | | - }) |
34 | | - | hir::Node::TraitItem(hir::TraitItem { |
35 | | - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)), |
36 | | - .. |
37 | | - }) |
38 | | - | hir::Node::ImplItem(hir::ImplItem { |
39 | | - kind: hir::ImplItemKind::Fn(_, body_id), .. |
40 | | - }) => tcx.hir_body(*body_id), |
41 | | - _ => continue, |
42 | | - }; |
43 | | - |
44 | | - if tcx.has_attr(def_id, sym::naked) { |
45 | | - check_no_patterns(tcx, body.params); |
46 | | - check_no_parameters_use(tcx, body); |
47 | | - check_asm(tcx, def_id, body); |
48 | | - } else { |
49 | | - // `naked_asm!` is not allowed outside of functions marked as `#[naked]` |
50 | | - let mut visitor = CheckNakedAsmInNakedFn { tcx }; |
51 | | - visitor.visit_body(body); |
52 | | - } |
53 | | - } |
| 15 | +/// Naked fns can only have trivial binding patterns in arguments, |
| 16 | +/// may not actually use those arguments, and the body must consist of just |
| 17 | +/// a single asm statement. |
| 18 | +pub(crate) fn typeck_naked_fn<'tcx>( |
| 19 | + tcx: TyCtxt<'tcx>, |
| 20 | + def_id: LocalDefId, |
| 21 | + body: &'tcx hir::Body<'tcx>, |
| 22 | +) { |
| 23 | + debug_assert!(tcx.has_attr(def_id, sym::naked)); |
| 24 | + check_no_patterns(tcx, body.params); |
| 25 | + check_no_parameters_use(tcx, body); |
| 26 | + check_asm(tcx, def_id, body); |
54 | 27 | } |
55 | 28 |
|
56 | 29 | /// Checks that parameters don't use patterns. Mirrors the checks for function declarations. |
@@ -231,25 +204,3 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly { |
231 | 204 | self.check_expr(expr, expr.span); |
232 | 205 | } |
233 | 206 | } |
234 | | - |
235 | | -struct CheckNakedAsmInNakedFn<'tcx> { |
236 | | - tcx: TyCtxt<'tcx>, |
237 | | -} |
238 | | - |
239 | | -impl<'tcx> Visitor<'tcx> for CheckNakedAsmInNakedFn<'tcx> { |
240 | | - type NestedFilter = OnlyBodies; |
241 | | - |
242 | | - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { |
243 | | - self.tcx |
244 | | - } |
245 | | - |
246 | | - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { |
247 | | - if let ExprKind::InlineAsm(inline_asm) = expr.kind { |
248 | | - if let rustc_ast::AsmMacro::NakedAsm = inline_asm.asm_macro { |
249 | | - self.tcx.dcx().emit_err(NakedAsmOutsideNakedFn { span: expr.span }); |
250 | | - } |
251 | | - } |
252 | | - |
253 | | - hir::intravisit::walk_expr(self, expr); |
254 | | - } |
255 | | -} |
0 commit comments