diff options
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/asm.rs | 71 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/errors.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test.rs | 8 |
3 files changed, 75 insertions, 25 deletions
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index dd0f9aaf221..62e59f1f4d4 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -310,6 +310,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) { p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span }); } +/// Report an invalid option error. +/// +/// This function must be called immediately after the option token is parsed. +/// Otherwise, the suggestion will be incorrect. +fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) { + // Tool-only output + let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span }; + p.dcx().emit_err(errors::GlobalAsmUnsupportedOption { span, symbol, full_span }); +} + /// Try to set the provided option in the provided `AsmArgs`. /// If it is already set, report a duplicate option error. /// @@ -318,13 +328,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) { fn try_set_option<'a>( p: &Parser<'a>, args: &mut AsmArgs, + is_global_asm: bool, symbol: Symbol, option: ast::InlineAsmOptions, ) { - if !args.options.contains(option) { - args.options |= option; - } else { + if is_global_asm && !ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) { + err_unsupported_option(p, symbol, p.prev_token.span); + } else if args.options.contains(option) { err_duplicate_option(p, symbol, p.prev_token.span); + } else { + args.options |= option; } } @@ -338,25 +351,33 @@ fn parse_options<'a>( p.expect(&token::OpenDelim(Delimiter::Parenthesis))?; while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { - if !is_global_asm && p.eat_keyword(sym::pure) { - try_set_option(p, args, sym::pure, ast::InlineAsmOptions::PURE); - } else if !is_global_asm && p.eat_keyword(sym::nomem) { - try_set_option(p, args, sym::nomem, ast::InlineAsmOptions::NOMEM); - } else if !is_global_asm && p.eat_keyword(sym::readonly) { - try_set_option(p, args, sym::readonly, ast::InlineAsmOptions::READONLY); - } else if !is_global_asm && p.eat_keyword(sym::preserves_flags) { - try_set_option(p, args, sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS); - } else if !is_global_asm && p.eat_keyword(sym::noreturn) { - try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN); - } else if !is_global_asm && p.eat_keyword(sym::nostack) { - try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK); - } else if !is_global_asm && p.eat_keyword(sym::may_unwind) { - try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND); - } else if p.eat_keyword(sym::att_syntax) { - try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX); - } else if p.eat_keyword(kw::Raw) { - try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW); - } else { + const OPTIONS: [(Symbol, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [ + (sym::pure, ast::InlineAsmOptions::PURE), + (sym::nomem, ast::InlineAsmOptions::NOMEM), + (sym::readonly, ast::InlineAsmOptions::READONLY), + (sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS), + (sym::noreturn, ast::InlineAsmOptions::NORETURN), + (sym::nostack, ast::InlineAsmOptions::NOSTACK), + (sym::may_unwind, ast::InlineAsmOptions::MAY_UNWIND), + (sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX), + (kw::Raw, ast::InlineAsmOptions::RAW), + ]; + + 'blk: { + for (symbol, option) in OPTIONS { + let kw_matched = + if !is_global_asm || ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) { + p.eat_keyword(symbol) + } else { + p.eat_keyword_noexpect(symbol) + }; + + if kw_matched { + try_set_option(p, args, is_global_asm, symbol, option); + break 'blk; + } + } + return p.unexpected(); } @@ -459,7 +480,7 @@ fn expand_preparsed_asm( for (i, template_expr) in args.templates.into_iter().enumerate() { if i != 0 { - template.push(ast::InlineAsmTemplatePiece::String("\n".to_string())); + template.push(ast::InlineAsmTemplatePiece::String("\n".into())); } let msg = "asm template must be a string literal"; @@ -527,7 +548,7 @@ fn expand_preparsed_asm( // Don't treat raw asm as a format string. if args.options.contains(ast::InlineAsmOptions::RAW) { - template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string())); + template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string().into())); let template_num_lines = 1 + template_str.matches('\n').count(); line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines)); continue; @@ -577,7 +598,7 @@ fn expand_preparsed_asm( for piece in unverified_pieces { match piece { parse::Piece::String(s) => { - template.push(ast::InlineAsmTemplatePiece::String(s.to_string())) + template.push(ast::InlineAsmTemplatePiece::String(s.to_string().into())) } parse::Piece::NextArgument(arg) => { let span = arg_spans.next().unwrap_or(template_sp); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 49d640436c2..f17819474ad 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -846,6 +846,17 @@ pub(crate) struct AsmOptAlreadyprovided { } #[derive(Diagnostic)] +#[diag(builtin_macros_global_asm_unsupported_option)] +pub(crate) struct GlobalAsmUnsupportedOption { + #[primary_span] + #[label] + pub(crate) span: Span, + pub(crate) symbol: Symbol, + #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + pub(crate) full_span: Span, +} + +#[derive(Diagnostic)] #[diag(builtin_macros_test_runner_invalid)] pub(crate) struct TestRunnerInvalid { #[primary_span] @@ -912,3 +923,13 @@ pub(crate) struct ExpectedItem<'a> { pub span: Span, pub token: &'a str, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)] +pub struct NakedFunctionTestingAttribute { + #[primary_span] + #[label(builtin_macros_naked_attribute)] + pub naked_span: Span, + #[label] + pub testing_span: Span, +} diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index c0310a2f4b0..bb00c8de1b8 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -133,6 +133,14 @@ pub(crate) fn expand_test_or_bench( }; }; + if let Some(attr) = attr::find_by_name(&item.attrs, sym::naked) { + cx.dcx().emit_err(errors::NakedFunctionTestingAttribute { + testing_span: attr_sp, + naked_span: attr.span, + }); + return vec![Annotatable::Item(item)]; + } + // check_*_signature will report any errors in the type so compilation // will fail. We shouldn't try to expand in this case because the errors // would be spurious. |
