diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc index 57c532486e5..0153b37ddf6 100644 --- a/gcc/rust/parse/rust-parse.cc +++ b/gcc/rust/parse/rust-parse.cc @@ -172,6 +172,8 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match, }}}; Location error_locus = match.get_match_locus (); + std::string kind_str = "fragment"; + auto &allowed_toks = follow_set[last_match.get_frag_spec ().get_kind ()]; // There are two behaviors to handle here: If the follow-up match is a token, // we want to check if it is allowed. @@ -183,16 +185,12 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match, { case AST::MacroMatch::Tok: { auto tok = static_cast (&match); - auto &allowed_toks - = follow_set[last_match.get_frag_spec ().get_kind ()]; - auto is_valid = contains (allowed_toks, tok->get_id ()); - if (!is_valid) - // FIXME: Add hint about allowed fragments - rust_error_at (tok->get_match_locus (), - "token %<%s%> is not allowed after %<%s%> fragment", - tok->get_str ().c_str (), - last_match.get_frag_spec ().as_string ().c_str ()); - return is_valid; + if (contains (allowed_toks, tok->get_id ())) + return true; + kind_str = "token `" + + std::string (get_token_description (tok->get_id ())) + "`"; + error_locus = tok->get_match_locus (); + break; } break; case AST::MacroMatch::Repetition: { @@ -219,9 +217,16 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match, break; } - // FIXME: Improve error message - rust_error_at (error_locus, "fragment not allowed after %<%s%> fragment", + rust_error_at (error_locus, "%s is not allowed after %<%s%> fragment", + kind_str.c_str (), last_match.get_frag_spec ().as_string ().c_str ()); + auto allowed_toks_str + = "`" + std::string (get_token_description (allowed_toks[0])) + "`"; + for (size_t i = 1; i < allowed_toks.size (); i++) + allowed_toks_str + += ", `" + std::string (get_token_description (allowed_toks[i])) + "`"; + + rust_inform (error_locus, "allowed tokens are %s", allowed_toks_str.c_str ()); return false; } diff --git a/gcc/testsuite/rust/compile/macro27.rs b/gcc/testsuite/rust/compile/macro27.rs index c477d979ec6..ee7833be0a6 100644 --- a/gcc/testsuite/rust/compile/macro27.rs +++ b/gcc/testsuite/rust/compile/macro27.rs @@ -1,6 +1,6 @@ macro_rules! m { ($a:expr tok) => { - // { dg-error "token .tok. is not allowed after .expr. fragment" "" { target *-*-* } .-1 } + // { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 } // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 } // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } $a diff --git a/gcc/testsuite/rust/compile/macro28.rs b/gcc/testsuite/rust/compile/macro28.rs index ff557da4f2c..3d83c08ec42 100644 --- a/gcc/testsuite/rust/compile/macro28.rs +++ b/gcc/testsuite/rust/compile/macro28.rs @@ -1,6 +1,6 @@ macro_rules! m { ($a:expr $(tok $es:expr)*) => { - // { dg-error "fragment not allowed after .expr. fragment" "" { target *-*-* } .-1 } + // { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 } // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 } // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } $a diff --git a/gcc/testsuite/rust/compile/macro29.rs b/gcc/testsuite/rust/compile/macro29.rs index b26ddb13b41..39f5021b74f 100644 --- a/gcc/testsuite/rust/compile/macro29.rs +++ b/gcc/testsuite/rust/compile/macro29.rs @@ -1,6 +1,6 @@ macro_rules! m { ($($es:expr)* tok) => { - // { dg-error "token .tok. is not allowed after .expr. fragment" "" { target *-*-* } .-1 } + // { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 } // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 } // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } $a diff --git a/gcc/testsuite/rust/compile/macro30.rs b/gcc/testsuite/rust/compile/macro30.rs index da4645a434b..35064bc0ee5 100644 --- a/gcc/testsuite/rust/compile/macro30.rs +++ b/gcc/testsuite/rust/compile/macro30.rs @@ -1,6 +1,6 @@ macro_rules! m { ($e:expr $f:expr) => { - // { dg-error "fragment not allowed after .expr. fragment" "" { target *-*-* } .-1 } + // { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 } // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 } // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } $e diff --git a/gcc/testsuite/rust/compile/macro31.rs b/gcc/testsuite/rust/compile/macro31.rs index 28d84ac43f1..6674a5fe554 100644 --- a/gcc/testsuite/rust/compile/macro31.rs +++ b/gcc/testsuite/rust/compile/macro31.rs @@ -1,6 +1,6 @@ macro_rules! m { ($($e:expr)* $($f:expr)*) => { - // { dg-error "fragment not allowed after .expr. fragment" "" { target *-*-* } .-1 } + // { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 } // { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 } // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } $e diff --git a/gcc/testsuite/rust/compile/macro35.rs b/gcc/testsuite/rust/compile/macro35.rs index a08bfd4581c..07b157b53c2 100644 --- a/gcc/testsuite/rust/compile/macro35.rs +++ b/gcc/testsuite/rust/compile/macro35.rs @@ -1,5 +1,5 @@ macro_rules! inside_matcher { - (($e:expr tok) tok) => {{}}; // { dg-error "token .tok. is not allowed after .expr. fragment" } + (($e:expr tok) tok) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" } // { dg-error "failed to parse macro matcher" "" { target *-*-* } .-1 } // { dg-error "failed to parse macro match" "" { target *-*-* } .-2 } // { dg-error "required first macro rule" "" { target *-*-* } .-3 }