@@ -10,18 +10,20 @@ use rustc_index::bit_set::GrowableBitSet;
10
10
use rustc_parse:: exp;
11
11
use rustc_parse:: parser:: { ExpKeywordPair , Parser } ;
12
12
use 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} ;
14
15
use rustc_target:: asm:: InlineAsmArch ;
15
16
use smallvec:: smallvec;
16
17
use { rustc_ast as ast, rustc_parse_format as parse} ;
17
18
18
- use crate :: errors;
19
19
use crate :: util:: { ExprToSpannedString , expr_to_spanned_string} ;
20
+ use crate :: { errors, fluent_generated as fluent} ;
20
21
21
22
/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
22
23
/// not validated at all.
23
24
pub struct AsmArg {
24
25
pub kind : AsmArgKind ,
26
+ pub attributes : AsmAttrVec ,
25
27
pub span : Span ,
26
28
}
27
29
@@ -52,6 +54,44 @@ struct ValidatedAsmArgs {
52
54
pub options_spans : Vec < Span > ,
53
55
}
54
56
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
+
55
95
/// Used for better error messages when operand types are used that are not
56
96
/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
57
97
///
@@ -167,8 +207,13 @@ pub fn parse_asm_args<'a>(
167
207
168
208
let mut args = Vec :: new ( ) ;
169
209
210
+ let attributes = AsmAttrVec :: parse ( p) ?;
170
211
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
+ } ) ;
172
217
173
218
let mut allow_templates = true ;
174
219
@@ -188,6 +233,7 @@ pub fn parse_asm_args<'a>(
188
233
break ;
189
234
}
190
235
236
+ let attributes = AsmAttrVec :: parse ( p) ?;
191
237
let span_start = p. token . span ;
192
238
193
239
// Parse `clobber_abi`.
@@ -197,6 +243,7 @@ pub fn parse_asm_args<'a>(
197
243
args. push ( AsmArg {
198
244
kind : AsmArgKind :: ClobberAbi ( parse_clobber_abi ( p) ?) ,
199
245
span : span_start. to ( p. prev_token . span ) ,
246
+ attributes,
200
247
} ) ;
201
248
202
249
continue ;
@@ -209,6 +256,7 @@ pub fn parse_asm_args<'a>(
209
256
args. push ( AsmArg {
210
257
kind : AsmArgKind :: Options ( parse_options ( p, asm_macro) ?) ,
211
258
span : span_start. to ( p. prev_token . span ) ,
259
+ attributes,
212
260
} ) ;
213
261
214
262
continue ;
@@ -231,6 +279,7 @@ pub fn parse_asm_args<'a>(
231
279
args. push ( AsmArg {
232
280
span : span_start. to ( p. prev_token . span ) ,
233
281
kind : AsmArgKind :: Operand ( name, op) ,
282
+ attributes,
234
283
} ) ;
235
284
} else if allow_templates {
236
285
let template = p. parse_expr ( ) ?;
@@ -252,7 +301,11 @@ pub fn parse_asm_args<'a>(
252
301
}
253
302
}
254
303
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
+ } ) ;
256
309
} else {
257
310
p. unexpected_any ( ) ?
258
311
}
@@ -278,6 +331,13 @@ fn validate_asm_args<'a>(
278
331
) -> PResult < ' a , ValidatedAsmArgs > {
279
332
let dcx = ecx. dcx ( ) ;
280
333
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
+
281
341
let mut validated = ValidatedAsmArgs {
282
342
templates : vec ! [ ] ,
283
343
operands : vec ! [ ] ,
@@ -291,6 +351,26 @@ fn validate_asm_args<'a>(
291
351
let mut allow_templates = true ;
292
352
293
353
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
+
294
374
match arg. kind {
295
375
AsmArgKind :: Template ( template) => {
296
376
// The error for the first template is delayed.
0 commit comments