https://gcc.gnu.org/g:0c6c73c5317111c5ec9cf465b3f6e37fe250a449
commit 0c6c73c5317111c5ec9cf465b3f6e37fe250a449 Author: Arthur Cohen <arthur.co...@embecosm.com> Date: Wed Apr 9 14:42:08 2025 +0200 format_args: Allow extraneous commas, improve safety gcc/rust/ChangeLog: * expand/rust-macro-builtins-format-args.cc (format_args_parse_arguments): Improve safety, allow extra commas after end of argument list. gcc/testsuite/ChangeLog: * rust/compile/format_args_extra_comma.rs: New test. Diff: --- gcc/rust/expand/rust-macro-builtins-format-args.cc | 7 ++++ .../rust/compile/format_args_extra_comma.rs | 47 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc index 3015225f47ce..bb01eba9873b 100644 --- a/gcc/rust/expand/rust-macro-builtins-format-args.cc +++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc @@ -55,6 +55,8 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) if (parser.peek_current_token ()->get_id () == STRING_LITERAL) format_expr = parser.parse_literal_expr (); + rust_assert (format_expr); + // TODO(Arthur): Clean this up - if we haven't parsed a string literal but a // macro invocation, what do we do here? return a tl::unexpected? auto format_str = static_cast<AST::LiteralExpr &> (*format_expr) @@ -81,6 +83,11 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) { parser.skip_token (COMMA); + // Check in case of an extraneous comma in the args list, which is + // allowed - format_args!("fmt", arg, arg2,) + if (parser.peek_current_token ()->get_id () == last_token_id) + break; + if (parser.peek_current_token ()->get_id () == IDENTIFIER && parser.peek (1)->get_id () == EQUAL) { diff --git a/gcc/testsuite/rust/compile/format_args_extra_comma.rs b/gcc/testsuite/rust/compile/format_args_extra_comma.rs new file mode 100644 index 000000000000..fcc435c074c2 --- /dev/null +++ b/gcc/testsuite/rust/compile/format_args_extra_comma.rs @@ -0,0 +1,47 @@ +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! format_args { + () => {}; +} + +#[lang = "sized"] +trait Sized {} + +pub mod core { + pub mod fmt { + pub struct Formatter; + pub struct Result; + + pub struct Arguments<'a>; + + impl<'a> Arguments<'a> { + pub fn new_v1(_: &'a [&'static str], _: &'a [ArgumentV1<'a>]) -> Arguments<'a> { + Arguments + } + } + + pub struct ArgumentV1<'a>; + + impl<'a> ArgumentV1<'a> { + pub fn new<'b, T>(_: &'b T, _: fn(&T, &mut Formatter) -> Result) -> ArgumentV1 { + ArgumentV1 + } + } + + pub trait Display { + fn fmt(&self, _: &mut Formatter) -> Result; + } + + impl Display for i32 { + fn fmt(&self, _: &mut Formatter) -> Result { + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + Result + } + } + } +} + +fn main() { + let _formatted = format_args!("extra commas {} {}", 15, 14,); +}