rustc_attr_parsing/attributes/
link_attrs.rs1use rustc_attr_data_structures::AttributeKind;
2use rustc_attr_data_structures::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
3use rustc_feature::{AttributeTemplate, template};
4use rustc_span::{Span, Symbol, sym};
5
6use crate::attributes::{
7 AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
8};
9use crate::context::{AcceptContext, Stage, parse_single_integer};
10use crate::parser::ArgParser;
11use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
12
13pub(crate) struct LinkNameParser;
14
15impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
16 const PATH: &[Symbol] = &[sym::link_name];
17 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
18 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
19 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
20
21 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
22 let Some(nv) = args.name_value() else {
23 cx.expected_name_value(cx.attr_span, None);
24 return None;
25 };
26 let Some(name) = nv.value_as_str() else {
27 cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
28 return None;
29 };
30
31 Some(LinkName { name, span: cx.attr_span })
32 }
33}
34
35pub(crate) struct LinkSectionParser;
36
37impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
38 const PATH: &[Symbol] = &[sym::link_section];
39 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
40 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
41 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
42
43 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
44 let Some(nv) = args.name_value() else {
45 cx.expected_name_value(cx.attr_span, None);
46 return None;
47 };
48 let Some(name) = nv.value_as_str() else {
49 cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
50 return None;
51 };
52 if name.as_str().contains('\0') {
53 cx.emit_err(NullOnLinkSection { span: cx.attr_span });
56 return None;
57 }
58
59 Some(LinkSection { name, span: cx.attr_span })
60 }
61}
62
63pub(crate) struct ExportStableParser;
64impl<S: Stage> NoArgsAttributeParser<S> for ExportStableParser {
65 const PATH: &[Symbol] = &[sym::export_stable];
66 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
67 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable;
68}
69
70pub(crate) struct FfiConstParser;
71impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser {
72 const PATH: &[Symbol] = &[sym::ffi_const];
73 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
74 const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst;
75}
76
77pub(crate) struct FfiPureParser;
78impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser {
79 const PATH: &[Symbol] = &[sym::ffi_pure];
80 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
81 const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
82}
83
84pub(crate) struct StdInternalSymbolParser;
85impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser {
86 const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol];
87 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
88 const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol;
89}
90
91pub(crate) struct LinkOrdinalParser;
92
93impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
94 const PATH: &[Symbol] = &[sym::link_ordinal];
95 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
96 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
97 const TEMPLATE: AttributeTemplate = template!(List: "ordinal");
98
99 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
100 let ordinal = parse_single_integer(cx, args)?;
101
102 let Ok(ordinal) = ordinal.try_into() else {
116 cx.emit_err(LinkOrdinalOutOfRange { span: cx.attr_span, ordinal });
117 return None;
118 };
119
120 Some(LinkOrdinal { ordinal, span: cx.attr_span })
121 }
122}