From 0df84cdc4979e53dbeb1620b8db1096a16271a85 Mon Sep 17 00:00:00 2001 From: jam1garner <8260240+jam1garner@users.noreply.github.com> Date: Fri, 1 Apr 2022 01:29:38 -0400 Subject: [PATCH 1/2] Don't emit non-asm contents error for naked function composed of errors --- compiler/rustc_passes/src/naked_functions.rs | 25 +++++++++++++++++--- src/test/ui/asm/naked-functions.rs | 13 ++++++++++ src/test/ui/asm/naked-functions.stderr | 14 ++++++++++- 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 00a93ccc9aa09..cd966df119f4c 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 9c6e810dfce6d..a8fd24a3e07c0 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 5520f815f3e54..32eae1f37a3f0 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`. From bf26d87df669d706c7897ca168c04bdeefb78bc5 Mon Sep 17 00:00:00 2001 From: jam1garner <8260240+jam1garner@users.noreply.github.com> Date: Fri, 1 Apr 2022 12:24:04 -0400 Subject: [PATCH 2/2] Add regression test for naked functions with invalid asm syntax --- src/test/ui/asm/naked-functions.rs | 6 ++++++ src/test/ui/asm/naked-functions.stderr | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs index a8fd24a3e07c0..2a57afa1a6a6e 100644 --- a/src/test/ui/asm/naked-functions.rs +++ b/src/test/ui/asm/naked-functions.rs @@ -209,3 +209,9 @@ pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 { //~^ ERROR this is a user specified error asm!("", options(noreturn)) } + +#[naked] +pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 { + asm!(invalid_syntax) + //~^ ERROR asm template must be a string literal +} diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr index 32eae1f37a3f0..7bbe49c3b1944 100644 --- a/src/test/ui/asm/naked-functions.stderr +++ b/src/test/ui/asm/naked-functions.stderr @@ -16,6 +16,12 @@ error: this is a user specified error LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: asm template must be a string literal + --> $DIR/naked-functions.rs:215:10 + | +LL | asm!(invalid_syntax) + | ^^^^^^^^^^^^^^ + error: patterns not allowed in naked function parameters --> $DIR/naked-functions.rs:20:5 | @@ -267,6 +273,6 @@ error: naked functions cannot be inlined LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ -error: aborting due to 32 previous errors; 2 warnings emitted +error: aborting due to 33 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0787`.