diff options
| -rw-r--r-- | compiler/rustc_attr_data_structures/src/attributes.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_attr_data_structures/src/encode_cross_crate.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/messages.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/context.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/session_diagnostics.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/messages.ftl | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/errors.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 10 | ||||
| -rw-r--r-- | src/librustdoc/clean/types.rs | 5 | ||||
| -rw-r--r-- | tests/ui/lint/unused/unused-attr-duplicate.stderr | 26 |
13 files changed, 84 insertions, 46 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index dc3598bcc36..d755afad59f 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -231,6 +231,14 @@ pub enum AttributeKind { /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html). DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol }, + /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute). + ExportName { + /// The name to export this item with. + /// It may not contain \0 bytes as it will be converted to a null-terminated string. + name: Symbol, + span: Span, + }, + /// Represents `#[inline]` and `#[rustc_force_inline]`. Inline(InlineAttr, Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index e41dd8bde8f..d4402f4e2e6 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -22,6 +22,7 @@ impl AttributeKind { ConstStabilityIndirect => No, Deprecation { .. } => Yes, DocComment { .. } => Yes, + ExportName { .. } => Yes, Inline(..) => No, MacroTransparency(..) => Yes, Repr(..) => No, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 2bb27ede860..39652335f55 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -93,9 +93,12 @@ attr_parsing_naked_functions_incompatible_attribute = attribute incompatible with `#[unsafe(naked)]` .label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]` .naked_attribute = function marked with `#[unsafe(naked)]` here + attr_parsing_non_ident_feature = 'feature' is not an identifier +attr_parsing_null_on_export = `export_name` may not contain null characters + attr_parsing_repr_ident = meta item in `repr` must be an identifier diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index eadf8657a0f..5a849e79cc3 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -6,7 +6,7 @@ use rustc_span::{Span, Symbol, sym}; use super::{AcceptMapping, AttributeOrder, AttributeParser, OnDuplicate, SingleAttributeParser}; use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::ArgParser; -use crate::session_diagnostics::NakedFunctionIncompatibleAttribute; +use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport}; pub(crate) struct OptimizeParser; @@ -59,6 +59,33 @@ impl<S: Stage> SingleAttributeParser<S> for ColdParser { } } +pub(crate) struct ExportNameParser; + +impl<S: Stage> SingleAttributeParser<S> for ExportNameParser { + const PATH: &[rustc_span::Symbol] = &[sym::export_name]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + let Some(nv) = args.name_value() else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + let Some(name) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + if name.as_str().contains('\0') { + // `#[export_name = ...]` will be converted to a null-terminated string, + // so it may not contain any null characters. + cx.emit_err(NullOnExport { span: cx.attr_span }); + return None; + } + Some(AttributeKind::ExportName { name, span: cx.attr_span }) + } +} + #[derive(Default)] pub(crate) struct NakedParser { span: Option<Span>, diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 6ca5c64e0bc..83e3c75dedb 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -16,7 +16,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; use crate::attributes::codegen_attrs::{ - ColdParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, + ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; @@ -117,6 +117,7 @@ attribute_parsers!( Single<ConstContinueParser>, Single<ConstStabilityIndirectParser>, Single<DeprecationParser>, + Single<ExportNameParser>, Single<InlineParser>, Single<LoopMatchParser>, Single<MayDangleParser>, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 263b323e3eb..7cfce579979 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -446,6 +446,13 @@ pub(crate) struct MustUseIllFormedAttributeInput { } #[derive(Diagnostic)] +#[diag(attr_parsing_null_on_export, code = E0648)] +pub(crate) struct NullOnExport { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(attr_parsing_stability_outside_std, code = E0734)] pub(crate) struct StabilityOutsideStd { #[primary_span] diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index b2e86414d90..4f2c832a3a4 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -230,8 +230,6 @@ codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} codegen_ssa_no_saved_object_file = cached cgu {$cgu_name} should have an object file, but doesn't -codegen_ssa_null_on_export = `export_name` may not contain null characters - codegen_ssa_out_of_range_integer = integer value out of range .label = value must be between `0` and `255` diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 7bd27eb3ef1..a6b3dfec4dc 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -119,6 +119,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { .max(); } AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, + AttributeKind::ExportName { name, span: attr_span } => { + codegen_fn_attrs.export_name = Some(*name); + mixed_export_name_no_mangle_lint_state.track_export_name(*attr_span); + } AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align), AttributeKind::NoMangle(attr_span) => { @@ -223,17 +227,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, - sym::export_name => { - if let Some(s) = attr.value_str() { - if s.as_str().contains('\0') { - // `#[export_name = ...]` will be converted to a null-terminated string, - // so it may not contain any null characters. - tcx.dcx().emit_err(errors::NullOnExport { span: attr.span() }); - } - codegen_fn_attrs.export_name = Some(s); - mixed_export_name_no_mangle_lint_state.track_export_name(attr.span()); - } - } sym::target_feature => { let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else { tcx.dcx().span_delayed_bug(attr.span(), "target_feature applied to non-fn"); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index caac0f83f9d..315d9c92ab0 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -141,13 +141,6 @@ pub(crate) struct RequiresRustAbi { } #[derive(Diagnostic)] -#[diag(codegen_ssa_null_on_export, code = E0648)] -pub(crate) struct NullOnExport { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(codegen_ssa_unsupported_instruction_set, code = E0779)] pub(crate) struct UnsupportedInstructionSet { #[primary_span] diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5bbe69c8d65..172f3372483 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -977,9 +977,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { }; match it.kind { hir::ItemKind::Fn { generics, .. } => { - if let Some(attr_span) = attr::find_by_name(attrs, sym::export_name) - .map(|at| at.span()) - .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span)) + if let Some(attr_span) = + find_attr!(attrs, AttributeKind::ExportName {span, ..} => *span) + .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span)) { check_no_mangle_on_generic_fn(attr_span, None, generics, it.span); } @@ -1010,9 +1010,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { for it in *items { if let hir::AssocItemKind::Fn { .. } = it.kind { let attrs = cx.tcx.hir_attrs(it.id.hir_id()); - if let Some(attr_span) = attr::find_by_name(attrs, sym::export_name) - .map(|at| at.span()) - .or_else(|| find_attr!(attrs, AttributeKind::NoMangle(span) => *span)) + if let Some(attr_span) = + find_attr!(attrs, AttributeKind::ExportName {span, ..} => *span) + .or_else( + || find_attr!(attrs, AttributeKind::NoMangle(span) => *span), + ) { check_no_mangle_on_generic_fn( attr_span, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 99c220d946e..7c985fa9f03 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -169,6 +169,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::Cold(attr_span)) => { self.check_cold(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::ExportName { span: attr_span, .. }) => { + self.check_export_name(hir_id, *attr_span, span, target) + } Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { self.check_align(span, target, *align, *repr_span) } @@ -223,7 +226,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &mut doc_aliases, ), [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target), - [sym::export_name, ..] => self.check_export_name(hir_id, attr, span, target), [sym::rustc_layout_scalar_valid_range_start, ..] | [sym::rustc_layout_scalar_valid_range_end, ..] => { self.check_rustc_layout_scalar_valid_range(attr, span, target) @@ -1653,7 +1655,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[export_name]` is applied to a function or static. - fn check_export_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_export_name(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { match target { Target::Static | Target::Fn => {} Target::Method(..) if self.is_impl_item(hir_id) => {} @@ -1662,10 +1664,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // 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 => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "export_name"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "export_name"); } _ => { - self.dcx().emit_err(errors::ExportName { attr_span: attr.span(), span }); + self.dcx().emit_err(errors::ExportName { attr_span, span }); } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 69899539b45..3cac55493f0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -755,8 +755,11 @@ impl Item { .filter_map(|attr| { // NoMangle is special cased, as it appears in HTML output, and we want to show it in source form, not HIR printing. // It is also used by cargo-semver-checks. - if matches!(attr, hir::Attribute::Parsed(AttributeKind::NoMangle(..))) { + if let hir::Attribute::Parsed(AttributeKind::NoMangle(..)) = attr { Some("#[no_mangle]".to_string()) + } else if let hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) = attr + { + Some(format!("#[export_name = \"{name}\"]")) } else if is_json { match attr { // rustdoc-json stores this in `Item::deprecation`, so we diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index df6cada6b06..3a520ffcb3d 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -90,19 +90,6 @@ LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:92:1 - | -LL | #[export_name = "exported_symbol_name"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:94:1 - | -LL | #[export_name = "exported_symbol_name2"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -error: unused attribute --> $DIR/unused-attr-duplicate.rs:102:1 | LL | #[used] @@ -278,6 +265,19 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error: unused attribute + --> $DIR/unused-attr-duplicate.rs:92:1 + | +LL | #[export_name = "exported_symbol_name"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:94:1 + | +LL | #[export_name = "exported_symbol_name2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute --> $DIR/unused-attr-duplicate.rs:98:1 | LL | #[no_mangle] |
