rustc_attr_parsing/attributes/
link_attrs.rs

1use rustc_attr_data_structures::AttributeKind;
2use rustc_attr_data_structures::AttributeKind::{LinkName, LinkSection};
3use rustc_feature::{AttributeTemplate, template};
4use rustc_span::{Symbol, sym};
5
6use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
7use crate::context::{AcceptContext, Stage};
8use crate::parser::ArgParser;
9use crate::session_diagnostics::NullOnLinkSection;
10
11pub(crate) struct LinkNameParser;
12
13impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
14    const PATH: &[Symbol] = &[sym::link_name];
15    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
16    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
17    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
18
19    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
20        let Some(nv) = args.name_value() else {
21            cx.expected_name_value(cx.attr_span, None);
22            return None;
23        };
24        let Some(name) = nv.value_as_str() else {
25            cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
26            return None;
27        };
28
29        Some(LinkName { name, span: cx.attr_span })
30    }
31}
32
33pub(crate) struct LinkSectionParser;
34
35impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
36    const PATH: &[Symbol] = &[sym::link_section];
37    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
38    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
39    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
40
41    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
42        let Some(nv) = args.name_value() else {
43            cx.expected_name_value(cx.attr_span, None);
44            return None;
45        };
46        let Some(name) = nv.value_as_str() else {
47            cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
48            return None;
49        };
50        if name.as_str().contains('\0') {
51            // `#[link_section = ...]` will be converted to a null-terminated string,
52            // so it may not contain any null characters.
53            cx.emit_err(NullOnLinkSection { span: cx.attr_span });
54            return None;
55        }
56
57        Some(LinkSection { name, span: cx.attr_span })
58    }
59}