@@ -10,18 +10,20 @@ use rustc_index::bit_set::GrowableBitSet;
1010use rustc_parse:: exp;
1111use rustc_parse:: parser:: { ExpKeywordPair , Parser } ;
1212use rustc_session:: lint;
13- use rustc_span:: { ErrorGuaranteed , InnerSpan , Span , Symbol , kw} ;
13+ use rustc_session:: parse:: feature_err;
14+ use rustc_span:: { ErrorGuaranteed , InnerSpan , Span , Symbol , kw, sym} ;
1415use rustc_target:: asm:: InlineAsmArch ;
1516use smallvec:: smallvec;
1617use { rustc_ast as ast, rustc_parse_format as parse} ;
1718
18- use crate :: errors;
1919use crate :: util:: { ExprToSpannedString , expr_to_spanned_string} ;
20+ use crate :: { errors, fluent_generated as fluent} ;
2021
2122/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
2223/// not validated at all.
2324pub struct AsmArg {
2425 pub kind : AsmArgKind ,
26+ pub attributes : AsmAttrVec ,
2527 pub span : Span ,
2628}
2729
@@ -52,6 +54,44 @@ struct ValidatedAsmArgs {
5254 pub options_spans : Vec < Span > ,
5355}
5456
57+ /// A parsed list of attributes that is not attached to any item.
58+ /// Used to check whether `asm!` arguments are configured out.
59+ pub struct AsmAttrVec ( pub ast:: AttrVec ) ;
60+
61+ impl AsmAttrVec {
62+ fn parse < ' a > ( p : & mut Parser < ' a > ) -> PResult < ' a , Self > {
63+ let mut attributes = ast:: AttrVec :: new ( ) ;
64+ while p. token == token:: Pound {
65+ let attr = p. parse_attribute ( rustc_parse:: parser:: attr:: InnerAttrPolicy :: Permitted ) ?;
66+ attributes. push ( attr) ;
67+ }
68+
69+ Ok ( Self ( attributes) )
70+ }
71+ }
72+ impl ast:: HasAttrs for AsmAttrVec {
73+ // Follows `ast::Expr`.
74+ const SUPPORTS_CUSTOM_INNER_ATTRS : bool = false ;
75+
76+ fn attrs ( & self ) -> & [ rustc_ast:: Attribute ] {
77+ & self . 0
78+ }
79+
80+ fn visit_attrs ( & mut self , f : impl FnOnce ( & mut rustc_ast:: AttrVec ) ) {
81+ f ( & mut self . 0 )
82+ }
83+ }
84+
85+ impl ast:: HasTokens for AsmAttrVec {
86+ fn tokens ( & self ) -> Option < & rustc_ast:: tokenstream:: LazyAttrTokenStream > {
87+ None
88+ }
89+
90+ fn tokens_mut ( & mut self ) -> Option < & mut Option < rustc_ast:: tokenstream:: LazyAttrTokenStream > > {
91+ None
92+ }
93+ }
94+
5595/// Used for better error messages when operand types are used that are not
5696/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
5797///
@@ -167,8 +207,13 @@ pub fn parse_asm_args<'a>(
167207
168208 let mut args = Vec :: new ( ) ;
169209
210+ let attributes = AsmAttrVec :: parse ( p) ?;
170211 let first_template = p. parse_expr ( ) ?;
171- args. push ( AsmArg { span : first_template. span , kind : AsmArgKind :: Template ( first_template) } ) ;
212+ args. push ( AsmArg {
213+ span : first_template. span ,
214+ kind : AsmArgKind :: Template ( first_template) ,
215+ attributes,
216+ } ) ;
172217
173218 let mut allow_templates = true ;
174219
@@ -188,6 +233,7 @@ pub fn parse_asm_args<'a>(
188233 break ;
189234 }
190235
236+ let attributes = AsmAttrVec :: parse ( p) ?;
191237 let span_start = p. token . span ;
192238
193239 // Parse `clobber_abi`.
@@ -197,6 +243,7 @@ pub fn parse_asm_args<'a>(
197243 args. push ( AsmArg {
198244 kind : AsmArgKind :: ClobberAbi ( parse_clobber_abi ( p) ?) ,
199245 span : span_start. to ( p. prev_token . span ) ,
246+ attributes,
200247 } ) ;
201248
202249 continue ;
@@ -209,6 +256,7 @@ pub fn parse_asm_args<'a>(
209256 args. push ( AsmArg {
210257 kind : AsmArgKind :: Options ( parse_options ( p, asm_macro) ?) ,
211258 span : span_start. to ( p. prev_token . span ) ,
259+ attributes,
212260 } ) ;
213261
214262 continue ;
@@ -231,6 +279,7 @@ pub fn parse_asm_args<'a>(
231279 args. push ( AsmArg {
232280 span : span_start. to ( p. prev_token . span ) ,
233281 kind : AsmArgKind :: Operand ( name, op) ,
282+ attributes,
234283 } ) ;
235284 } else if allow_templates {
236285 let template = p. parse_expr ( ) ?;
@@ -252,7 +301,11 @@ pub fn parse_asm_args<'a>(
252301 }
253302 }
254303
255- args. push ( AsmArg { span : template. span , kind : AsmArgKind :: Template ( template) } ) ;
304+ args. push ( AsmArg {
305+ span : template. span ,
306+ kind : AsmArgKind :: Template ( template) ,
307+ attributes,
308+ } ) ;
256309 } else {
257310 p. unexpected_any ( ) ?
258311 }
@@ -278,6 +331,13 @@ fn validate_asm_args<'a>(
278331) -> PResult < ' a , ValidatedAsmArgs > {
279332 let dcx = ecx. dcx ( ) ;
280333
334+ let strip_unconfigured = rustc_expand:: config:: StripUnconfigured {
335+ sess : ecx. sess ,
336+ features : Some ( ecx. ecfg . features ) ,
337+ config_tokens : false ,
338+ lint_node_id : ecx. current_expansion . lint_node_id ,
339+ } ;
340+
281341 let mut validated = ValidatedAsmArgs {
282342 templates : vec ! [ ] ,
283343 operands : vec ! [ ] ,
@@ -291,6 +351,26 @@ fn validate_asm_args<'a>(
291351 let mut allow_templates = true ;
292352
293353 for arg in args {
354+ for attr in arg. attributes . 0 . iter ( ) {
355+ match attr. name ( ) {
356+ Some ( sym:: cfg | sym:: cfg_attr) => {
357+ if !ecx. ecfg . features . asm_cfg ( ) {
358+ let span = attr. span ( ) ;
359+ feature_err ( ecx. sess , sym:: asm_cfg, span, fluent:: builtin_macros_asm_cfg)
360+ . emit ( ) ;
361+ }
362+ }
363+ _ => {
364+ ecx. dcx ( ) . emit_err ( errors:: AsmAttributeNotSupported { span : attr. span ( ) } ) ;
365+ }
366+ }
367+ }
368+
369+ // Skip arguments that are configured out.
370+ if ecx. ecfg . features . asm_cfg ( ) && strip_unconfigured. configure ( arg. attributes ) . is_none ( ) {
371+ continue ;
372+ }
373+
294374 match arg. kind {
295375 AsmArgKind :: Template ( template) => {
296376 // The error for the first template is delayed.
0 commit comments