From 0424f016cb0076a20dcc2065e146ac68067245c5 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 18 Sep 2025 16:08:30 +0200 Subject: [PATCH 1/3] Prevent segfault on builtin metavars Builtin metavars are not in the fragment, the compiler should not emit an error message. gcc/rust/ChangeLog: * expand/rust-macro-substitute-ctx.cc (is_builtin_metavariable): Add function to check builtin metavars knowledge. (SubstituteCtx::check_repetition_amount): Do not process missing fragment. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/expand/rust-macro-substitute-ctx.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index ac36ed8b0451..0b78fa535cb7 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -108,6 +108,12 @@ SubstituteCtx::substitute_metavar ( return true; } +static bool +is_builtin_metavariable (AST::Token &token) +{ + return token.get_id () == CRATE; +} + bool SubstituteCtx::check_repetition_amount (size_t pattern_start, size_t pattern_end, @@ -125,6 +131,10 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start, || frag_token->get_id () == IDENTIFIER) { auto it = fragments.find (frag_token->get_str ()); + + if (is_builtin_metavariable (*frag_token)) + continue; + if (it == fragments.end ()) { // If the repetition is not anything we know (ie no declared @@ -136,6 +146,7 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start, frag_token->get_str ().c_str ()); is_valid = false; + continue; } auto &fragment = *it->second; From 164ee118fd1abe57ca672c261e2b56621e20b840 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 18 Sep 2025 16:57:15 +0200 Subject: [PATCH 2/3] Emit errors from the transcriber when they occur Emitting the errors later means some error could be emitted multiple times. gcc/rust/ChangeLog: * expand/rust-macro-expand.cc (transcribe_expression): Emit error early. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/expand/rust-macro-expand.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 662cc61fb860..ec4f666dc7b3 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -963,7 +963,11 @@ transcribe_expression (Parser &parser) auto attrs = parser.parse_outer_attributes (); auto expr = parser.parse_expr (std::move (attrs)); if (expr == nullptr) - return AST::Fragment::create_error (); + { + for (auto error : parser.get_errors ()) + error.emit (); + return AST::Fragment::create_error (); + } // FIXME: make this an error for some edititons if (parser.peek_current_token ()->get_id () == SEMICOLON) @@ -1152,11 +1156,7 @@ MacroExpander::transcribe_rule ( // emit any errors if (parser.has_errors ()) - { - for (auto &err : parser.get_errors ()) - rust_error_at (err.locus, "%s", err.message.c_str ()); - return AST::Fragment::create_error (); - } + return AST::Fragment::create_error (); // are all the tokens used? bool did_delimit = parser.skip_token (last_token_id); From 47aefd705b8d4b634e4466997f393062b7c8264e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 18 Sep 2025 17:47:54 +0200 Subject: [PATCH 3/3] Add origin location to expanded tokens gcc/rust/ChangeLog: * expand/rust-macro-expand.cc: Forward invocation tree locus to substitution context. * expand/rust-macro-substitute-ctx.cc: Use origin location for expanded tokens. * expand/rust-macro-substitute-ctx.h (class SubstituteCtx): Save invocation location. gcc/testsuite/ChangeLog: * rust/compile/macros/mbe/macro58.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/expand/rust-macro-expand.cc | 5 +++-- gcc/rust/expand/rust-macro-substitute-ctx.cc | 8 ++++---- gcc/rust/expand/rust-macro-substitute-ctx.h | 6 ++++-- gcc/testsuite/rust/compile/macros/mbe/macro58.rs | 12 ++++++++++++ 4 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/rust/compile/macros/mbe/macro58.rs diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index ec4f666dc7b3..52f8e2b10e33 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -1108,8 +1108,9 @@ MacroExpander::transcribe_rule ( auto invoc_stream = invoc_token_tree.to_token_stream (); auto macro_rule_tokens = transcribe_tree.to_token_stream (); - auto substitute_context = SubstituteCtx (invoc_stream, macro_rule_tokens, - matched_fragments, definition); + auto substitute_context + = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments, + definition, invoc_token_tree.get_locus ()); std::vector> substituted_tokens = substitute_context.substitute_tokens (); diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 0b78fa535cb7..36bae5bf45ac 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -40,7 +40,7 @@ SubstituteCtx::substitute_dollar_crate ( if (*def_crate == current_crate) { expanded.push_back (std::make_unique ( - Rust::Token::make_identifier (UNKNOWN_LOCATION, "crate"))); + Rust::Token::make_identifier (origin, "crate"))); } else { @@ -49,9 +49,9 @@ SubstituteCtx::substitute_dollar_crate ( rust_assert (name); expanded.push_back (std::make_unique ( - Rust::Token::make (SCOPE_RESOLUTION, UNKNOWN_LOCATION))); + Rust::Token::make (SCOPE_RESOLUTION, origin))); expanded.push_back (std::make_unique ( - Rust::Token::make_identifier (UNKNOWN_LOCATION, std::string (*name)))); + Rust::Token::make_identifier (origin, std::string (*name)))); } return true; @@ -237,7 +237,7 @@ SubstituteCtx::substitute_repetition ( } auto substitute_context - = SubstituteCtx (input, new_macro, sub_map, definition); + = SubstituteCtx (input, new_macro, sub_map, definition, origin); auto new_tokens = substitute_context.substitute_tokens (); // Skip the first repetition, but add the separator to the expanded diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h index c5c4956bc8e8..3829a5a81fa0 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.h +++ b/gcc/rust/expand/rust-macro-substitute-ctx.h @@ -27,6 +27,8 @@ class SubstituteCtx std::vector> ¯o; std::map &fragments; AST::MacroRulesDefinition &definition; + // Macro invocation location + location_t origin; /** * Find the repetition amount to use when expanding a repetition, and @@ -43,9 +45,9 @@ class SubstituteCtx SubstituteCtx (std::vector> &input, std::vector> ¯o, std::map &fragments, - AST::MacroRulesDefinition &definition) + AST::MacroRulesDefinition &definition, location_t origin) : input (input), macro (macro), fragments (fragments), - definition (definition) + definition (definition), origin (origin) {} /** diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro58.rs b/gcc/testsuite/rust/compile/macros/mbe/macro58.rs new file mode 100644 index 000000000000..d8f75995e576 --- /dev/null +++ b/gcc/testsuite/rust/compile/macros/mbe/macro58.rs @@ -0,0 +1,12 @@ +pub fn print(a: *const u8) {} +#[macro_export] +macro_rules! pr_warn ( + ($($arg:tt)*) => ( + $($crate::print($arg))* + ) +); + +fn main() { + pr_warn!("test\0", "test\0"); + // { dg-error "expecting .;. but .identifier. found" "" { target *-*-* } .-1 } +}