improve error message when #[naked]
is used with #[inline]
This commit is contained in:
parent
ceec6ddf9e
commit
4bd36324b6
8 changed files with 104 additions and 111 deletions
|
@ -69,9 +69,6 @@ passes_break_non_loop =
|
||||||
.suggestion = use `break` on its own without a value inside this `{$kind}` loop
|
.suggestion = use `break` on its own without a value inside this `{$kind}` loop
|
||||||
.break_expr_suggestion = alternatively, you might have meant to use the available loop label
|
.break_expr_suggestion = alternatively, you might have meant to use the available loop label
|
||||||
|
|
||||||
passes_cannot_inline_naked_function =
|
|
||||||
naked functions cannot be inlined
|
|
||||||
|
|
||||||
passes_cannot_stabilize_deprecated =
|
passes_cannot_stabilize_deprecated =
|
||||||
an API can't be stabilized after it is deprecated
|
an API can't be stabilized after it is deprecated
|
||||||
.label = invalid version
|
.label = invalid version
|
||||||
|
@ -485,6 +482,11 @@ passes_naked_functions_asm_block =
|
||||||
passes_naked_functions_asm_options =
|
passes_naked_functions_asm_options =
|
||||||
asm options unsupported in naked functions: {$unsupported_options}
|
asm options unsupported in naked functions: {$unsupported_options}
|
||||||
|
|
||||||
|
passes_naked_functions_codegen_attribute =
|
||||||
|
cannot use additional code generation attributes with `#[naked]`
|
||||||
|
.label = this attribute is incompatible with `#[naked]`
|
||||||
|
.label2 = function marked with `#[naked]` here
|
||||||
|
|
||||||
passes_naked_functions_must_use_noreturn =
|
passes_naked_functions_must_use_noreturn =
|
||||||
asm in naked functions must use `noreturn` option
|
asm in naked functions must use `noreturn` option
|
||||||
.suggestion = consider specifying that the asm block is responsible for returning from the function
|
.suggestion = consider specifying that the asm block is responsible for returning from the function
|
||||||
|
@ -492,9 +494,6 @@ passes_naked_functions_must_use_noreturn =
|
||||||
passes_naked_functions_operands =
|
passes_naked_functions_operands =
|
||||||
only `const` and `sym` operands are supported in naked functions
|
only `const` and `sym` operands are supported in naked functions
|
||||||
|
|
||||||
passes_naked_tracked_caller =
|
|
||||||
cannot use `#[track_caller]` with `#[naked]`
|
|
||||||
|
|
||||||
passes_no_link =
|
passes_no_link =
|
||||||
attribute should be applied to an `extern crate` item
|
attribute should be applied to an `extern crate` item
|
||||||
.label = not an `extern crate` item
|
.label = not an `extern crate` item
|
||||||
|
|
|
@ -155,7 +155,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
[sym::rustc_std_internal_symbol] => {
|
[sym::rustc_std_internal_symbol] => {
|
||||||
self.check_rustc_std_internal_symbol(attr, span, target)
|
self.check_rustc_std_internal_symbol(attr, span, target)
|
||||||
}
|
}
|
||||||
[sym::naked] => self.check_naked(hir_id, attr, span, target),
|
[sym::naked] => self.check_naked(hir_id, attr, span, target, attrs),
|
||||||
[sym::rustc_never_returns_null_ptr] => {
|
[sym::rustc_never_returns_null_ptr] => {
|
||||||
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
|
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
|
||||||
}
|
}
|
||||||
|
@ -410,12 +410,33 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if `#[naked]` is applied to a function definition.
|
/// Checks if `#[naked]` is applied to a function definition.
|
||||||
fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
|
fn check_naked(
|
||||||
|
&self,
|
||||||
|
hir_id: HirId,
|
||||||
|
attr: &Attribute,
|
||||||
|
span: Span,
|
||||||
|
target: Target,
|
||||||
|
attrs: &[Attribute],
|
||||||
|
) -> bool {
|
||||||
|
const FORBIDDEN: [rustc_span::Symbol; 3] =
|
||||||
|
[sym::track_caller, sym::inline, sym::target_feature];
|
||||||
|
|
||||||
|
for other_attr in attrs {
|
||||||
|
if FORBIDDEN.into_iter().any(|name| other_attr.has_name(name)) {
|
||||||
|
self.dcx().emit_err(errors::NakedFunctionCodegenAttribute {
|
||||||
|
span: other_attr.span,
|
||||||
|
naked_span: attr.span,
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match target {
|
match target {
|
||||||
Target::Fn
|
Target::Fn
|
||||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
|
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
|
||||||
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
|
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
|
||||||
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
|
// `#[naked]` attribute with just a lint, because we previously
|
||||||
// erroneously allowed it and some crates used it accidentally, to be compatible
|
// erroneously allowed it and some crates used it accidentally, to be compatible
|
||||||
// with crates depending on them, we can't throw an error here.
|
// with crates depending on them, we can't throw an error here.
|
||||||
Target::Field | Target::Arm | Target::MacroDef => {
|
Target::Field | Target::Arm | Target::MacroDef => {
|
||||||
|
@ -488,7 +509,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
|
/// Checks if a `#[track_caller]` is applied to a function. Returns `true` if valid.
|
||||||
fn check_track_caller(
|
fn check_track_caller(
|
||||||
&self,
|
&self,
|
||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
|
@ -498,10 +519,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
target: Target,
|
target: Target,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match target {
|
match target {
|
||||||
_ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => {
|
|
||||||
self.dcx().emit_err(errors::NakedTrackedCaller { attr_span });
|
|
||||||
false
|
|
||||||
}
|
|
||||||
Target::Fn => {
|
Target::Fn => {
|
||||||
// `#[track_caller]` is not valid on weak lang items because they are called via
|
// `#[track_caller]` is not valid on weak lang items because they are called via
|
||||||
// `extern` declarations and `#[track_caller]` would alter their ABI.
|
// `extern` declarations and `#[track_caller]` would alter their ABI.
|
||||||
|
|
|
@ -79,13 +79,6 @@ pub struct AttrShouldBeAppliedToFn {
|
||||||
pub on_crate: bool,
|
pub on_crate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(passes_naked_tracked_caller, code = E0736)]
|
|
||||||
pub struct NakedTrackedCaller {
|
|
||||||
#[primary_span]
|
|
||||||
pub attr_span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_should_be_applied_to_fn, code = E0739)]
|
#[diag(passes_should_be_applied_to_fn, code = E0739)]
|
||||||
pub struct TrackedCallerWrongLocation {
|
pub struct TrackedCallerWrongLocation {
|
||||||
|
@ -1124,13 +1117,6 @@ pub struct UnlabeledCfInWhileCondition<'a> {
|
||||||
pub cf_type: &'a str,
|
pub cf_type: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(passes_cannot_inline_naked_function)]
|
|
||||||
pub struct CannotInlineNakedFunction {
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(passes_undefined_naked_function_abi)]
|
#[diag(passes_undefined_naked_function_abi)]
|
||||||
pub struct UndefinedNakedFunctionAbi;
|
pub struct UndefinedNakedFunctionAbi;
|
||||||
|
@ -1196,6 +1182,16 @@ pub struct NakedFunctionsMustUseNoreturn {
|
||||||
pub last_span: Span,
|
pub last_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(passes_naked_functions_codegen_attribute, code = E0736)]
|
||||||
|
pub struct NakedFunctionCodegenAttribute {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[label(passes_label2)]
|
||||||
|
pub naked_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_attr_only_in_functions)]
|
#[diag(passes_attr_only_in_functions)]
|
||||||
pub struct AttrOnlyInFunctions {
|
pub struct AttrOnlyInFunctions {
|
||||||
|
|
|
@ -14,9 +14,8 @@ use rustc_span::Span;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
|
NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn,
|
||||||
NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
|
NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi,
|
||||||
UndefinedNakedFunctionAbi,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
|
@ -53,15 +52,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||||
check_no_patterns(tcx, body.params);
|
check_no_patterns(tcx, body.params);
|
||||||
check_no_parameters_use(tcx, body);
|
check_no_parameters_use(tcx, body);
|
||||||
check_asm(tcx, def_id, body);
|
check_asm(tcx, def_id, body);
|
||||||
check_inline(tcx, def_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that the function isn't inlined.
|
|
||||||
fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|
||||||
let attrs = tcx.get_attrs(def_id, sym::inline);
|
|
||||||
for attr in attrs {
|
|
||||||
tcx.dcx().emit_err(CannotInlineNakedFunction { span: attr.span });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
tests/ui/asm/naked-functions-inline.rs
Normal file
31
tests/ui/asm/naked-functions-inline.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//@ needs-asm-support
|
||||||
|
#![feature(naked_functions)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
use std::arch::asm;
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern "C" fn inline_none() {
|
||||||
|
asm!("", options(noreturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
#[inline]
|
||||||
|
//~^ ERROR [E0736]
|
||||||
|
pub unsafe extern "C" fn inline_hint() {
|
||||||
|
asm!("", options(noreturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
#[inline(always)]
|
||||||
|
//~^ ERROR [E0736]
|
||||||
|
pub unsafe extern "C" fn inline_always() {
|
||||||
|
asm!("", options(noreturn));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
#[inline(never)]
|
||||||
|
//~^ ERROR [E0736]
|
||||||
|
pub unsafe extern "C" fn inline_never() {
|
||||||
|
asm!("", options(noreturn));
|
||||||
|
}
|
27
tests/ui/asm/naked-functions-inline.stderr
Normal file
27
tests/ui/asm/naked-functions-inline.stderr
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
error[E0736]: cannot use additional code generation attributes with `#[naked]`
|
||||||
|
--> $DIR/naked-functions-inline.rs:13:1
|
||||||
|
|
|
||||||
|
LL | #[naked]
|
||||||
|
| -------- function marked with `#[naked]` here
|
||||||
|
LL | #[inline]
|
||||||
|
| ^^^^^^^^^ this attribute is incompatible with `#[naked]`
|
||||||
|
|
||||||
|
error[E0736]: cannot use additional code generation attributes with `#[naked]`
|
||||||
|
--> $DIR/naked-functions-inline.rs:20:1
|
||||||
|
|
|
||||||
|
LL | #[naked]
|
||||||
|
| -------- function marked with `#[naked]` here
|
||||||
|
LL | #[inline(always)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]`
|
||||||
|
|
||||||
|
error[E0736]: cannot use additional code generation attributes with `#[naked]`
|
||||||
|
--> $DIR/naked-functions-inline.rs:27:1
|
||||||
|
|
|
||||||
|
LL | #[naked]
|
||||||
|
| -------- function marked with `#[naked]` here
|
||||||
|
LL | #[inline(never)]
|
||||||
|
| ^^^^^^^^^^^^^^^^ this attribute is incompatible with `#[naked]`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0736`.
|
|
@ -168,37 +168,6 @@ pub unsafe extern "C" fn inline_none() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
#[inline]
|
|
||||||
//~^ ERROR naked functions cannot be inlined
|
|
||||||
pub unsafe extern "C" fn inline_hint() {
|
|
||||||
asm!("", options(noreturn));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[naked]
|
|
||||||
#[inline(always)]
|
|
||||||
//~^ ERROR naked functions cannot be inlined
|
|
||||||
pub unsafe extern "C" fn inline_always() {
|
|
||||||
asm!("", options(noreturn));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[naked]
|
|
||||||
#[inline(never)]
|
|
||||||
//~^ ERROR naked functions cannot be inlined
|
|
||||||
pub unsafe extern "C" fn inline_never() {
|
|
||||||
asm!("", options(noreturn));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[naked]
|
|
||||||
#[inline]
|
|
||||||
//~^ ERROR naked functions cannot be inlined
|
|
||||||
#[inline(always)]
|
|
||||||
//~^ ERROR naked functions cannot be inlined
|
|
||||||
#[inline(never)]
|
|
||||||
//~^ ERROR naked functions cannot be inlined
|
|
||||||
pub unsafe extern "C" fn inline_all() {
|
|
||||||
asm!("", options(noreturn));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
|
pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
|
||||||
compile_error!("this is a user specified error")
|
compile_error!("this is a user specified error")
|
||||||
|
|
|
@ -5,19 +5,19 @@ LL | asm!("", options(readonly, nostack), options(pure));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this is a user specified error
|
error: this is a user specified error
|
||||||
--> $DIR/naked-functions.rs:204:5
|
--> $DIR/naked-functions.rs:173:5
|
||||||
|
|
|
|
||||||
LL | compile_error!("this is a user specified error")
|
LL | compile_error!("this is a user specified error")
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this is a user specified error
|
error: this is a user specified error
|
||||||
--> $DIR/naked-functions.rs:210:5
|
--> $DIR/naked-functions.rs:179:5
|
||||||
|
|
|
|
||||||
LL | compile_error!("this is a user specified error");
|
LL | compile_error!("this is a user specified error");
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: asm template must be a string literal
|
error: asm template must be a string literal
|
||||||
--> $DIR/naked-functions.rs:217:10
|
--> $DIR/naked-functions.rs:186:10
|
||||||
|
|
|
|
||||||
LL | asm!(invalid_syntax)
|
LL | asm!(invalid_syntax)
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
@ -249,42 +249,6 @@ warning: Rust ABI is unsupported in naked functions
|
||||||
LL | pub unsafe fn rust_abi() {
|
LL | pub unsafe fn rust_abi() {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: naked functions cannot be inlined
|
error: aborting due to 27 previous errors; 2 warnings emitted
|
||||||
--> $DIR/naked-functions.rs:171:1
|
|
||||||
|
|
|
||||||
LL | #[inline]
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: naked functions cannot be inlined
|
|
||||||
--> $DIR/naked-functions.rs:178:1
|
|
||||||
|
|
|
||||||
LL | #[inline(always)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: naked functions cannot be inlined
|
|
||||||
--> $DIR/naked-functions.rs:185:1
|
|
||||||
|
|
|
||||||
LL | #[inline(never)]
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: naked functions cannot be inlined
|
|
||||||
--> $DIR/naked-functions.rs:192:1
|
|
||||||
|
|
|
||||||
LL | #[inline]
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
||||||
error: naked functions cannot be inlined
|
|
||||||
--> $DIR/naked-functions.rs:194:1
|
|
||||||
|
|
|
||||||
LL | #[inline(always)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: naked functions cannot be inlined
|
|
||||||
--> $DIR/naked-functions.rs:196:1
|
|
||||||
|
|
|
||||||
LL | #[inline(never)]
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 33 previous errors; 2 warnings emitted
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0787`.
|
For more information about this error, try `rustc --explain E0787`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue