about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNathaniel McCallum <nathaniel@congru.us>2021-08-02 15:03:43 -0400
committerNathaniel McCallum <nathaniel@congru.us>2021-08-02 21:49:51 -0400
commit157e0a0e8f68ab997b320a2d61c2d8ad20d5ce86 (patch)
tree7d397100e11380c2f4d0b2c2877c4e06e7ed160e
parent6be8a06bcf2e7c45db2f9e3dd3c9c0e282562a93 (diff)
downloadrust-157e0a0e8f68ab997b320a2d61c2d8ad20d5ce86.tar.gz
rust-157e0a0e8f68ab997b320a2d61c2d8ad20d5ce86.zip
Validate that naked functions are never inlined
Reject all uses of the inline attribute on naked functions.

rust-lang/rfcs#2774
rust-lang/rfcs#2972
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs3
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs12
-rw-r--r--src/test/ui/asm/naked-functions.rs43
-rw-r--r--src/test/ui/asm/naked-functions.stderr56
4 files changed, 112 insertions, 2 deletions
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 7195c41eae9..b1948ae072b 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2720,6 +2720,9 @@ declare_lint! {
     /// The asm block must not contain any operands other than `const` and
     /// `sym`. Additionally, naked function should specify a non-Rust ABI.
     ///
+    /// Naked functions cannot be inlined. All forms of the `inline` attribute
+    /// are prohibited.
+    ///
     /// While other definitions of naked functions were previously accepted,
     /// they are unsupported and might not work reliably. This is a
     /// [future-incompatible] lint that will transition into hard error in
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 89bc2e1a987..e05ec205b65 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -1,6 +1,6 @@
 //! Checks validity of naked functions.
 
-use rustc_ast::InlineAsmOptions;
+use rustc_ast::{Attribute, InlineAsmOptions};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{ErasedMap, FnKind, NestedVisitorMap, Visitor};
@@ -70,10 +70,20 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
             check_no_patterns(self.tcx, body.params);
             check_no_parameters_use(self.tcx, body);
             check_asm(self.tcx, hir_id, body, span);
+            check_inline(self.tcx, hir_id, attrs);
         }
     }
 }
 
+/// Check that the function isn't inlined.
+fn check_inline(tcx: TyCtxt<'_>, hir_id: HirId, attrs: &[Attribute]) {
+    for attr in attrs.iter().filter(|attr| attr.has_name(sym::inline)) {
+        tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, attr.span, |lint| {
+            lint.build("naked functions cannot be inlined").emit();
+        });
+    }
+}
+
 /// Checks that function uses non-Rust ABI.
 fn check_abi(tcx: TyCtxt<'_>, hir_id: HirId, abi: Abi, fn_ident_span: Span) {
     if abi == Abi::Rust {
diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs
index a46ca4544a6..7075995c2cf 100644
--- a/src/test/ui/asm/naked-functions.rs
+++ b/src/test/ui/asm/naked-functions.rs
@@ -167,3 +167,46 @@ pub unsafe extern "C" fn valid_c() {
 pub unsafe extern "C" fn valid_att_syntax() {
     asm!("", options(noreturn, att_syntax));
 }
+
+#[naked]
+pub unsafe extern "C" fn inline_none() {
+    asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline]
+//~^ WARN naked functions cannot be inlined
+//~| WARN this was previously accepted
+pub unsafe extern "C" fn inline_hint() {
+    asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline(always)]
+//~^ WARN naked functions cannot be inlined
+//~| WARN this was previously accepted
+pub unsafe extern "C" fn inline_always() {
+    asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline(never)]
+//~^ WARN naked functions cannot be inlined
+//~| WARN this was previously accepted
+pub unsafe extern "C" fn inline_never() {
+    asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline]
+//~^ WARN naked functions cannot be inlined
+//~| WARN this was previously accepted
+#[inline(always)]
+//~^ WARN naked functions cannot be inlined
+//~| WARN this was previously accepted
+#[inline(never)]
+//~^ WARN naked functions cannot be inlined
+//~| WARN this was previously accepted
+pub unsafe extern "C" fn inline_all() {
+    asm!("", options(noreturn));
+}
diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr
index 9a82da8d90d..2a186a69ff4 100644
--- a/src/test/ui/asm/naked-functions.stderr
+++ b/src/test/ui/asm/naked-functions.stderr
@@ -296,5 +296,59 @@ LL | pub unsafe extern "Rust" fn rust_abi() {
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
-error: aborting due to 8 previous errors; 19 warnings emitted
+warning: naked functions cannot be inlined
+  --> $DIR/naked-functions.rs:177:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions cannot be inlined
+  --> $DIR/naked-functions.rs:185:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions cannot be inlined
+  --> $DIR/naked-functions.rs:193:1
+   |
+LL | #[inline(never)]
+   | ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions cannot be inlined
+  --> $DIR/naked-functions.rs:201:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions cannot be inlined
+  --> $DIR/naked-functions.rs:204:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions cannot be inlined
+  --> $DIR/naked-functions.rs:207:1
+   |
+LL | #[inline(never)]
+   | ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+error: aborting due to 8 previous errors; 25 warnings emitted