@@ -3,7 +3,10 @@ use rustc_feature::{AttributeTemplate, template};
3
3
use rustc_session:: parse:: feature_err;
4
4
use rustc_span:: { Span , Symbol , sym} ;
5
5
6
- use super :: { AcceptMapping , AttributeOrder , AttributeParser , OnDuplicate , SingleAttributeParser } ;
6
+ use super :: {
7
+ AcceptMapping , AttributeOrder , AttributeParser , CombineAttributeParser , ConvertFn , OnDuplicate ,
8
+ SingleAttributeParser ,
9
+ } ;
7
10
use crate :: context:: { AcceptContext , FinalizeContext , Stage } ;
8
11
use crate :: parser:: ArgParser ;
9
12
use crate :: session_diagnostics:: { NakedFunctionIncompatibleAttribute , NullOnExport } ;
@@ -309,3 +312,54 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
309
312
} )
310
313
}
311
314
}
315
+
316
+ pub ( crate ) struct TargetFeatureParser ;
317
+
318
+ impl < S : Stage > CombineAttributeParser < S > for TargetFeatureParser {
319
+ type Item = ( Symbol , Span ) ;
320
+ const PATH : & [ Symbol ] = & [ sym:: target_feature] ;
321
+ const CONVERT : ConvertFn < Self :: Item > =
322
+ ConvertFn :: WithFirstAttributeSpan ( AttributeKind :: TargetFeature ) ;
323
+ const TEMPLATE : AttributeTemplate = template ! ( List : "enable = \" feat1, feat2\" " ) ;
324
+
325
+ fn extend < ' c > (
326
+ cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
327
+ args : & ' c ArgParser < ' _ > ,
328
+ ) -> impl IntoIterator < Item = Self :: Item > + ' c {
329
+ let mut features = Vec :: new ( ) ;
330
+ let ArgParser :: List ( list) = args else {
331
+ cx. expected_list ( cx. attr_span ) ;
332
+ return features;
333
+ } ;
334
+ for item in list. mixed ( ) {
335
+ let Some ( name_value) = item. meta_item ( ) else {
336
+ cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
337
+ return features;
338
+ } ;
339
+
340
+ // Validate name
341
+ let Some ( name) = name_value. path ( ) . word_sym ( ) else {
342
+ cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
343
+ return features;
344
+ } ;
345
+ if name != sym:: enable {
346
+ cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
347
+ return features;
348
+ }
349
+
350
+ // Use value
351
+ let Some ( name_value) = name_value. args ( ) . name_value ( ) else {
352
+ cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
353
+ return features;
354
+ } ;
355
+ let Some ( value_str) = name_value. value_as_str ( ) else {
356
+ cx. expected_string_literal ( name_value. value_span , Some ( name_value. value_as_lit ( ) ) ) ;
357
+ return features;
358
+ } ;
359
+ for feature in value_str. as_str ( ) . split ( "," ) {
360
+ features. push ( ( Symbol :: intern ( feature) , item. span ( ) ) ) ;
361
+ }
362
+ }
363
+ features
364
+ }
365
+ }
0 commit comments