rustc_attr_parsing/attributes/
link_attrs.rs1use rustc_feature::{AttributeTemplate, template};
2use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
3use rustc_hir::attrs::{AttributeKind, Linkage};
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!(
20 NameValueStr: "name",
21 "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute"
22 );
23
24 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
25 let Some(nv) = args.name_value() else {
26 cx.expected_name_value(cx.attr_span, None);
27 return None;
28 };
29 let Some(name) = nv.value_as_str() else {
30 cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
31 return None;
32 };
33
34 Some(LinkName { name, span: cx.attr_span })
35 }
36}
37
38pub(crate) struct LinkSectionParser;
39
40impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
41 const PATH: &[Symbol] = &[sym::link_section];
42 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
43 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
44 const TEMPLATE: AttributeTemplate = template!(
45 NameValueStr: "name",
46 "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute"
47 );
48
49 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
50 let Some(nv) = args.name_value() else {
51 cx.expected_name_value(cx.attr_span, None);
52 return None;
53 };
54 let Some(name) = nv.value_as_str() else {
55 cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
56 return None;
57 };
58 if name.as_str().contains('\0') {
59 cx.emit_err(NullOnLinkSection { span: cx.attr_span });
62 return None;
63 }
64
65 Some(LinkSection { name, span: cx.attr_span })
66 }
67}
68
69pub(crate) struct ExportStableParser;
70impl<S: Stage> NoArgsAttributeParser<S> for ExportStableParser {
71 const PATH: &[Symbol] = &[sym::export_stable];
72 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
73 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable;
74}
75
76pub(crate) struct FfiConstParser;
77impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser {
78 const PATH: &[Symbol] = &[sym::ffi_const];
79 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
80 const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst;
81}
82
83pub(crate) struct FfiPureParser;
84impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser {
85 const PATH: &[Symbol] = &[sym::ffi_pure];
86 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
87 const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
88}
89
90pub(crate) struct StdInternalSymbolParser;
91impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser {
92 const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol];
93 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
94 const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol;
95}
96
97pub(crate) struct LinkOrdinalParser;
98
99impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
100 const PATH: &[Symbol] = &[sym::link_ordinal];
101 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
102 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
103 const TEMPLATE: AttributeTemplate = template!(
104 List: &["ordinal"],
105 "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute"
106 );
107
108 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
109 let ordinal = parse_single_integer(cx, args)?;
110
111 let Ok(ordinal) = ordinal.try_into() else {
125 cx.emit_err(LinkOrdinalOutOfRange { span: cx.attr_span, ordinal });
126 return None;
127 };
128
129 Some(LinkOrdinal { ordinal, span: cx.attr_span })
130 }
131}
132
133pub(crate) struct LinkageParser;
134
135impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
136 const PATH: &[Symbol] = &[sym::linkage];
137
138 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
139
140 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
141
142 const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
143 "available_externally",
144 "common",
145 "extern_weak",
146 "external",
147 "internal",
148 "linkonce",
149 "linkonce_odr",
150 "weak",
151 "weak_odr",
152 ]);
153
154 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
155 let Some(name_value) = args.name_value() else {
156 cx.expected_name_value(cx.attr_span, Some(sym::linkage));
157 return None;
158 };
159
160 let Some(value) = name_value.value_as_str() else {
161 cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
162 return None;
163 };
164
165 let linkage = match value {
174 sym::available_externally => Linkage::AvailableExternally,
175 sym::common => Linkage::Common,
176 sym::extern_weak => Linkage::ExternalWeak,
177 sym::external => Linkage::External,
178 sym::internal => Linkage::Internal,
179 sym::linkonce => Linkage::LinkOnceAny,
180 sym::linkonce_odr => Linkage::LinkOnceODR,
181 sym::weak => Linkage::WeakAny,
182 sym::weak_odr => Linkage::WeakODR,
183
184 _ => {
185 cx.expected_specific_argument(
186 name_value.value_span,
187 vec![
188 "available_externally",
189 "common",
190 "extern_weak",
191 "external",
192 "internal",
193 "linkonce",
194 "linkonce_odr",
195 "weak",
196 "weak_odr",
197 ],
198 );
199 return None;
200 }
201 };
202
203 Some(AttributeKind::Linkage(linkage, cx.attr_span))
204 }
205}