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