]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_passes/src/naked_functions.rs
Rollup merge of #107316 - ChrisDenton:snap, r=oli-obk
[rust.git] / compiler / rustc_passes / src / naked_functions.rs
index 607973446fc1e32c3818f682c746013b5e0e250a..acc54e7e11006885c3eee899c05fba4a44252295 100644 (file)
@@ -1,7 +1,6 @@
 //! Checks validity of naked functions.
 
 use rustc_ast::InlineAsmOptions;
-use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
+use crate::errors::{
+    CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
+    NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
+    UndefinedNakedFunctionAbi,
+};
+
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { check_mod_naked_functions, ..*providers };
 }
@@ -56,7 +61,7 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let attrs = tcx.get_attrs(def_id.to_def_id(), sym::inline);
     for attr in attrs {
-        tcx.sess.struct_span_err(attr.span, "naked functions cannot be inlined").emit();
+        tcx.sess.emit_err(CannotInlineNakedFunction { span: attr.span });
     }
 }
 
@@ -65,9 +70,12 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
     if abi == Abi::Rust {
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         let span = tcx.def_span(def_id);
-        tcx.struct_span_lint_hir(UNDEFINED_NAKED_FUNCTION_ABI, hir_id, span, |lint| {
-            lint.build("Rust ABI is unsupported in naked functions").emit();
-        });
+        tcx.emit_spanned_lint(
+            UNDEFINED_NAKED_FUNCTION_ABI,
+            hir_id,
+            span,
+            UndefinedNakedFunctionAbi,
+        );
     }
 }
 
@@ -78,12 +86,7 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
             hir::PatKind::Wild
             | hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, _, None) => {}
             _ => {
-                tcx.sess
-                    .struct_span_err(
-                        param.pat.span,
-                        "patterns not allowed in naked function parameters",
-                    )
-                    .emit();
+                tcx.sess.emit_err(NoPatterns { span: param.pat.span });
             }
         }
     }
@@ -113,14 +116,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         )) = expr.kind
         {
             if self.params.contains(var_hir_id) {
-                self.tcx
-                    .sess
-                    .struct_span_err(
-                        expr.span,
-                        "referencing function parameters is not allowed in naked functions",
-                    )
-                    .help("follow the calling convention in asm block to use parameters")
-                    .emit();
+                self.tcx.sess.emit_err(ParamsNotAllowed { span: expr.span });
                 return;
             }
         }
@@ -135,26 +131,21 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
     if let [(ItemKind::Asm | ItemKind::Err, _)] = this.items[..] {
         // Ok.
     } else {
-        let mut diag = struct_span_err!(
-            tcx.sess,
-            tcx.def_span(def_id),
-            E0787,
-            "naked functions must contain a single asm block"
-        );
-
         let mut must_show_error = false;
         let mut has_asm = false;
         let mut has_err = false;
+        let mut multiple_asms = vec![];
+        let mut non_asms = vec![];
         for &(kind, span) in &this.items {
             match kind {
                 ItemKind::Asm if has_asm => {
                     must_show_error = true;
-                    diag.span_label(span, "multiple asm blocks are unsupported in naked functions");
+                    multiple_asms.push(span);
                 }
                 ItemKind::Asm => has_asm = true,
                 ItemKind::NonAsm => {
                     must_show_error = true;
-                    diag.span_label(span, "non-asm is unsupported in naked functions");
+                    non_asms.push(span);
                 }
                 ItemKind::Err => has_err = true,
             }
@@ -164,9 +155,11 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
         // errors, then don't show an additional error. This allows for appending/prepending
         // `compile_error!("...")` statements and reduces error noise.
         if must_show_error || !has_err {
-            diag.emit();
-        } else {
-            diag.cancel();
+            tcx.sess.emit_err(NakedFunctionsAsmBlock {
+                span: tcx.def_span(def_id),
+                multiple_asms,
+                non_asms,
+            });
         }
     }
 }
@@ -247,13 +240,7 @@ fn check_inline_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
             })
             .collect();
         if !unsupported_operands.is_empty() {
-            struct_span_err!(
-                self.tcx.sess,
-                unsupported_operands,
-                E0787,
-                "only `const` and `sym` operands are supported in naked functions",
-            )
-            .emit();
+            self.tcx.sess.emit_err(NakedFunctionsOperands { unsupported_operands });
         }
 
         let unsupported_options: Vec<&'static str> = [
@@ -269,14 +256,10 @@ fn check_inline_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
         .collect();
 
         if !unsupported_options.is_empty() {
-            struct_span_err!(
-                self.tcx.sess,
+            self.tcx.sess.emit_err(NakedFunctionsAsmOptions {
                 span,
-                E0787,
-                "asm options unsupported in naked functions: {}",
-                unsupported_options.join(", ")
-            )
-            .emit();
+                unsupported_options: unsupported_options.join(", "),
+            });
         }
 
         if !asm.options.contains(InlineAsmOptions::NORETURN) {
@@ -286,20 +269,7 @@ fn check_inline_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
                 .map_or_else(|| asm.template_strs.last().unwrap().2, |op| op.1)
                 .shrink_to_hi();
 
-            struct_span_err!(
-                self.tcx.sess,
-                span,
-                E0787,
-                "asm in naked functions must use `noreturn` option"
-            )
-            .span_suggestion(
-                last_span,
-                "consider specifying that the asm block is responsible \
-                for returning from the function",
-                ", options(noreturn)",
-                Applicability::MachineApplicable,
-            )
-            .emit();
+            self.tcx.sess.emit_err(NakedFunctionsMustUseNoreturn { span, last_span });
         }
     }
 }