Validate naked functions definitions
This commit is contained in:
parent
91fe548825
commit
8065dabd17
@ -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,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
169
src/test/ui/asm/naked-functions.rs
Normal file
169
src/test/ui/asm/naked-functions.rs
Normal 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));
|
||||
}
|
300
src/test/ui/asm/naked-functions.stderr
Normal file
300
src/test/ui/asm/naked-functions.stderr
Normal 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
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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]
|
||||
| ^^^^^^^^
|
||||
|
@ -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() {}
|
||||
|
@ -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]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
Loading…
x
Reference in New Issue
Block a user