Validate naked functions definitions

This commit is contained in:
Tomasz Miąsko 2020-12-07 00:00:00 +00:00
parent 91fe548825
commit 8065dabd17
10 changed files with 757 additions and 121 deletions

View File

@ -2742,6 +2742,50 @@ declare_lint! {
"detects deprecation attributes with no effect",
}
declare_lint! {
/// The `unsupported_naked_functions` lint detects naked function
/// definitions that are unsupported but were previously accepted.
///
/// ### Example
///
/// ```rust
/// #![feature(naked_functions)]
///
/// #[naked]
/// pub fn f() -> u32 {
/// 42
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The naked functions must be defined using a single inline assembly
/// block.
///
/// The execution must never fall through past the end of the assembly
/// code so the block must use `noreturn` option. The asm block can also
/// use `att_syntax` option, but other options are not allowed.
///
/// The asm block must not contain any operands other than `const` and
/// `sym`. Additionally, naked function should specify a non-Rust ABI.
///
/// 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
/// the future.
///
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub UNSUPPORTED_NAKED_FUNCTIONS,
Warn,
"unsupported naked function definitions",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #32408 <https://github.com/rust-lang/rust/issues/32408>",
edition: None,
};
}
declare_tool_lint! {
pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
Deny,
@ -2832,6 +2876,7 @@ declare_lint_pass! {
UNINHABITED_STATIC,
FUNCTION_ITEM_REFERENCES,
USELESS_DEPRECATED,
UNSUPPORTED_NAKED_FUNCTIONS,
]
}

View File

@ -1,10 +1,16 @@
//! Checks validity of naked functions.
use rustc_ast::InlineAsmOptions;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{ErasedMap, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{ExprKind, HirId, InlineAsmOperand, StmtKind};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::UNSUPPORTED_NAKED_FUNCTIONS;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
tcx.hir().visit_item_likes_in_module(
@ -33,27 +39,52 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
fk: FnKind<'v>,
_fd: &'tcx hir::FnDecl<'tcx>,
body_id: hir::BodyId,
_span: Span,
_hir_id: hir::HirId,
span: Span,
hir_id: HirId,
) {
let ident_span;
let fn_header;
match fk {
// Rejected during attribute check. Do not validate further.
FnKind::Closure(..) => return,
FnKind::ItemFn(..) | FnKind::Method(..) => {}
FnKind::Closure(..) => {
// Closures with a naked attribute are rejected during attribute
// check. Don't validate them any further.
return;
}
FnKind::ItemFn(ident, _, ref header, ..) => {
ident_span = ident.span;
fn_header = header;
}
FnKind::Method(ident, ref sig, ..) => {
ident_span = ident.span;
fn_header = &sig.header;
}
}
let naked = fk.attrs().iter().any(|attr| attr.has_name(sym::naked));
if naked {
let body = self.tcx.hir().body(body_id);
check_params(self.tcx, body);
check_body(self.tcx, body);
check_abi(self.tcx, hir_id, fn_header.abi, ident_span);
check_no_patterns(self.tcx, body.params);
check_no_parameters_use(self.tcx, body);
check_asm(self.tcx, hir_id, body, span);
}
}
}
/// 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 {
tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_ident_span, |lint| {
lint.build("Rust ABI is unsupported in naked functions").emit();
});
}
}
/// Checks that parameters don't use patterns. Mirrors the checks for function declarations.
fn check_params(tcx: TyCtxt<'_>, body: &hir::Body<'_>) {
for param in body.params {
fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
for param in params {
match param.pat.kind {
hir::PatKind::Wild
| hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, _, None) => {}
@ -69,23 +100,23 @@ fn check_params(tcx: TyCtxt<'_>, body: &hir::Body<'_>) {
}
}
/// Checks that function parameters aren't referenced in the function body.
fn check_body<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) {
/// Checks that function parameters aren't used in the function body.
fn check_no_parameters_use<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) {
let mut params = hir::HirIdSet::default();
for param in body.params {
param.pat.each_binding(|_binding_mode, hir_id, _span, _ident| {
params.insert(hir_id);
});
}
CheckBody { tcx, params }.visit_body(body);
CheckParameters { tcx, params }.visit_body(body);
}
struct CheckBody<'tcx> {
struct CheckParameters<'tcx> {
tcx: TyCtxt<'tcx>,
params: hir::HirIdSet,
}
impl<'tcx> Visitor<'tcx> for CheckBody<'tcx> {
impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
type Map = ErasedMap<'tcx>;
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@ -103,11 +134,189 @@ impl<'tcx> Visitor<'tcx> for CheckBody<'tcx> {
.sess
.struct_span_err(
expr.span,
"use of parameters not allowed inside naked functions",
"referencing function parameters is not allowed in naked functions",
)
.help("follow the calling convention in asm block to use parameters")
.emit();
return;
}
}
hir::intravisit::walk_expr(self, expr);
}
}
/// Checks that function body contains a single inline assembly block.
fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId, 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[..] {
// Ok.
} else {
tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_span, |lint| {
let mut diag = lint.build("naked functions must contain a single asm block");
let mut has_asm = false;
for &(kind, span) in &this.items {
match kind {
ItemKind::Asm if has_asm => {
diag.span_label(
span,
"multiple asm blocks are unsupported in naked functions",
);
}
ItemKind::Asm => has_asm = true,
ItemKind::NonAsm => {
diag.span_label(span, "non-asm is unsupported in naked functions");
}
}
}
diag.emit();
});
}
}
struct CheckInlineAssembly<'tcx> {
tcx: TyCtxt<'tcx>,
items: Vec<(ItemKind, Span)>,
}
#[derive(Copy, Clone)]
enum ItemKind {
Asm,
NonAsm,
}
impl<'tcx> CheckInlineAssembly<'tcx> {
fn check_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, span: Span) {
match expr.kind {
ExprKind::Box(..)
| ExprKind::ConstBlock(..)
| ExprKind::Array(..)
| ExprKind::Call(..)
| ExprKind::MethodCall(..)
| ExprKind::Tup(..)
| ExprKind::Binary(..)
| ExprKind::Unary(..)
| ExprKind::Lit(..)
| ExprKind::Cast(..)
| ExprKind::Type(..)
| ExprKind::Loop(..)
| ExprKind::Match(..)
| ExprKind::Closure(..)
| ExprKind::Assign(..)
| ExprKind::AssignOp(..)
| ExprKind::Field(..)
| ExprKind::Index(..)
| ExprKind::Path(..)
| ExprKind::AddrOf(..)
| ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
| ExprKind::Yield(..) => {
self.items.push((ItemKind::NonAsm, span));
}
ExprKind::InlineAsm(ref asm) => {
self.items.push((ItemKind::Asm, span));
self.check_inline_asm(expr.hir_id, asm, span);
}
ExprKind::LlvmInlineAsm(..) => {
self.items.push((ItemKind::Asm, span));
self.tcx.struct_span_lint_hir(
UNSUPPORTED_NAKED_FUNCTIONS,
expr.hir_id,
span,
|lint| {
lint.build(
"the LLVM-style inline assembly is unsupported in naked functions",
)
.help("use the new asm! syntax specified in RFC 2873")
.emit();
},
);
}
ExprKind::DropTemps(..) | ExprKind::Block(..) | ExprKind::Err => {
hir::intravisit::walk_expr(self, expr);
}
}
}
fn check_inline_asm(&self, hir_id: HirId, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
let unsupported_operands: Vec<Span> = asm
.operands
.iter()
.filter_map(|&(ref op, op_sp)| match op {
InlineAsmOperand::Const { .. } | InlineAsmOperand::Sym { .. } => None,
InlineAsmOperand::In { .. }
| InlineAsmOperand::Out { .. }
| InlineAsmOperand::InOut { .. }
| InlineAsmOperand::SplitInOut { .. } => Some(op_sp),
})
.collect();
if !unsupported_operands.is_empty() {
self.tcx.struct_span_lint_hir(
UNSUPPORTED_NAKED_FUNCTIONS,
hir_id,
unsupported_operands,
|lint| {
lint.build("only `const` and `sym` operands are supported in naked functions")
.emit();
},
);
}
let unsupported_options: Vec<&'static str> = [
(InlineAsmOptions::NOMEM, "`nomem`"),
(InlineAsmOptions::NOSTACK, "`nostack`"),
(InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"),
(InlineAsmOptions::PURE, "`pure`"),
(InlineAsmOptions::READONLY, "`readonly`"),
]
.iter()
.filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None })
.collect();
if !unsupported_options.is_empty() {
self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| {
lint.build(&format!(
"asm options unsupported in naked functions: {}",
unsupported_options.join(", ")
))
.emit();
});
}
if !asm.options.contains(InlineAsmOptions::NORETURN) {
self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| {
lint.build("asm in naked functions must use `noreturn` option").emit();
});
}
}
}
impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> {
type Map = ErasedMap<'tcx>;
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
NestedVisitorMap::None
}
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
match stmt.kind {
StmtKind::Item(..) => {}
StmtKind::Local(..) => {
self.items.push((ItemKind::NonAsm, stmt.span));
}
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
self.check_expr(expr, stmt.span);
}
}
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
self.check_expr(&expr, expr.span);
}
}

View File

@ -0,0 +1,169 @@
// only-x86_64
#![feature(asm)]
#![feature(llvm_asm)]
#![feature(naked_functions)]
#![feature(or_patterns)]
#![crate_type = "lib"]
#[repr(C)]
pub struct P { x: u8, y: u16 }
#[naked]
pub unsafe extern "C" fn patterns(
mut a: u32,
//~^ ERROR patterns not allowed in naked function parameters
&b: &i32,
//~^ ERROR patterns not allowed in naked function parameters
(None | Some(_)): Option<std::ptr::NonNull<u8>>,
//~^ ERROR patterns not allowed in naked function parameters
P { x, y }: P,
//~^ ERROR patterns not allowed in naked function parameters
) {
asm!("", options(noreturn))
}
#[naked]
pub unsafe extern "C" fn inc(a: u32) -> u32 {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
a + 1
//~^ ERROR referencing function parameters is not allowed in naked functions
}
#[naked]
pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
asm!("/* {0} */", in(reg) a, options(noreturn));
//~^ ERROR referencing function parameters is not allowed in naked functions
//~| WARN only `const` and `sym` operands are supported in naked functions
//~| WARN this was previously accepted
}
#[naked]
pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
(|| a + 1)()
}
#[naked]
pub unsafe extern "C" fn unsupported_operands() {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
let mut a = 0usize;
let mut b = 0usize;
let mut c = 0usize;
let mut d = 0usize;
let mut e = 0usize;
const F: usize = 0usize;
static G: usize = 0usize;
asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
in(reg) a,
//~^ WARN only `const` and `sym` operands are supported in naked functions
//~| WARN this was previously accepted
inlateout(reg) b,
inout(reg) c,
lateout(reg) d,
out(reg) e,
const F,
sym G,
);
}
#[naked]
pub extern "C" fn missing_assembly() {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
}
#[naked]
pub extern "C" fn too_many_asm_blocks() {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
asm!("");
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
asm!("");
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
asm!("");
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
asm!("", options(noreturn));
}
pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
#[naked]
pub extern "C" fn inner(y: usize) -> usize {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
*&y
//~^ ERROR referencing function parameters is not allowed in naked functions
}
inner
}
#[naked]
unsafe extern "C" fn llvm() -> ! {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
llvm_asm!("");
//~^ WARN LLVM-style inline assembly is unsupported in naked functions
//~| WARN this was previously accepted
core::hint::unreachable_unchecked();
}
#[naked]
unsafe extern "C" fn invalid_options() {
asm!("", options(nomem, preserves_flags, noreturn));
//~^ WARN asm options unsupported in naked functions: `nomem`, `preserves_flags`
//~| WARN this was previously accepted
}
#[naked]
unsafe extern "C" fn invalid_options_continued() {
asm!("", options(readonly, nostack), options(pure));
//~^ ERROR asm with `pure` option must have at least one output
//~| WARN asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
//~| WARN this was previously accepted
//~| WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
}
#[naked]
pub unsafe fn default_abi() {
//~^ WARN Rust ABI is unsupported in naked functions
//~| WARN this was previously accepted
asm!("", options(noreturn));
}
#[naked]
pub unsafe extern "Rust" fn rust_abi() {
//~^ WARN Rust ABI is unsupported in naked functions
//~| WARN this was previously accepted
asm!("", options(noreturn));
}
#[naked]
pub extern "C" fn valid_a<T>() -> T {
unsafe { asm!("", options(noreturn)); }
}
#[naked]
pub extern "C" fn valid_b() {
unsafe { { {
asm!("", options(noreturn)); ; ; ;
} ; } ; }
}
#[naked]
pub unsafe extern "C" fn valid_c() {
asm!("", options(noreturn));
}
#[cfg(target_arch = "x86_64")]
#[naked]
pub unsafe extern "C" fn valid_att_syntax() {
asm!("", options(noreturn, att_syntax));
}

View File

@ -0,0 +1,300 @@
error: asm with `pure` option must have at least one output
--> $DIR/naked-functions.rs:126:14
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:13:5
|
LL | mut a: u32,
| ^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:15:5
|
LL | &b: &i32,
| ^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:17:6
|
LL | (None | Some(_)): Option<std::ptr::NonNull<u8>>,
| ^^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:19:5
|
LL | P { x, y }: P,
| ^^^^^^^^^^
error: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:29:5
|
LL | a + 1
| ^
|
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:26:1
|
LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
LL | |
LL | |
LL | | a + 1
| | ----- non-asm is unsupported in naked functions
LL | |
LL | | }
| |_^
|
= note: `#[warn(unsupported_naked_functions)]` on by default
= 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: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:35:31
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^
|
= help: follow the calling convention in asm block to use parameters
warning: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:35:23
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^^^^^^^^^
|
= 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 must contain a single asm block
--> $DIR/naked-functions.rs:42:1
|
LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
LL | |
LL | |
LL | | (|| a + 1)()
| | ------------ non-asm is unsupported in naked functions
LL | | }
| |_^
|
= 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: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:62:10
|
LL | in(reg) a,
| ^^^^^^^^^
...
LL | inlateout(reg) b,
| ^^^^^^^^^^^^^^^^
LL | inout(reg) c,
| ^^^^^^^^^^^^
LL | lateout(reg) d,
| ^^^^^^^^^^^^^^
LL | out(reg) e,
| ^^^^^^^^^^
|
= 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: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:59:5
|
LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
LL | |
LL | |
LL | | in(reg) a,
... |
LL | | sym G,
LL | | );
| |______^
|
= 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 must contain a single asm block
--> $DIR/naked-functions.rs:49:1
|
LL | / pub unsafe extern "C" fn unsupported_operands() {
LL | |
LL | |
LL | | let mut a = 0usize;
| | ------------------- non-asm is unsupported in naked functions
LL | | let mut b = 0usize;
| | ------------------- non-asm is unsupported in naked functions
LL | | let mut c = 0usize;
| | ------------------- non-asm is unsupported in naked functions
LL | | let mut d = 0usize;
| | ------------------- non-asm is unsupported in naked functions
LL | | let mut e = 0usize;
| | ------------------- non-asm is unsupported in naked functions
... |
LL | | );
LL | | }
| |_^
|
= 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 must contain a single asm block
--> $DIR/naked-functions.rs:75:1
|
LL | / pub extern "C" fn missing_assembly() {
LL | |
LL | |
LL | | }
| |_^
|
= 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: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:84:5
|
LL | asm!("");
| ^^^^^^^^^
|
= 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: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:87:5
|
LL | asm!("");
| ^^^^^^^^^
|
= 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: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:90:5
|
LL | asm!("");
| ^^^^^^^^^
|
= 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 must contain a single asm block
--> $DIR/naked-functions.rs:81:1
|
LL | / pub extern "C" fn too_many_asm_blocks() {
LL | |
LL | |
LL | | asm!("");
... |
LL | | asm!("");
| | --------- multiple asm blocks are unsupported in naked functions
... |
LL | | asm!("");
| | --------- multiple asm blocks are unsupported in naked functions
... |
LL | | asm!("", options(noreturn));
| | ---------------------------- multiple asm blocks are unsupported in naked functions
LL | | }
| |_^
|
= 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: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:101:11
|
LL | *&y
| ^
|
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:98:5
|
LL | / pub extern "C" fn inner(y: usize) -> usize {
LL | |
LL | |
LL | | *&y
| | --- non-asm is unsupported in naked functions
LL | |
LL | | }
| |_____^
|
= 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: the LLVM-style inline assembly is unsupported in naked functions
--> $DIR/naked-functions.rs:111:5
|
LL | llvm_asm!("");
| ^^^^^^^^^^^^^^
|
= 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>
= help: use the new asm! syntax specified in RFC 2873
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:108:1
|
LL | / unsafe extern "C" fn llvm() -> ! {
LL | |
LL | |
LL | | llvm_asm!("");
... |
LL | | core::hint::unreachable_unchecked();
| | ------------------------------------ non-asm is unsupported in naked functions
LL | | }
| |_^
|
= 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: asm options unsupported in naked functions: `nomem`, `preserves_flags`
--> $DIR/naked-functions.rs:119:5
|
LL | asm!("", options(nomem, preserves_flags, noreturn));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
--> $DIR/naked-functions.rs:126:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:126:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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: Rust ABI is unsupported in naked functions
--> $DIR/naked-functions.rs:135:15
|
LL | pub unsafe fn default_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>
warning: Rust ABI is unsupported in naked functions
--> $DIR/naked-functions.rs:142:29
|
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

View File

@ -1,51 +0,0 @@
// Check that use of function parameters is validate in naked functions.
//
// ignore-wasm32 asm unsupported
#![feature(asm)]
#![feature(naked_functions)]
#![feature(or_patterns)]
#![crate_type = "lib"]
#[repr(C)]
pub struct P { x: u8, y: u16 }
#[naked]
pub unsafe extern "C" fn f(
mut a: u32,
//~^ ERROR patterns not allowed in naked function parameters
&b: &i32,
//~^ ERROR patterns not allowed in naked function parameters
(None | Some(_)): Option<std::ptr::NonNull<u8>>,
//~^ ERROR patterns not allowed in naked function parameters
P { x, y }: P,
//~^ ERROR patterns not allowed in naked function parameters
) {
asm!("", options(noreturn))
}
#[naked]
pub unsafe extern "C" fn inc(a: u32) -> u32 {
a + 1
//~^ ERROR use of parameters not allowed inside naked functions
}
#[naked]
pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
asm!("/* {0} */", in(reg) a, options(noreturn));
//~^ ERROR use of parameters not allowed inside naked functions
}
#[naked]
pub unsafe extern "C" fn sum(x: u32, y: u32) -> u32 {
// FIXME: Should be detected by asm-only check.
(|| { x + y})()
}
pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
#[naked]
pub extern "C" fn inner(y: usize) -> usize {
*&y
//~^ ERROR use of parameters not allowed inside naked functions
}
inner
}

View File

@ -1,44 +0,0 @@
error: patterns not allowed in naked function parameters
--> $DIR/naked-params.rs:14:5
|
LL | mut a: u32,
| ^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-params.rs:16:5
|
LL | &b: &i32,
| ^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-params.rs:18:6
|
LL | (None | Some(_)): Option<std::ptr::NonNull<u8>>,
| ^^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-params.rs:20:5
|
LL | P { x, y }: P,
| ^^^^^^^^^^
error: use of parameters not allowed inside naked functions
--> $DIR/naked-params.rs:28:5
|
LL | a + 1
| ^
error: use of parameters not allowed inside naked functions
--> $DIR/naked-params.rs:34:31
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^
error: use of parameters not allowed inside naked functions
--> $DIR/naked-params.rs:47:11
|
LL | *&y
| ^
error: aborting due to 7 previous errors

View File

@ -1,11 +1,15 @@
#[naked]
//~^ the `#[naked]` attribute is an experimental feature
fn naked() {}
#![feature(asm)]
#[naked]
//~^ the `#[naked]` attribute is an experimental feature
fn naked_2() -> isize {
0
extern "C" fn naked() {
asm!("", options(noreturn))
}
#[naked]
//~^ the `#[naked]` attribute is an experimental feature
extern "C" fn naked_2() -> isize {
asm!("", options(noreturn))
}
fn main() {}

View File

@ -1,5 +1,5 @@
error[E0658]: the `#[naked]` attribute is an experimental feature
--> $DIR/feature-gate-naked_functions.rs:1:1
--> $DIR/feature-gate-naked_functions.rs:3:1
|
LL | #[naked]
| ^^^^^^^^
@ -8,7 +8,7 @@ LL | #[naked]
= help: add `#![feature(naked_functions)]` to the crate attributes to enable
error[E0658]: the `#[naked]` attribute is an experimental feature
--> $DIR/feature-gate-naked_functions.rs:5:1
--> $DIR/feature-gate-naked_functions.rs:9:1
|
LL | #[naked]
| ^^^^^^^^

View File

@ -1,15 +1,19 @@
#![feature(naked_functions)]
#![feature(asm, naked_functions)]
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
#[naked]
fn f() {}
extern "C" fn f() {
asm!("", options(noreturn));
}
struct S;
impl S {
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
#[naked]
fn g() {}
extern "C" fn g() {
asm!("", options(noreturn));
}
}
fn main() {}

View File

@ -5,7 +5,7 @@ LL | #[track_caller]
| ^^^^^^^^^^^^^^^
error[E0736]: cannot use `#[track_caller]` with `#[naked]`
--> $DIR/error-with-naked.rs:10:5
--> $DIR/error-with-naked.rs:12:5
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^