@@ -2,7 +2,9 @@ use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
2
2
use rustc_session:: parse:: feature_err;
3
3
4
4
use super :: prelude:: * ;
5
- use crate :: session_diagnostics:: { NakedFunctionIncompatibleAttribute , NullOnExport } ;
5
+ use crate :: session_diagnostics:: {
6
+ NakedFunctionIncompatibleAttribute , NullOnExport , NullOnObjcClass , NullOnObjcSelector ,
7
+ } ;
6
8
7
9
pub ( crate ) struct OptimizeParser ;
8
10
@@ -148,6 +150,64 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
148
150
}
149
151
}
150
152
153
+ pub ( crate ) struct ObjcClassParser ;
154
+
155
+ impl < S : Stage > SingleAttributeParser < S > for ObjcClassParser {
156
+ const PATH : & [ rustc_span:: Symbol ] = & [ sym:: rustc_objc_class] ;
157
+ const ATTRIBUTE_ORDER : AttributeOrder = AttributeOrder :: KeepInnermost ;
158
+ const ON_DUPLICATE : OnDuplicate < S > = OnDuplicate :: Error ;
159
+ const ALLOWED_TARGETS : AllowedTargets =
160
+ AllowedTargets :: AllowList ( & [ Allow ( Target :: ForeignStatic ) ] ) ;
161
+ const TEMPLATE : AttributeTemplate = template ! ( NameValueStr : "ClassName" ) ;
162
+
163
+ fn convert ( cx : & mut AcceptContext < ' _ , ' _ , S > , args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
164
+ let Some ( nv) = args. name_value ( ) else {
165
+ cx. expected_name_value ( cx. attr_span , None ) ;
166
+ return None ;
167
+ } ;
168
+ let Some ( classname) = nv. value_as_str ( ) else {
169
+ cx. expected_string_literal ( nv. value_span , Some ( nv. value_as_lit ( ) ) ) ;
170
+ return None ;
171
+ } ;
172
+ if classname. as_str ( ) . contains ( '\0' ) {
173
+ // `#[rustc_objc_class = ...]` will be converted to a null-terminated string,
174
+ // so it may not contain any null characters.
175
+ cx. emit_err ( NullOnObjcClass { span : cx. attr_span } ) ;
176
+ return None ;
177
+ }
178
+ Some ( AttributeKind :: ObjcClass { classname, span : cx. attr_span } )
179
+ }
180
+ }
181
+
182
+ pub ( crate ) struct ObjcSelectorParser ;
183
+
184
+ impl < S : Stage > SingleAttributeParser < S > for ObjcSelectorParser {
185
+ const PATH : & [ rustc_span:: Symbol ] = & [ sym:: rustc_objc_selector] ;
186
+ const ATTRIBUTE_ORDER : AttributeOrder = AttributeOrder :: KeepInnermost ;
187
+ const ON_DUPLICATE : OnDuplicate < S > = OnDuplicate :: Error ;
188
+ const ALLOWED_TARGETS : AllowedTargets =
189
+ AllowedTargets :: AllowList ( & [ Allow ( Target :: ForeignStatic ) ] ) ;
190
+ const TEMPLATE : AttributeTemplate = template ! ( NameValueStr : "methodName" ) ;
191
+
192
+ fn convert ( cx : & mut AcceptContext < ' _ , ' _ , S > , args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
193
+ let Some ( nv) = args. name_value ( ) else {
194
+ cx. expected_name_value ( cx. attr_span , None ) ;
195
+ return None ;
196
+ } ;
197
+ let Some ( methname) = nv. value_as_str ( ) else {
198
+ cx. expected_string_literal ( nv. value_span , Some ( nv. value_as_lit ( ) ) ) ;
199
+ return None ;
200
+ } ;
201
+ if methname. as_str ( ) . contains ( '\0' ) {
202
+ // `#[rustc_objc_selector = ...]` will be converted to a null-terminated string,
203
+ // so it may not contain any null characters.
204
+ cx. emit_err ( NullOnObjcSelector { span : cx. attr_span } ) ;
205
+ return None ;
206
+ }
207
+ Some ( AttributeKind :: ObjcSelector { methname, span : cx. attr_span } )
208
+ }
209
+ }
210
+
151
211
#[ derive( Default ) ]
152
212
pub ( crate ) struct NakedParser {
153
213
span : Option < Span > ,
0 commit comments