Port the #[linkage] attribute to the new attribute system

This commit is contained in:
Sasha Pourcelot
2025-08-12 20:22:45 +02:00
parent 350d0ef0ec
commit d435197afc
27 changed files with 207 additions and 124 deletions

View File

@@ -11,7 +11,6 @@ use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{self as ty, TyCtxt};
@@ -26,31 +25,6 @@ use crate::target_features::{
check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr,
};
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
use rustc_middle::mir::mono::Linkage::*;
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
// applicable to variable declarations and may not really make sense for
// Rust code in the first place but allow them anyway and trust that the
// user knows what they're doing. Who knows, unanticipated use cases may pop
// up in the future.
//
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
// and don't have to be, LLVM treats them as no-ops.
match name {
"available_externally" => AvailableExternally,
"common" => Common,
"extern_weak" => ExternalWeak,
"external" => External,
"internal" => Internal,
"linkonce" => LinkOnceAny,
"linkonce_odr" => LinkOnceODR,
"weak" => WeakAny,
"weak_odr" => WeakODR,
_ => tcx.dcx().span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
}
}
/// In some cases, attributes are only valid on functions, but it's the `check_attr`
/// pass that checks that they aren't used anywhere else, rather than this module.
/// In these cases, we bail from performing further checks that are only meaningful for
@@ -103,13 +77,6 @@ fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<Instr
}
}
// FIXME(jdonszelmann): remove when linkage becomes a parsed attr
fn parse_linkage_attr(tcx: TyCtxt<'_>, did: LocalDefId, attr: &Attribute) -> Option<Linkage> {
let val = attr.value_str()?;
let linkage = linkage_by_name(tcx, did, val.as_str());
Some(linkage)
}
// FIXME(jdonszelmann): remove when no_sanitize becomes a parsed attr
fn parse_no_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<SanitizerSet> {
let list = attr.meta_item_list()?;
@@ -332,6 +299,28 @@ fn process_builtin_attrs(
AttributeKind::StdInternalSymbol(_) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
}
AttributeKind::Linkage(linkage, _) => {
let linkage = Some(*linkage);
if tcx.is_foreign_item(did) {
codegen_fn_attrs.import_linkage = linkage;
if tcx.is_mutable_static(did.into()) {
let mut diag = tcx.dcx().struct_span_err(
attr.span(),
"extern mutable statics are not allowed with `#[linkage]`",
);
diag.note(
"marking the extern static mutable would allow changing which \
symbol the static references rather than make the target of the \
symbol mutable",
);
diag.emit();
}
} else {
codegen_fn_attrs.linkage = linkage;
}
}
_ => {}
}
}
@@ -349,28 +338,6 @@ fn process_builtin_attrs(
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
sym::linkage => {
let linkage = parse_linkage_attr(tcx, did, attr);
if tcx.is_foreign_item(did) {
codegen_fn_attrs.import_linkage = linkage;
if tcx.is_mutable_static(did.into()) {
let mut diag = tcx.dcx().struct_span_err(
attr.span(),
"extern mutable statics are not allowed with `#[linkage]`",
);
diag.note(
"marking the extern static mutable would allow changing which \
symbol the static references rather than make the target of the \
symbol mutable",
);
diag.emit();
}
} else {
codegen_fn_attrs.linkage = linkage;
}
}
sym::no_sanitize => {
interesting_spans.no_sanitize = Some(attr.span());
codegen_fn_attrs.no_sanitize |=