diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index fb984912b1936..b913518c191db 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -403,6 +403,18 @@ pub(crate) struct InvalidTarget { #[derive(Subdiagnostic)] pub(crate) enum InvalidTargetHelp { + #[multipart_suggestion( + "did you mean to use `#[export_name]`?", + applicability = "maybe-incorrect" + )] + UseExportName { + #[suggestion_part(code = "unsafe(")] + unsafe_open: Option, + #[suggestion_part(code = "export_name")] + name: Span, + #[suggestion_part(code = ")")] + unsafe_close: Option, + }, #[help("use `#[rustc_align(...)]` instead")] UseRustcAlign, #[help("use `#[rustc_align_static(...)]` instead")] diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 461820626f2ad..6b0d1b094ca0f 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use rustc_ast::AttrStyle; +use rustc_ast::{AttrStyle, Safety}; use rustc_errors::{DiagArgValue, MultiSpan, StashKey}; use rustc_feature::Features; use rustc_hir::attrs::AttributeKind; @@ -187,6 +187,15 @@ impl<'sess> AttributeParser<'sess> { cx: &AcceptContext<'_, '_>, ) -> Option { match &*cx.attr_path.segments { + [sym::link_name] if cx.target == Target::Static => { + let needs_unsafe_wrapper = matches!(cx.attr_safety, Safety::Default); + + Some(InvalidTargetHelp::UseExportName { + unsafe_open: needs_unsafe_wrapper.then(|| cx.inner_span.shrink_to_lo()), + name: cx.attr_path.span, + unsafe_close: needs_unsafe_wrapper.then(|| cx.inner_span.shrink_to_hi()), + }) + } [sym::repr] if attribute_args == "(align(...))" => match cx.target { Target::Fn | Target::Method(..) if cx.features().fn_align() => { Some(InvalidTargetHelp::UseRustcAlign) diff --git a/tests/ui/attributes/link-name-on-static.rs b/tests/ui/attributes/link-name-on-static.rs new file mode 100644 index 0000000000000..85082d3a43fb4 --- /dev/null +++ b/tests/ui/attributes/link-name-on-static.rs @@ -0,0 +1,17 @@ +#[link_name = "VALUE"] +//~^ WARN the `link_name` attribute cannot be used on statics +//~| WARN this was previously accepted by the compiler but is being phased out +static VALUE_DEFINITION: u8 = 0; + +#[unsafe(link_name = "UNSAFE_VALUE")] +//~^ ERROR `link_name` is not an unsafe attribute +//~| WARN the `link_name` attribute cannot be used on statics +//~| WARN this was previously accepted by the compiler but is being phased out +static UNSAFE_VALUE_DEFINITION: u8 = 0; + +unsafe extern "C" { + #[link_name = "VALUE"] + static VALUE_DECLARATION: u8; +} + +fn main() {} diff --git a/tests/ui/attributes/link-name-on-static.stderr b/tests/ui/attributes/link-name-on-static.stderr new file mode 100644 index 0000000000000..2d768acd51bfb --- /dev/null +++ b/tests/ui/attributes/link-name-on-static.stderr @@ -0,0 +1,39 @@ +error: `link_name` is not an unsafe attribute + --> $DIR/link-name-on-static.rs:6:3 + | +LL | #[unsafe(link_name = "UNSAFE_VALUE")] + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes + +warning: the `link_name` attribute cannot be used on statics + --> $DIR/link-name-on-static.rs:1:3 + | +LL | #[link_name = "VALUE"] + | ^^^^^^^^^ + | + = help: the `link_name` attribute can be applied to foreign functions and foreign statics + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: requested on the command line with `-W unused-attributes` +help: did you mean to use `#[export_name]`? + | +LL - #[link_name = "VALUE"] +LL + #[unsafe(export_name = "VALUE")] + | + +warning: the `link_name` attribute cannot be used on statics + --> $DIR/link-name-on-static.rs:6:10 + | +LL | #[unsafe(link_name = "UNSAFE_VALUE")] + | ^^^^^^^^^ + | + = help: the `link_name` attribute can be applied to foreign functions and foreign statics + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +help: did you mean to use `#[export_name]`? + | +LL - #[unsafe(link_name = "UNSAFE_VALUE")] +LL + #[unsafe(export_name = "UNSAFE_VALUE")] + | + +error: aborting due to 1 previous error; 2 warnings emitted +