Skip to content

Commit a64a5cf

Browse files
committed
macros: Do not propagate parse errors in match repetitions
Since parsing repetitions is very eager, the parser might accumulate bogus errors by trying to match more repetitions than there are. We can avoid this by clearing the parsing errors if parsing repetitions returned a valid result. This should not be an issue for previous matchers erroring out, as they would immediately return upon failure and not reach inside other match functions.
1 parent 1bb9a29 commit a64a5cf

File tree

4 files changed

+18
-6
lines changed

4 files changed

+18
-6
lines changed

gcc/rust/expand/rust-macro-expand.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,6 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser,
505505
return false;
506506
}
507507

508-
for (const auto &error : parser.get_errors ())
509-
error.emit_error ();
510-
511508
// it matches if the parser did not produce errors trying to parse that type
512509
// of item
513510
return !parser.has_errors ();
@@ -714,7 +711,13 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
714711
bool did_meet_lo_bound = match_amount >= lo_bound;
715712
bool did_meet_hi_bound = hi_bound ? match_amount <= hi_bound : true;
716713

717-
return did_meet_lo_bound && did_meet_hi_bound;
714+
// If the end-result is valid, then we can clear the parse errors: Since
715+
// repetitions are parsed eagerly, it is okay to fail in some cases
716+
auto res = did_meet_lo_bound && did_meet_hi_bound;
717+
if (res)
718+
parser.clear_errors ();
719+
720+
return res;
718721
}
719722

720723
bool

gcc/rust/parse/rust-parse.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,6 @@ template <typename ManagedTokenSource> class Parser
649649
bool done_end_of_file ();
650650

651651
void add_error (Error error) { error_table.push_back (std::move (error)); }
652-
void clear_errors () { error_table.clear (); }
653652

654653
public:
655654
// Construct parser with specified "managed" token source.
@@ -668,6 +667,8 @@ template <typename ManagedTokenSource> class Parser
668667

669668
// Returns whether any parsing errors have occurred.
670669
bool has_errors () const { return !error_table.empty (); }
670+
// Remove all parsing errors from the table
671+
void clear_errors () { error_table.clear (); }
671672

672673
// Get a reference to the list of errors encountered
673674
std::vector<Error> &get_errors () { return error_table; }

gcc/testsuite/rust/compile/macro25.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
macro_rules! valid {
2+
($($a:literal)* $i:ident) => {{}};
3+
}
4+
5+
fn main() {
6+
valid!(1 one_lit);
7+
valid!(identifier_only);
8+
valid!(1 2 two_lits);
9+
}

gcc/testsuite/rust/compile/macro9.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ fn main() -> i32 {
1212
let b = add!(15);
1313
let b = add!(15 14); // { dg-error "Failed to match any rule within macro" }
1414
let b = add!(15, 14,); // { dg-error "Failed to match any rule within macro" }
15-
// { dg-error "found unexpected token" "" { target *-*-* } .-1 }
1615

1716
0
1817
}

0 commit comments

Comments
 (0)