diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index aff81448deae..f81d4b5b6f9b 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -12023,6 +12023,11 @@ Parser::parse_expr (int right_binding_power, if (restrictions.expr_can_be_null) { TokenId id = current_token->get_id (); + if (restrictions.stop_on_token && (id == MATCH_ARROW || id == COMMA)) + { + rust_debug ("Stopping Parsing at special token"); + return nullptr; + } if (id == SEMICOLON || id == RIGHT_PAREN || id == RIGHT_CURLY || id == RIGHT_SQUARE || id == COMMA || id == LEFT_CURLY) return nullptr; @@ -12078,6 +12083,14 @@ Parser::left_denotations (std::unique_ptr expr, while (right_binding_power < left_binding_power (current_token)) { lexer.skip_token (); + if (restrictions.stop_on_token + && (current_token->get_id () == MATCH_ARROW + || current_token->get_id () == COMMA)) + { + rust_debug ( + "Stopping parsing at restricted token in left_denotations"); + return expr; + } // FIXME attributes should generally be applied to the null denotation. expr = left_denotation (current_token, std::move (expr), @@ -12116,6 +12129,13 @@ Parser::null_denotation (const_TokenPtr tok, /* note: tok is previous character in input stream, not current one, as * parse_expr skips it before passing it in */ + if (restrictions.stop_on_token + && (tok->get_id () == MATCH_ARROW || tok->get_id () == COMMA)) + { + rust_debug ("Stopping parsing at restricted token in null_denotation"); + return nullptr; + } + /* as a Pratt parser (which works by decomposing expressions into a null * denotation and then a left denotation), null denotations handle primaries * and unary operands (but only prefix unary operands) */ diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 95c0a0b94289..471ef729a9c9 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -89,6 +89,8 @@ struct ParseRestrictions bool entered_from_unary = false; bool expr_can_be_null = false; bool expr_can_be_stmt = false; + bool stop_on_token + = false; // This is for stopping parsing at a specific token bool consume_semi = true; /* Macro invocations that are statements can expand without a semicolon after * the final statement, if it's an expression statement. */ diff --git a/gcc/testsuite/rust/compile/issue-3099.rs b/gcc/testsuite/rust/compile/issue-3099.rs new file mode 100644 index 000000000000..409cc3df9e33 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3099.rs @@ -0,0 +1,16 @@ +extern "C" { + fn printf(s: *const i8, ...); +} + +pub fn main() { + unsafe { + let value = 10; + let result = match value { + 10 => 15, + _ => 20, + }; + + let format = "Result: %d\n\0" as *const str as *const i8; + printf(format, result); + } +}