|
1 | 1 | use rustc_attr_data_structures::{AttributeKind, OptimizeAttr};
|
2 | 2 | use rustc_feature::{AttributeTemplate, template};
|
3 |
| -use rustc_span::sym; |
| 3 | +use rustc_span::{Span, Symbol, sym}; |
4 | 4 |
|
5 |
| -use super::{AttributeOrder, OnDuplicate, SingleAttributeParser}; |
| 5 | +use super::{ |
| 6 | + AttributeOrder, CombineAttributeParser, ConvertFn, OnDuplicate, SingleAttributeParser, |
| 7 | +}; |
6 | 8 | use crate::context::{AcceptContext, Stage};
|
7 | 9 | use crate::parser::ArgParser;
|
8 | 10 |
|
@@ -56,3 +58,54 @@ impl<S: Stage> SingleAttributeParser<S> for ColdParser {
|
56 | 58 | Some(AttributeKind::Cold(cx.attr_span))
|
57 | 59 | }
|
58 | 60 | }
|
| 61 | + |
| 62 | +pub(crate) struct TargetFeatureParser; |
| 63 | + |
| 64 | +impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser { |
| 65 | + type Item = (Symbol, Span); |
| 66 | + const PATH: &[Symbol] = &[sym::target_feature]; |
| 67 | + const CONVERT: ConvertFn<Self::Item> = |
| 68 | + ConvertFn::WithFirstAttributeSpan(AttributeKind::TargetFeature); |
| 69 | + const TEMPLATE: AttributeTemplate = template!(List: "enable = \"feat1, feat2\""); |
| 70 | + |
| 71 | + fn extend<'c>( |
| 72 | + cx: &'c mut AcceptContext<'_, '_, S>, |
| 73 | + args: &'c ArgParser<'_>, |
| 74 | + ) -> impl IntoIterator<Item = Self::Item> + 'c { |
| 75 | + let mut features = Vec::new(); |
| 76 | + let ArgParser::List(list) = args else { |
| 77 | + cx.expected_list(cx.attr_span); |
| 78 | + return features; |
| 79 | + }; |
| 80 | + for item in list.mixed() { |
| 81 | + let Some(name_value) = item.meta_item() else { |
| 82 | + cx.expected_name_value(item.span(), Some(sym::enable)); |
| 83 | + return features; |
| 84 | + }; |
| 85 | + |
| 86 | + // Validate name |
| 87 | + let Some(name) = name_value.path().word_sym() else { |
| 88 | + cx.expected_name_value(name_value.path().span(), Some(sym::enable)); |
| 89 | + return features; |
| 90 | + }; |
| 91 | + if name != sym::enable { |
| 92 | + cx.expected_name_value(name_value.path().span(), Some(sym::enable)); |
| 93 | + return features; |
| 94 | + } |
| 95 | + |
| 96 | + // Use value |
| 97 | + let Some(name_value) = name_value.args().name_value() else { |
| 98 | + cx.expected_name_value(item.span(), Some(sym::enable)); |
| 99 | + return features; |
| 100 | + }; |
| 101 | + let Some(value_str) = name_value.value_as_str() else { |
| 102 | + cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit())); |
| 103 | + return features; |
| 104 | + }; |
| 105 | + for feature in value_str.as_str().split(",") { |
| 106 | + features.push((Symbol::intern(feature), item.span())); |
| 107 | + } |
| 108 | + } |
| 109 | + features |
| 110 | + } |
| 111 | +} |
0 commit comments