@@ -6,7 +6,7 @@ use rustc_span::{Span, Symbol, sym};
66use super :: { AcceptMapping , AttributeOrder , AttributeParser , OnDuplicate , SingleAttributeParser } ;
77use crate :: context:: { AcceptContext , FinalizeContext , Stage } ;
88use crate :: parser:: ArgParser ;
9- use crate :: session_diagnostics:: NakedFunctionIncompatibleAttribute ;
9+ use crate :: session_diagnostics:: { NakedFunctionIncompatibleAttribute , NullOnExport } ;
1010
1111pub ( crate ) struct OptimizeParser ;
1212
@@ -59,6 +59,33 @@ impl<S: Stage> SingleAttributeParser<S> for ColdParser {
5959 }
6060}
6161
62+ pub ( crate ) struct ExportNameParser ;
63+
64+ impl < S : Stage > SingleAttributeParser < S > for ExportNameParser {
65+ const PATH : & [ rustc_span:: Symbol ] = & [ sym:: export_name] ;
66+ const ATTRIBUTE_ORDER : AttributeOrder = AttributeOrder :: KeepFirst ;
67+ const ON_DUPLICATE : OnDuplicate < S > = OnDuplicate :: WarnButFutureError ;
68+ const TEMPLATE : AttributeTemplate = template ! ( NameValueStr : "name" ) ;
69+
70+ fn convert ( cx : & mut AcceptContext < ' _ , ' _ , S > , args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
71+ let Some ( nv) = args. name_value ( ) else {
72+ cx. expected_name_value ( cx. attr_span , None ) ;
73+ return None ;
74+ } ;
75+ let Some ( name) = nv. value_as_str ( ) else {
76+ cx. expected_string_literal ( nv. value_span , Some ( nv. value_as_lit ( ) ) ) ;
77+ return None ;
78+ } ;
79+ if name. as_str ( ) . contains ( '\0' ) {
80+ // `#[export_name = ...]` will be converted to a null-terminated string,
81+ // so it may not contain any null characters.
82+ cx. emit_err ( NullOnExport { span : cx. attr_span } ) ;
83+ return None ;
84+ }
85+ Some ( AttributeKind :: ExportName { name, span : cx. attr_span } )
86+ }
87+ }
88+
6289#[ derive( Default ) ]
6390pub ( crate ) struct NakedParser {
6491 span : Option < Span > ,
0 commit comments