@@ -3,7 +3,10 @@ use rustc_feature::{AttributeTemplate, template};
33use rustc_session:: parse:: feature_err;
44use rustc_span:: { Span , Symbol , sym} ;
55
6- use super :: { AcceptMapping , AttributeOrder , AttributeParser , OnDuplicate , SingleAttributeParser } ;
6+ use super :: {
7+ AcceptMapping , AttributeOrder , AttributeParser , CombineAttributeParser , ConvertFn , OnDuplicate ,
8+ SingleAttributeParser ,
9+ } ;
710use crate :: context:: { AcceptContext , FinalizeContext , Stage } ;
811use crate :: parser:: ArgParser ;
912use crate :: session_diagnostics:: { NakedFunctionIncompatibleAttribute , NullOnExport } ;
@@ -309,3 +312,54 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
309312 } )
310313 }
311314}
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