1
Fork 0

improve error message when #[naked] is used with #[inline]

This commit is contained in:
Folkert 2024-07-16 23:03:13 +02:00
parent ceec6ddf9e
commit 4bd36324b6
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
8 changed files with 104 additions and 111 deletions

View file

@ -155,7 +155,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::rustc_std_internal_symbol] => {
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] => {
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.
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 {
Target::Fn
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
// 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
// with crates depending on them, we can't throw an error here.
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(
&self,
hir_id: HirId,
@ -498,10 +519,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
target: Target,
) -> bool {
match target {
_ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => {
self.dcx().emit_err(errors::NakedTrackedCaller { attr_span });
false
}
Target::Fn => {
// `#[track_caller]` is not valid on weak lang items because they are called via
// `extern` declarations and `#[track_caller]` would alter their ABI.

View file

@ -79,13 +79,6 @@ pub struct AttrShouldBeAppliedToFn {
pub on_crate: bool,
}
#[derive(Diagnostic)]
#[diag(passes_naked_tracked_caller, code = E0736)]
pub struct NakedTrackedCaller {
#[primary_span]
pub attr_span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_fn, code = E0739)]
pub struct TrackedCallerWrongLocation {
@ -1124,13 +1117,6 @@ pub struct UnlabeledCfInWhileCondition<'a> {
pub cf_type: &'a str,
}
#[derive(Diagnostic)]
#[diag(passes_cannot_inline_naked_function)]
pub struct CannotInlineNakedFunction {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(passes_undefined_naked_function_abi)]
pub struct UndefinedNakedFunctionAbi;
@ -1196,6 +1182,16 @@ pub struct NakedFunctionsMustUseNoreturn {
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)]
#[diag(passes_attr_only_in_functions)]
pub struct AttrOnlyInFunctions {

View file

@ -14,9 +14,8 @@ use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use crate::errors::{
CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
UndefinedNakedFunctionAbi,
NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn,
NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi,
};
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_parameters_use(tcx, 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 });
}
}