]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Insert empty repeated metavars for nested repetitions
authorOwen Avery <powerboat9.gamer@gmail.com>
Wed, 7 Jun 2023 16:26:37 +0000 (12:26 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:46:30 +0000 (18:46 +0100)
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>
gcc/rust/expand/rust-macro-expand.cc
gcc/rust/expand/rust-macro-expand.h
gcc/testsuite/rust/compile/macro-issue2268.rs [new file with mode: 0644]

index 27a298efc308725947d7f33f62a92249720b6a94..0d8b930cb581826de57bfc9ee390e5fb7de52121 100644 (file)
@@ -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)
@@ -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;
 }
index ce8d0f2c7d4a36e46c6730654b00cd50a0bbcddf..378a7e25f509a18389611fa13fd8ab0f1b7e8e87 100644 (file)
@@ -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);
 
diff --git a/gcc/testsuite/rust/compile/macro-issue2268.rs b/gcc/testsuite/rust/compile/macro-issue2268.rs
new file mode 100644 (file)
index 0000000..4bd9c10
--- /dev/null
@@ -0,0 +1,5 @@
+macro_rules! foo {
+    ($(+ $($a:ident)*)*) => {$($($a)*)*}
+}
+
+foo!();