aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/expand/rust-macro-expand.cc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-03-23 09:28:09 +0000
committerGitHub <noreply@github.com>2022-03-23 09:28:09 +0000
commiteef1ee2638c73e35cc804c2d4ab42598dccea8ac (patch)
tree49e8cb28376b9059702bad0b2ead1fa054ad583b /gcc/rust/expand/rust-macro-expand.cc
parentb9720caa100efa6758a5f0d54d3764072d83be41 (diff)
parentef5638186202daac03feed7a20eb975991965403 (diff)
downloadgcc-eef1ee2638c73e35cc804c2d4ab42598dccea8ac.zip
gcc-eef1ee2638c73e35cc804c2d4ab42598dccea8ac.tar.gz
gcc-eef1ee2638c73e35cc804c2d4ab42598dccea8ac.tar.bz2
Merge #1049
1049: Add better restrictions around semicolons in statements r=CohenArthur a=CohenArthur When parsing macro invocations, rustc does not actually consume the statement's trailing semicolon. Let's take the following example: ```rust macro_rules! one_stmt { ($s:stmt) => {}; } macro_rules! one_or_more_stmt { ($($s:stmt)*) => {}; } one_stmt!(let a = 1); one_stmt!(let b = 2;); // error one_or_more_stmt!(;); // valid one_or_more_stmt!(let a = 15;); // valid, two statements! one_or_more_stmt!(let a = 15 let b = 13); // valid, two statements again ``` A semicolon can count as a valid empty statement, but cannot be part of a statement (in macro invocations). This commit adds more restrictions that allow the parser to not always expect a semicolon token after the statement. Furthermore, this fixes a test that was previously accepted by the compiler but not by rustc. Fixes #1046 Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc/rust/expand/rust-macro-expand.cc')
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc16
1 files changed, 11 insertions, 5 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index fbcc8f3..e0dfc50 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -477,9 +477,12 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser,
parser.parse_visibility ();
break;
- case AST::MacroFragSpec::STMT:
- parser.parse_stmt (/* allow_no_semi */ true);
- break;
+ case AST::MacroFragSpec::STMT: {
+ auto restrictions = ParseRestrictions ();
+ restrictions.consume_semi = false;
+ parser.parse_stmt (restrictions);
+ break;
+ }
case AST::MacroFragSpec::LIFETIME:
parser.parse_lifetime_params ();
@@ -887,11 +890,14 @@ transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
static std::vector<AST::SingleASTNode>
transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
+ auto restrictions = ParseRestrictions ();
+ restrictions.consume_semi = false;
+
// FIXME: This is invalid! It needs to also handle cases where the macro
// transcriber is an expression, but since the macro call is followed by
// a semicolon, it's a valid ExprStmt
- return parse_many (parser, delimiter, [&parser] () {
- auto stmt = parser.parse_stmt (/* allow_no_semi */ true);
+ return parse_many (parser, delimiter, [&parser, restrictions] () {
+ auto stmt = parser.parse_stmt (restrictions);
return AST::SingleASTNode (std::move (stmt));
});
}