about summary refs log tree commit diff
diff options
context:
space:
mode:
authorjam1garner <8260240+jam1garner@users.noreply.github.com>2022-04-01 01:29:38 -0400
committerjam1garner <8260240+jam1garner@users.noreply.github.com>2022-04-01 11:02:36 -0400
commit0df84cdc4979e53dbeb1620b8db1096a16271a85 (patch)
treeb260a292523103c009abe5189bac8830ca155f7c
parent0677edc86e342f333d4828b0ee1ef395a4e70fe5 (diff)
downloadrust-0df84cdc4979e53dbeb1620b8db1096a16271a85.tar.gz
rust-0df84cdc4979e53dbeb1620b8db1096a16271a85.zip
Don't emit non-asm contents error for naked function composed of errors
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs25
-rw-r--r--src/test/ui/asm/naked-functions.rs13
-rw-r--r--src/test/ui/asm/naked-functions.stderr14
3 files changed, 48 insertions, 4 deletions
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 00a93ccc9aa..cd966df119f 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -147,7 +147,7 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
 fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>, fn_span: Span) {
     let mut this = CheckInlineAssembly { tcx, items: Vec::new() };
     this.visit_body(body);
-    if let [(ItemKind::Asm, _)] = this.items[..] {
+    if let [(ItemKind::Asm | ItemKind::Err, _)] = this.items[..] {
         // Ok.
     } else {
         let mut diag = struct_span_err!(
@@ -156,19 +156,33 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>, fn_span: Span
             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;
         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");
                 }
                 ItemKind::Asm => has_asm = true,
                 ItemKind::NonAsm => {
+                    must_show_error = true;
                     diag.span_label(span, "non-asm is unsupported in naked functions");
                 }
+                ItemKind::Err => has_err = true,
             }
         }
-        diag.emit();
+
+        // If the naked function only contains a single asm block and a non-zero number of
+        // 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();
+        }
     }
 }
 
@@ -181,6 +195,7 @@ struct CheckInlineAssembly<'tcx> {
 enum ItemKind {
     Asm,
     NonAsm,
+    Err,
 }
 
 impl<'tcx> CheckInlineAssembly<'tcx> {
@@ -222,9 +237,13 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
                 self.check_inline_asm(asm, span);
             }
 
-            ExprKind::DropTemps(..) | ExprKind::Block(..) | ExprKind::Err => {
+            ExprKind::DropTemps(..) | ExprKind::Block(..) => {
                 hir::intravisit::walk_expr(self, expr);
             }
+
+            ExprKind::Err => {
+                self.items.push((ItemKind::Err, span));
+            }
         }
     }
 
diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs
index 9c6e810dfce..a8fd24a3e07 100644
--- a/src/test/ui/asm/naked-functions.rs
+++ b/src/test/ui/asm/naked-functions.rs
@@ -196,3 +196,16 @@ pub unsafe extern "C" fn inline_never() {
 pub unsafe extern "C" fn inline_all() {
     asm!("", options(noreturn));
 }
+
+#[naked]
+pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
+    compile_error!("this is a user specified error")
+    //~^ ERROR this is a user specified error
+}
+
+#[naked]
+pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 {
+    compile_error!("this is a user specified error");
+    //~^ ERROR this is a user specified error
+    asm!("", options(noreturn))
+}
diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr
index 5520f815f3e..32eae1f37a3 100644
--- a/src/test/ui/asm/naked-functions.stderr
+++ b/src/test/ui/asm/naked-functions.stderr
@@ -4,6 +4,18 @@ error: asm with the `pure` option must have at least one output
 LL |     asm!("", options(readonly, nostack), options(pure));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
 
+error: this is a user specified error
+  --> $DIR/naked-functions.rs:202:5
+   |
+LL |     compile_error!("this is a user specified error")
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this is a user specified error
+  --> $DIR/naked-functions.rs:208:5
+   |
+LL |     compile_error!("this is a user specified error");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: patterns not allowed in naked function parameters
   --> $DIR/naked-functions.rs:20:5
    |
@@ -255,6 +267,6 @@ error: naked functions cannot be inlined
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
 
-error: aborting due to 30 previous errors; 2 warnings emitted
+error: aborting due to 32 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0787`.