Skip to content

Commit cf295a1

Browse files
authored
Unrolled build for rust-lang#128207
Rollup merge of rust-lang#128207 - folkertdev:asm-parser-generalize, r=Amanieu improve error message when `global_asm!` uses `asm!` options specifically, what was error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` --> $DIR/bad-options.rs:45:25 | LL | global_asm!("", options(preserves_flags)); | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` is now error: the `preserves_flags` option cannot be used with `global_asm!` --> $DIR/bad-options.rs:45:25 | LL | global_asm!("", options(preserves_flags)); | ^^^^^^^^^^^^^^^ the `preserves_flags` option is not meaningful for global-scoped inline assembly mirroring the phrasing of the [reference](https://doc.rust-lang.org/reference/inline-assembly.html#options). This is also a bit of a refactor for a future `naked_asm!` macro (for use in `#[naked]` functions). Currently this sort of error can come up when switching from inline to global asm, or when a user just isn't that experienced with assembly. With `naked_asm!` added to the mix hitting this error is more likely.
2 parents d9e1dea + 33b5ca9 commit cf295a1

17 files changed

+224
-105
lines changed

compiler/rustc_ast/src/ast.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2266,6 +2266,11 @@ bitflags::bitflags! {
22662266
}
22672267

22682268
impl InlineAsmOptions {
2269+
pub const COUNT: usize = Self::all().bits().count_ones() as usize;
2270+
2271+
pub const GLOBAL_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW);
2272+
pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW).union(Self::NORETURN);
2273+
22692274
pub fn human_readable_names(&self) -> Vec<&'static str> {
22702275
let mut options = vec![];
22712276

compiler/rustc_builtin_macros/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ builtin_macros_format_use_positional = consider using a positional formatting ar
199199
200200
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
201201
202+
builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!`
203+
.label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
204+
.suggestion = remove this option
205+
202206
builtin_macros_invalid_crate_attribute = invalid crate attribute
203207
204208
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes

compiler/rustc_builtin_macros/src/asm.rs

+43-22
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
310310
p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
311311
}
312312

313+
/// Report an invalid option error.
314+
///
315+
/// This function must be called immediately after the option token is parsed.
316+
/// Otherwise, the suggestion will be incorrect.
317+
fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
318+
// Tool-only output
319+
let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
320+
p.dcx().emit_err(errors::GlobalAsmUnsupportedOption { span, symbol, full_span });
321+
}
322+
313323
/// Try to set the provided option in the provided `AsmArgs`.
314324
/// If it is already set, report a duplicate option error.
315325
///
@@ -318,13 +328,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
318328
fn try_set_option<'a>(
319329
p: &Parser<'a>,
320330
args: &mut AsmArgs,
331+
is_global_asm: bool,
321332
symbol: Symbol,
322333
option: ast::InlineAsmOptions,
323334
) {
324-
if !args.options.contains(option) {
325-
args.options |= option;
326-
} else {
335+
if is_global_asm && !ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
336+
err_unsupported_option(p, symbol, p.prev_token.span);
337+
} else if args.options.contains(option) {
327338
err_duplicate_option(p, symbol, p.prev_token.span);
339+
} else {
340+
args.options |= option;
328341
}
329342
}
330343

@@ -338,25 +351,33 @@ fn parse_options<'a>(
338351
p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
339352

340353
while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
341-
if !is_global_asm && p.eat_keyword(sym::pure) {
342-
try_set_option(p, args, sym::pure, ast::InlineAsmOptions::PURE);
343-
} else if !is_global_asm && p.eat_keyword(sym::nomem) {
344-
try_set_option(p, args, sym::nomem, ast::InlineAsmOptions::NOMEM);
345-
} else if !is_global_asm && p.eat_keyword(sym::readonly) {
346-
try_set_option(p, args, sym::readonly, ast::InlineAsmOptions::READONLY);
347-
} else if !is_global_asm && p.eat_keyword(sym::preserves_flags) {
348-
try_set_option(p, args, sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS);
349-
} else if !is_global_asm && p.eat_keyword(sym::noreturn) {
350-
try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN);
351-
} else if !is_global_asm && p.eat_keyword(sym::nostack) {
352-
try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
353-
} else if !is_global_asm && p.eat_keyword(sym::may_unwind) {
354-
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND);
355-
} else if p.eat_keyword(sym::att_syntax) {
356-
try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
357-
} else if p.eat_keyword(kw::Raw) {
358-
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
359-
} else {
354+
const OPTIONS: [(Symbol, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
355+
(sym::pure, ast::InlineAsmOptions::PURE),
356+
(sym::nomem, ast::InlineAsmOptions::NOMEM),
357+
(sym::readonly, ast::InlineAsmOptions::READONLY),
358+
(sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS),
359+
(sym::noreturn, ast::InlineAsmOptions::NORETURN),
360+
(sym::nostack, ast::InlineAsmOptions::NOSTACK),
361+
(sym::may_unwind, ast::InlineAsmOptions::MAY_UNWIND),
362+
(sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX),
363+
(kw::Raw, ast::InlineAsmOptions::RAW),
364+
];
365+
366+
'blk: {
367+
for (symbol, option) in OPTIONS {
368+
let kw_matched =
369+
if !is_global_asm || ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
370+
p.eat_keyword(symbol)
371+
} else {
372+
p.eat_keyword_noexpect(symbol)
373+
};
374+
375+
if kw_matched {
376+
try_set_option(p, args, is_global_asm, symbol, option);
377+
break 'blk;
378+
}
379+
}
380+
360381
return p.unexpected();
361382
}
362383

compiler/rustc_builtin_macros/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,17 @@ pub(crate) struct AsmOptAlreadyprovided {
845845
pub(crate) full_span: Span,
846846
}
847847

848+
#[derive(Diagnostic)]
849+
#[diag(builtin_macros_global_asm_unsupported_option)]
850+
pub(crate) struct GlobalAsmUnsupportedOption {
851+
#[primary_span]
852+
#[label]
853+
pub(crate) span: Span,
854+
pub(crate) symbol: Symbol,
855+
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
856+
pub(crate) full_span: Span,
857+
}
858+
848859
#[derive(Diagnostic)]
849860
#[diag(builtin_macros_test_runner_invalid)]
850861
pub(crate) struct TestRunnerInvalid {

compiler/rustc_parse/src/parser/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ impl<'a> Parser<'a> {
599599

600600
/// If the next token is the given keyword, eats it and returns `true`.
601601
/// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
602-
// Public for rustfmt usage.
602+
// Public for rustc_builtin_macros and rustfmt usage.
603603
#[inline]
604604
pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
605605
if self.check_keyword(kw) {
@@ -631,8 +631,11 @@ impl<'a> Parser<'a> {
631631
false
632632
}
633633

634+
/// If the next token is the given keyword, eats it and returns `true`.
635+
/// Otherwise, returns `false`. No expectation is added.
636+
// Public for rustc_builtin_macros usage.
634637
#[inline]
635-
fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
638+
pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
636639
if self.token.is_keyword(kw) {
637640
self.bump();
638641
true

compiler/rustc_passes/src/naked_functions.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
244244
self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
245245
}
246246

247-
let supported_options =
248-
InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX;
249-
let unsupported_options = asm.options.difference(supported_options);
250-
247+
let unsupported_options = asm.options.difference(InlineAsmOptions::NAKED_OPTIONS);
251248
if !unsupported_options.is_empty() {
252249
self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
253250
span,

tests/ui/asm/aarch64/bad-options.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ fn main() {
2626
}
2727

2828
global_asm!("", options(nomem));
29-
//~^ ERROR expected one of
29+
//~^ ERROR the `nomem` option cannot be used with `global_asm!`
3030
global_asm!("", options(readonly));
31-
//~^ ERROR expected one of
31+
//~^ ERROR the `readonly` option cannot be used with `global_asm!`
3232
global_asm!("", options(noreturn));
33-
//~^ ERROR expected one of
33+
//~^ ERROR the `noreturn` option cannot be used with `global_asm!`
3434
global_asm!("", options(pure));
35-
//~^ ERROR expected one of
35+
//~^ ERROR the `pure` option cannot be used with `global_asm!`
3636
global_asm!("", options(nostack));
37-
//~^ ERROR expected one of
37+
//~^ ERROR the `nostack` option cannot be used with `global_asm!`
3838
global_asm!("", options(preserves_flags));
39-
//~^ ERROR expected one of
39+
//~^ ERROR the `preserves_flags` option cannot be used with `global_asm!`

tests/ui/asm/aarch64/bad-options.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -36,41 +36,41 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C"));
3636
| |
3737
| generic outputs
3838

39-
error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
39+
error: the `nomem` option cannot be used with `global_asm!`
4040
--> $DIR/bad-options.rs:28:25
4141
|
4242
LL | global_asm!("", options(nomem));
43-
| ^^^^^ expected one of `)`, `att_syntax`, or `raw`
43+
| ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
4444

45-
error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
45+
error: the `readonly` option cannot be used with `global_asm!`
4646
--> $DIR/bad-options.rs:30:25
4747
|
4848
LL | global_asm!("", options(readonly));
49-
| ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
49+
| ^^^^^^^^ the `readonly` option is not meaningful for global-scoped inline assembly
5050

51-
error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
51+
error: the `noreturn` option cannot be used with `global_asm!`
5252
--> $DIR/bad-options.rs:32:25
5353
|
5454
LL | global_asm!("", options(noreturn));
55-
| ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
55+
| ^^^^^^^^ the `noreturn` option is not meaningful for global-scoped inline assembly
5656

57-
error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
57+
error: the `pure` option cannot be used with `global_asm!`
5858
--> $DIR/bad-options.rs:34:25
5959
|
6060
LL | global_asm!("", options(pure));
61-
| ^^^^ expected one of `)`, `att_syntax`, or `raw`
61+
| ^^^^ the `pure` option is not meaningful for global-scoped inline assembly
6262

63-
error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
63+
error: the `nostack` option cannot be used with `global_asm!`
6464
--> $DIR/bad-options.rs:36:25
6565
|
6666
LL | global_asm!("", options(nostack));
67-
| ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
67+
| ^^^^^^^ the `nostack` option is not meaningful for global-scoped inline assembly
6868

69-
error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
69+
error: the `preserves_flags` option cannot be used with `global_asm!`
7070
--> $DIR/bad-options.rs:38:25
7171
|
7272
LL | global_asm!("", options(preserves_flags));
73-
| ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
73+
| ^^^^^^^^^^^^^^^ the `preserves_flags` option is not meaningful for global-scoped inline assembly
7474

7575
error: invalid ABI for `clobber_abi`
7676
--> $DIR/bad-options.rs:20:18

tests/ui/asm/aarch64/parse-error.rs

+2
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,10 @@ global_asm!("", options(FOO));
9898
//~^ ERROR expected one of
9999
global_asm!("", options(nomem FOO));
100100
//~^ ERROR expected one of
101+
//~| ERROR the `nomem` option cannot be used with `global_asm!`
101102
global_asm!("", options(nomem, FOO));
102103
//~^ ERROR expected one of
104+
//~| ERROR the `nomem` option cannot be used with `global_asm!`
103105
global_asm!("{}", options(), const FOO);
104106
global_asm!("", clobber_abi(FOO));
105107
//~^ ERROR expected string literal

tests/ui/asm/aarch64/parse-error.stderr

+30-18
Original file line numberDiff line numberDiff line change
@@ -218,92 +218,104 @@ error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
218218
LL | global_asm!("", options(FOO));
219219
| ^^^ expected one of `)`, `att_syntax`, or `raw`
220220

221-
error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
221+
error: the `nomem` option cannot be used with `global_asm!`
222222
--> $DIR/parse-error.rs:99:25
223223
|
224224
LL | global_asm!("", options(nomem FOO));
225-
| ^^^^^ expected one of `)`, `att_syntax`, or `raw`
225+
| ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
226226

227-
error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
228-
--> $DIR/parse-error.rs:101:25
227+
error: expected one of `)` or `,`, found `FOO`
228+
--> $DIR/parse-error.rs:99:31
229+
|
230+
LL | global_asm!("", options(nomem FOO));
231+
| ^^^ expected one of `)` or `,`
232+
233+
error: the `nomem` option cannot be used with `global_asm!`
234+
--> $DIR/parse-error.rs:102:25
235+
|
236+
LL | global_asm!("", options(nomem, FOO));
237+
| ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
238+
239+
error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
240+
--> $DIR/parse-error.rs:102:32
229241
|
230242
LL | global_asm!("", options(nomem, FOO));
231-
| ^^^^^ expected one of `)`, `att_syntax`, or `raw`
243+
| ^^^ expected one of `)`, `att_syntax`, or `raw`
232244

233245
error: expected string literal
234-
--> $DIR/parse-error.rs:104:29
246+
--> $DIR/parse-error.rs:106:29
235247
|
236248
LL | global_asm!("", clobber_abi(FOO));
237249
| ^^^ not a string literal
238250

239251
error: expected one of `)` or `,`, found `FOO`
240-
--> $DIR/parse-error.rs:106:33
252+
--> $DIR/parse-error.rs:108:33
241253
|
242254
LL | global_asm!("", clobber_abi("C" FOO));
243255
| ^^^ expected one of `)` or `,`
244256

245257
error: expected string literal
246-
--> $DIR/parse-error.rs:108:34
258+
--> $DIR/parse-error.rs:110:34
247259
|
248260
LL | global_asm!("", clobber_abi("C", FOO));
249261
| ^^^ not a string literal
250262

251263
error: `clobber_abi` cannot be used with `global_asm!`
252-
--> $DIR/parse-error.rs:110:19
264+
--> $DIR/parse-error.rs:112:19
253265
|
254266
LL | global_asm!("{}", clobber_abi("C"), const FOO);
255267
| ^^^^^^^^^^^^^^^^
256268

257269
error: `clobber_abi` cannot be used with `global_asm!`
258-
--> $DIR/parse-error.rs:112:28
270+
--> $DIR/parse-error.rs:114:28
259271
|
260272
LL | global_asm!("", options(), clobber_abi("C"));
261273
| ^^^^^^^^^^^^^^^^
262274

263275
error: `clobber_abi` cannot be used with `global_asm!`
264-
--> $DIR/parse-error.rs:114:30
276+
--> $DIR/parse-error.rs:116:30
265277
|
266278
LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
267279
| ^^^^^^^^^^^^^^^^
268280

269281
error: duplicate argument named `a`
270-
--> $DIR/parse-error.rs:116:35
282+
--> $DIR/parse-error.rs:118:35
271283
|
272284
LL | global_asm!("{a}", a = const FOO, a = const BAR);
273285
| ------------- ^^^^^^^^^^^^^ duplicate argument
274286
| |
275287
| previously here
276288

277289
error: argument never used
278-
--> $DIR/parse-error.rs:116:35
290+
--> $DIR/parse-error.rs:118:35
279291
|
280292
LL | global_asm!("{a}", a = const FOO, a = const BAR);
281293
| ^^^^^^^^^^^^^ argument never used
282294
|
283295
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
284296

285297
error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
286-
--> $DIR/parse-error.rs:119:28
298+
--> $DIR/parse-error.rs:121:28
287299
|
288300
LL | global_asm!("", options(), "");
289301
| ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
290302

291303
error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
292-
--> $DIR/parse-error.rs:121:30
304+
--> $DIR/parse-error.rs:123:30
293305
|
294306
LL | global_asm!("{}", const FOO, "{}", const FOO);
295307
| ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
296308

297309
error: asm template must be a string literal
298-
--> $DIR/parse-error.rs:123:13
310+
--> $DIR/parse-error.rs:125:13
299311
|
300312
LL | global_asm!(format!("{{{}}}", 0), const FOO);
301313
| ^^^^^^^^^^^^^^^^^^^^
302314
|
303315
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
304316

305317
error: asm template must be a string literal
306-
--> $DIR/parse-error.rs:125:20
318+
--> $DIR/parse-error.rs:127:20
307319
|
308320
LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
309321
| ^^^^^^^^^^^^^^^^^^^^
@@ -398,6 +410,6 @@ help: consider using `const` instead of `let`
398410
LL | const bar: /* Type */ = 0;
399411
| ~~~~~ ++++++++++++
400412

401-
error: aborting due to 57 previous errors
413+
error: aborting due to 59 previous errors
402414

403415
For more information about this error, try `rustc --explain E0435`.

tests/ui/asm/parse-error.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,15 @@ global_asm!("{}", const);
111111
global_asm!("{}", const(reg) FOO);
112112
//~^ ERROR expected one of
113113
global_asm!("", options(FOO));
114-
//~^ ERROR expected one of
114+
//~^ ERROR expected one of `)`, `att_syntax`, or `raw`, found `FOO`
115+
global_asm!("", options(FOO,));
116+
//~^ ERROR expected one of `)`, `att_syntax`, or `raw`, found `FOO`
115117
global_asm!("", options(nomem FOO));
116-
//~^ ERROR expected one of
118+
//~^ ERROR the `nomem` option cannot be used with `global_asm!`
119+
//~| ERROR expected one of `)` or `,`, found `FOO`
117120
global_asm!("", options(nomem, FOO));
118-
//~^ ERROR expected one of
121+
//~^ ERROR the `nomem` option cannot be used with `global_asm!`
122+
//~| ERROR expected one of `)`, `att_syntax`, or `raw`, found `FOO`
119123
global_asm!("{}", options(), const FOO);
120124
global_asm!("", clobber_abi(FOO));
121125
//~^ ERROR expected string literal

0 commit comments

Comments
 (0)