Skip to content

Commit

Permalink
Insert empty repeated metavars for nested repetitions
Browse files Browse the repository at this point in the history
gcc/rust/ChangeLog:

	* expand/rust-macro-expand.cc
	(MacroExpander::match_repetition_skipped_metavars): New.
	(MacroExpander::match_repetition): Use new method.
	* expand/rust-macro-expand.h
	(MacroExpander::match_repetition_skipped_metavars): New.

gcc/testsuite/ChangeLog:

	* rust/compile/macro-issue2268.rs: New test.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
  • Loading branch information
powerboat9 authored and CohenArthur committed Jun 27, 2023
1 parent 5711a2a commit 2983beb
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 18 deletions.
75 changes: 57 additions & 18 deletions gcc/rust/expand/rust-macro-expand.cc
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,62 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
return res;
}

/*
* Helper function for defining unmatched repetition metavars
*/
void
MacroExpander::match_repetition_skipped_metavars (AST::MacroMatch &match)
{
// We have to handle zero fragments differently: They will not have been
// "matched" but they are still valid and should be inserted as a special
// case. So we go through the stack map, and for every fragment which doesn't
// exist, insert a zero-matched fragment.
switch (match.get_macro_match_type ())
{
case AST::MacroMatch::MacroMatchType::Fragment:
match_repetition_skipped_metavars (
static_cast<AST::MacroMatchFragment &> (match));
break;
case AST::MacroMatch::MacroMatchType::Repetition:
match_repetition_skipped_metavars (
static_cast<AST::MacroMatchRepetition &> (match));
break;
case AST::MacroMatch::MacroMatchType::Matcher:
match_repetition_skipped_metavars (
static_cast<AST::MacroMatcher &> (match));
break;
case AST::MacroMatch::MacroMatchType::Tok:
break;
}
}

void
MacroExpander::match_repetition_skipped_metavars (
AST::MacroMatchFragment &fragment)
{
auto &stack_map = sub_stack.peek ();
auto it = stack_map.find (fragment.get_ident ());

if (it == stack_map.end ())
sub_stack.insert_matches (fragment.get_ident (),
MatchedFragmentContainer::zero ());
}

void
MacroExpander::match_repetition_skipped_metavars (
AST::MacroMatchRepetition &rep)
{
for (auto &match : rep.get_matches ())
match_repetition_skipped_metavars (*match);
}

void
MacroExpander::match_repetition_skipped_metavars (AST::MacroMatcher &rep)
{
for (auto &match : rep.get_matches ())
match_repetition_skipped_metavars (*match);
}

bool
MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
AST::MacroMatchRepetition &rep)
Expand Down Expand Up @@ -703,24 +759,7 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
res ? "successfully" : "unsuccessfully",
(unsigned long) match_amount);

// We have to handle zero fragments differently: They will not have been
// "matched" but they are still valid and should be inserted as a special
// case. So we go through the stack map, and for every fragment which doesn't
// exist, insert a zero-matched fragment.
auto &stack_map = sub_stack.peek ();
for (auto &match : rep.get_matches ())
{
if (match->get_macro_match_type ()
== AST::MacroMatch::MacroMatchType::Fragment)
{
auto fragment = static_cast<AST::MacroMatchFragment *> (match.get ());
auto it = stack_map.find (fragment->get_ident ());

if (it == stack_map.end ())
sub_stack.insert_matches (fragment->get_ident (),
MatchedFragmentContainer::zero ());
}
}
match_repetition_skipped_metavars (rep);

return res;
}
Expand Down
5 changes: 5 additions & 0 deletions gcc/rust/expand/rust-macro-expand.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ struct MacroExpander

bool match_token (Parser<MacroInvocLexer> &parser, AST::Token &token);

void match_repetition_skipped_metavars (AST::MacroMatch &);
void match_repetition_skipped_metavars (AST::MacroMatchFragment &);
void match_repetition_skipped_metavars (AST::MacroMatchRepetition &);
void match_repetition_skipped_metavars (AST::MacroMatcher &);

bool match_repetition (Parser<MacroInvocLexer> &parser,
AST::MacroMatchRepetition &rep);

Expand Down
5 changes: 5 additions & 0 deletions gcc/testsuite/rust/compile/macro-issue2268.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
macro_rules! foo {
($(+ $($a:ident)*)*) => {$($($a)*)*}
}

foo!();

0 comments on commit 2983beb

Please sign in to comment.