Skip to content

Commit 134a607

Browse files
committed
Port #[link_section] to the new attribute parsing infrastructure
1 parent dddd7ab commit 134a607

File tree

13 files changed

+98
-24
lines changed

13 files changed

+98
-24
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ pub enum AttributeKind {
253253
/// Represents `#[inline]` and `#[rustc_force_inline]`.
254254
Inline(InlineAttr, Span),
255255

256+
/// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
257+
LinkSection { name: Symbol, span: Span },
258+
256259
/// Represents `#[loop_match]`.
257260
LoopMatch(Span),
258261

compiler/rustc_attr_data_structures/src/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impl AttributeKind {
2424
DocComment { .. } => Yes,
2525
ExportName { .. } => Yes,
2626
Inline(..) => No,
27+
LinkSection { .. } => No,
2728
MacroTransparency(..) => Yes,
2829
Repr(..) => No,
2930
Stability { .. } => Yes,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use rustc_attr_data_structures::AttributeKind;
2+
use rustc_attr_data_structures::AttributeKind::LinkSection;
3+
use rustc_feature::{AttributeTemplate, template};
4+
use rustc_span::{Symbol, sym};
5+
6+
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
7+
use crate::context::{AcceptContext, Stage};
8+
use crate::parser::ArgParser;
9+
10+
pub(crate) struct LinkSectionParser;
11+
12+
impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
13+
const PATH: &[Symbol] = &[sym::link_section];
14+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
15+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
16+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
17+
18+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
19+
let Some(nv) = args.name_value() else {
20+
cx.expected_name_value(cx.attr_span, None);
21+
return None;
22+
};
23+
let Some(name) = nv.value_as_str() else {
24+
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
25+
return None;
26+
};
27+
28+
Some(LinkSection { name, span: cx.attr_span })
29+
}
30+
}

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub(crate) mod codegen_attrs;
3131
pub(crate) mod confusables;
3232
pub(crate) mod deprecation;
3333
pub(crate) mod inline;
34+
pub(crate) mod link_section;
3435
pub(crate) mod lint_helpers;
3536
pub(crate) mod loop_match;
3637
pub(crate) mod must_use;

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::attributes::codegen_attrs::{
2222
use crate::attributes::confusables::ConfusablesParser;
2323
use crate::attributes::deprecation::DeprecationParser;
2424
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
25+
use crate::attributes::link_section::LinkSectionParser;
2526
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
2627
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
2728
use crate::attributes::must_use::MustUseParser;
@@ -121,6 +122,7 @@ attribute_parsers!(
121122
Single<DeprecationParser>,
122123
Single<ExportNameParser>,
123124
Single<InlineParser>,
125+
Single<LinkSectionParser>,
124126
Single<LoopMatchParser>,
125127
Single<MayDangleParser>,
126128
Single<MustUseParser>,

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
123123
}
124124
AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
125125
AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align),
126+
AttributeKind::LinkSection { name, .. } => {
127+
if name.as_str().bytes().any(|b| b == 0) {
128+
let msg = format!("illegal null byte in link_section value: `{name}`");
129+
tcx.dcx().span_err(attr.span(), msg);
130+
} else {
131+
codegen_fn_attrs.link_section = Some(*name);
132+
}
133+
}
126134
AttributeKind::NoMangle(attr_span) => {
127135
if tcx.opt_item_name(did.to_def_id()).is_some() {
128136
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
@@ -252,16 +260,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
252260
}
253261
}
254262
}
255-
sym::link_section => {
256-
if let Some(val) = attr.value_str() {
257-
if val.as_str().bytes().any(|b| b == 0) {
258-
let msg = format!("illegal null byte in link_section value: `{val}`");
259-
tcx.dcx().span_err(attr.span(), msg);
260-
} else {
261-
codegen_fn_attrs.link_section = Some(val);
262-
}
263-
}
264-
}
265263
sym::link_name => codegen_fn_attrs.link_name = attr.value_str(),
266264
sym::link_ordinal => {
267265
link_ordinal_span = Some(attr.span());

compiler/rustc_passes/src/check_attr.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
177177
Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => {
178178
self.check_align(span, target, *align, *repr_span)
179179
}
180+
Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => {
181+
self.check_link_section(hir_id, *attr_span, span, target)
182+
}
180183
Attribute::Parsed(AttributeKind::Naked(attr_span)) => {
181184
self.check_naked(hir_id, *attr_span, span, target)
182185
}
@@ -284,7 +287,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
284287
[sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
285288
[sym::link, ..] => self.check_link(hir_id, attr, span, target),
286289
[sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
287-
[sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target),
288290
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
289291
self.check_macro_use(hir_id, attr, target)
290292
}
@@ -1831,23 +1833,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
18311833
}
18321834

18331835
/// Checks if `#[link_section]` is applied to a function or static.
1834-
fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
1836+
fn check_link_section(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
18351837
match target {
18361838
Target::Static | Target::Fn | Target::Method(..) => {}
18371839
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
18381840
// `#[link_section]` attribute with just a lint, because we previously
18391841
// erroneously allowed it and some crates used it accidentally, to be compatible
18401842
// with crates depending on them, we can't throw an error here.
18411843
Target::Field | Target::Arm | Target::MacroDef => {
1842-
self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "link_section");
1844+
self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "link_section");
18431845
}
18441846
_ => {
18451847
// FIXME: #[link_section] was previously allowed on non-functions/statics and some
18461848
// crates used this, so only emit a warning.
18471849
self.tcx.emit_node_span_lint(
18481850
UNUSED_ATTRIBUTES,
18491851
hir_id,
1850-
attr.span(),
1852+
attr_span,
18511853
errors::LinkSection { span },
18521854
);
18531855
}

src/librustdoc/clean/types.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,9 +753,12 @@ impl Item {
753753
.other_attrs
754754
.iter()
755755
.filter_map(|attr| {
756+
if let hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) = attr {
757+
Some(format!("#[link_section = \"{name}\"]"))
758+
}
756759
// NoMangle is special cased, as it appears in HTML output, and we want to show it in source form, not HIR printing.
757760
// It is also used by cargo-semver-checks.
758-
if let hir::Attribute::Parsed(AttributeKind::NoMangle(..)) = attr {
761+
else if let hir::Attribute::Parsed(AttributeKind::NoMangle(..)) = attr {
759762
Some("#[no_mangle]".to_string())
760763
} else if let hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) = attr
761764
{
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@ edition: 2021
2+
#![no_std]
3+
4+
//@ is "$.index[?(@.name=='example')].attrs" '["#[link_section = \".text\"]"]'
5+
#[link_section = ".text"]
6+
pub extern "C" fn example() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@ edition: 2024
2+
#![no_std]
3+
4+
// Since the 2024 edition the link_section attribute must use the unsafe qualification.
5+
// However, the unsafe qualification is not shown by rustdoc.
6+
7+
//@ is "$.index[?(@.name=='example')].attrs" '["#[link_section = \".text\"]"]'
8+
#[unsafe(link_section = ".text")]
9+
pub extern "C" fn example() {}

0 commit comments

Comments
 (0)