|
1 | 1 | use rustc_attr_data_structures::{AttributeKind, OptimizeAttr}; |
2 | 2 | use rustc_feature::{AttributeTemplate, template}; |
3 | 3 | use rustc_session::parse::feature_err; |
4 | | -use rustc_span::{Span, sym}; |
| 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; |
@@ -183,3 +186,54 @@ impl<S: Stage> SingleAttributeParser<S> for NoMangleParser { |
183 | 186 | Some(AttributeKind::NoMangle(cx.attr_span)) |
184 | 187 | } |
185 | 188 | } |
| 189 | + |
| 190 | +pub(crate) struct TargetFeatureParser; |
| 191 | + |
| 192 | +impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser { |
| 193 | + type Item = (Symbol, Span); |
| 194 | + const PATH: &[Symbol] = &[sym::target_feature]; |
| 195 | + const CONVERT: ConvertFn<Self::Item> = |
| 196 | + ConvertFn::WithFirstAttributeSpan(AttributeKind::TargetFeature); |
| 197 | + const TEMPLATE: AttributeTemplate = template!(List: "enable = \"feat1, feat2\""); |
| 198 | + |
| 199 | + fn extend<'c>( |
| 200 | + cx: &'c mut AcceptContext<'_, '_, S>, |
| 201 | + args: &'c ArgParser<'_>, |
| 202 | + ) -> impl IntoIterator<Item = Self::Item> + 'c { |
| 203 | + let mut features = Vec::new(); |
| 204 | + let ArgParser::List(list) = args else { |
| 205 | + cx.expected_list(cx.attr_span); |
| 206 | + return features; |
| 207 | + }; |
| 208 | + for item in list.mixed() { |
| 209 | + let Some(name_value) = item.meta_item() else { |
| 210 | + cx.expected_name_value(item.span(), Some(sym::enable)); |
| 211 | + return features; |
| 212 | + }; |
| 213 | + |
| 214 | + // Validate name |
| 215 | + let Some(name) = name_value.path().word_sym() else { |
| 216 | + cx.expected_name_value(name_value.path().span(), Some(sym::enable)); |
| 217 | + return features; |
| 218 | + }; |
| 219 | + if name != sym::enable { |
| 220 | + cx.expected_name_value(name_value.path().span(), Some(sym::enable)); |
| 221 | + return features; |
| 222 | + } |
| 223 | + |
| 224 | + // Use value |
| 225 | + let Some(name_value) = name_value.args().name_value() else { |
| 226 | + cx.expected_name_value(item.span(), Some(sym::enable)); |
| 227 | + return features; |
| 228 | + }; |
| 229 | + let Some(value_str) = name_value.value_as_str() else { |
| 230 | + cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit())); |
| 231 | + return features; |
| 232 | + }; |
| 233 | + for feature in value_str.as_str().split(",") { |
| 234 | + features.push((Symbol::intern(feature), item.span())); |
| 235 | + } |
| 236 | + } |
| 237 | + features |
| 238 | + } |
| 239 | +} |
0 commit comments