@@ -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 RawAsmArg {
24
25
pub kind : RawAsmArgKind ,
26
+ pub attributes : AsmAttrVec ,
25
27
pub span : Span ,
26
28
}
27
29
@@ -43,6 +45,48 @@ struct AsmArgs {
43
45
pub options_spans : Vec < Span > ,
44
46
}
45
47
48
+ /// A parsed list of attributes that is not attached to any item.
49
+ /// Used to check whether `asm!` arguments are configured out.
50
+ pub struct AsmAttrVec ( pub ast:: AttrVec ) ;
51
+
52
+ impl AsmAttrVec {
53
+ fn parse < ' a > ( p : & mut Parser < ' a > ) -> PResult < ' a , Self > {
54
+ let mut attributes = ast:: AttrVec :: new ( ) ;
55
+ loop {
56
+ if p. token != token:: Pound {
57
+ break ;
58
+ }
59
+
60
+ let attr = p. parse_attribute ( rustc_parse:: parser:: attr:: InnerAttrPolicy :: Permitted ) ?;
61
+ attributes. push ( attr) ;
62
+ }
63
+
64
+ Ok ( Self ( attributes) )
65
+ }
66
+ }
67
+ impl ast:: HasAttrs for AsmAttrVec {
68
+ // Follows `ast::Expr`.
69
+ const SUPPORTS_CUSTOM_INNER_ATTRS : bool = false ;
70
+
71
+ fn attrs ( & self ) -> & [ rustc_ast:: Attribute ] {
72
+ & self . 0
73
+ }
74
+
75
+ fn visit_attrs ( & mut self , f : impl FnOnce ( & mut rustc_ast:: AttrVec ) ) {
76
+ f ( & mut self . 0 )
77
+ }
78
+ }
79
+
80
+ impl ast:: HasTokens for AsmAttrVec {
81
+ fn tokens ( & self ) -> Option < & rustc_ast:: tokenstream:: LazyAttrTokenStream > {
82
+ None
83
+ }
84
+
85
+ fn tokens_mut ( & mut self ) -> Option < & mut Option < rustc_ast:: tokenstream:: LazyAttrTokenStream > > {
86
+ None
87
+ }
88
+ }
89
+
46
90
/// Used for better error messages when operand types are used that are not
47
91
/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
48
92
///
@@ -158,10 +202,12 @@ pub fn parse_raw_asm_args<'a>(
158
202
159
203
let mut args = Vec :: new ( ) ;
160
204
205
+ let attributes = AsmAttrVec :: parse ( p) ?;
161
206
let first_template = p. parse_expr ( ) ?;
162
207
args. push ( RawAsmArg {
163
208
span : first_template. span ,
164
209
kind : RawAsmArgKind :: Template ( first_template) ,
210
+ attributes,
165
211
} ) ;
166
212
167
213
let mut allow_templates = true ;
@@ -180,6 +226,7 @@ pub fn parse_raw_asm_args<'a>(
180
226
break ;
181
227
} // accept trailing commas
182
228
229
+ let attributes = AsmAttrVec :: parse ( p) ?;
183
230
let span_start = p. token . span ;
184
231
185
232
// Parse clobber_abi
@@ -189,6 +236,7 @@ pub fn parse_raw_asm_args<'a>(
189
236
args. push ( RawAsmArg {
190
237
kind : RawAsmArgKind :: ClobberAbi ( parse_clobber_abi ( p) ?) ,
191
238
span : span_start. to ( p. prev_token . span ) ,
239
+ attributes,
192
240
} ) ;
193
241
194
242
continue ;
@@ -201,6 +249,7 @@ pub fn parse_raw_asm_args<'a>(
201
249
args. push ( RawAsmArg {
202
250
kind : RawAsmArgKind :: Options ( parse_options ( p, asm_macro) ?) ,
203
251
span : span_start. to ( p. prev_token . span ) ,
252
+ attributes,
204
253
} ) ;
205
254
206
255
continue ;
@@ -223,6 +272,7 @@ pub fn parse_raw_asm_args<'a>(
223
272
args. push ( RawAsmArg {
224
273
span : span_start. to ( p. prev_token . span ) ,
225
274
kind : RawAsmArgKind :: Operand ( name, op) ,
275
+ attributes,
226
276
} ) ;
227
277
} else if allow_templates {
228
278
let template = p. parse_expr ( ) ?;
@@ -244,7 +294,11 @@ pub fn parse_raw_asm_args<'a>(
244
294
}
245
295
}
246
296
247
- args. push ( RawAsmArg { span : template. span , kind : RawAsmArgKind :: Template ( template) } ) ;
297
+ args. push ( RawAsmArg {
298
+ span : template. span ,
299
+ kind : RawAsmArgKind :: Template ( template) ,
300
+ attributes,
301
+ } ) ;
248
302
} else {
249
303
p. unexpected_any ( ) ?
250
304
}
@@ -270,6 +324,13 @@ fn validate_raw_asm_args<'a>(
270
324
) -> PResult < ' a , AsmArgs > {
271
325
let dcx = ecx. dcx ( ) ;
272
326
327
+ let strip_unconfigured = rustc_expand:: config:: StripUnconfigured {
328
+ sess : ecx. sess ,
329
+ features : Some ( ecx. ecfg . features ) ,
330
+ config_tokens : false ,
331
+ lint_node_id : ecx. current_expansion . lint_node_id ,
332
+ } ;
333
+
273
334
let mut args = AsmArgs {
274
335
templates : vec ! [ ] ,
275
336
operands : vec ! [ ] ,
@@ -283,6 +344,26 @@ fn validate_raw_asm_args<'a>(
283
344
let mut allow_templates = true ;
284
345
285
346
for arg in raw_args {
347
+ for attr in arg. attributes . 0 . iter ( ) {
348
+ match attr. name ( ) {
349
+ Some ( sym:: cfg | sym:: cfg_attr) => {
350
+ if !ecx. ecfg . features . asm_cfg ( ) {
351
+ let span = attr. span ( ) ;
352
+ feature_err ( ecx. sess , sym:: asm_cfg, span, fluent:: builtin_macros_asm_cfg)
353
+ . emit ( ) ;
354
+ }
355
+ }
356
+ _ => {
357
+ ecx. dcx ( ) . emit_err ( errors:: AsmAttributeNotSupported { span : attr. span ( ) } ) ;
358
+ }
359
+ }
360
+ }
361
+
362
+ // Skip arguments that are configured out.
363
+ if ecx. ecfg . features . asm_cfg ( ) && strip_unconfigured. configure ( arg. attributes ) . is_none ( ) {
364
+ continue ;
365
+ }
366
+
286
367
match arg. kind {
287
368
RawAsmArgKind :: Template ( template) => {
288
369
// The error for the first template is delayed.
0 commit comments