gcc/rust/ChangeLog:

        * expand/rust-macro-expand.cc (MacroExpander::match_matcher): Handle
        fragments differently based on whether or not we are currently trying
        to match a matcher in a repetition context.
        (MacroExpander::match_n_matches): Use new `in_repetition` argument
        properly when calling `match_matcher`.
        * expand/rust-macro-expand.h (MacroExpander::match_matcher): Allow
        passing extra `in_repetition` bool argument

gcc/testsuite/ChangeLog:

        * rust/compile/macro43.rs: New test.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/rust/expand/rust-macro-expand.cc  | 14 +++---
 gcc/rust/expand/rust-macro-expand.h   |  2 +-
 gcc/testsuite/rust/compile/macro43.rs | 64 +++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/macro43.rs

diff --git a/gcc/rust/expand/rust-macro-expand.cc 
b/gcc/rust/expand/rust-macro-expand.cc
index a214ca906bf..df258bd96ec 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -435,7 +435,7 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> 
&parser,
 
 bool
 MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
-                             AST::MacroMatcher &matcher)
+                             AST::MacroMatcher &matcher, bool in_repetition)
 {
   if (depth_exceeds_recursion_limit ())
     {
@@ -485,8 +485,12 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> 
&parser,
 
            // matched fragment get the offset in the token stream
            size_t offs_end = source.get_offs ();
-           sub_stack.insert_metavar (
-             MatchedFragment (fragment->get_ident (), offs_begin, offs_end));
+           if (in_repetition)
+             sub_stack.append_fragment (
+               MatchedFragment (fragment->get_ident (), offs_begin, offs_end));
+           else
+             sub_stack.insert_metavar (
+               MatchedFragment (fragment->get_ident (), offs_begin, offs_end));
          }
          break;
 
@@ -509,7 +513,7 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> 
&parser,
            AST::MacroMatcher *m
              = static_cast<AST::MacroMatcher *> (match.get ());
            expansion_depth++;
-           if (!match_matcher (parser, *m))
+           if (!match_matcher (parser, *m, in_repetition))
              {
                expansion_depth--;
                return false;
@@ -619,7 +623,7 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> 
&parser,
              case AST::MacroMatch::MacroMatchType::Matcher: {
                AST::MacroMatcher *m
                  = static_cast<AST::MacroMatcher *> (match.get ());
-               valid_current_match = match_matcher (parser, *m);
+               valid_current_match = match_matcher (parser, *m, true);
              }
              break;
            }
diff --git a/gcc/rust/expand/rust-macro-expand.h 
b/gcc/rust/expand/rust-macro-expand.h
index 97a02692d1f..bef140236b3 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -273,7 +273,7 @@ struct MacroExpander
                         AST::MacroMatchRepetition &rep);
 
   bool match_matcher (Parser<MacroInvocLexer> &parser,
-                     AST::MacroMatcher &matcher);
+                     AST::MacroMatcher &matcher, bool in_repetition = false);
 
   /**
    * Match any amount of matches
diff --git a/gcc/testsuite/rust/compile/macro43.rs 
b/gcc/testsuite/rust/compile/macro43.rs
new file mode 100644
index 00000000000..c7bf50a030e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro43.rs
@@ -0,0 +1,64 @@
+macro_rules! nonzero_integers {
+    ( $( $Ty: ident($Int: ty); )+ ) => {
+        $(
+            /// An integer that is known not to equal zero.
+            ///
+            /// This enables some memory layout optimization.
+            /// For example, `Option<NonZeroU32>` is the same size as `u32`:
+            ///
+            /// ```rust
+            /// use std::mem::size_of;
+            /// assert_eq!(size_of::<Option<std::num::NonZeroU32>>(), 
size_of::<u32>());
+            /// ```
+            #[stable(feature = "nonzero", since = "1.28.0")]
+            #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+            #[repr(transparent)]
+            pub struct $Ty(NonZero<$Int>);
+
+            impl $Ty {
+                /// Create a non-zero without checking the value.
+                ///
+                /// # Safety
+                ///
+                /// The value must not be zero.
+                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[inline]
+                pub const unsafe fn new_unchecked(n: $Int) -> Self {
+                    $Ty(NonZero(n))
+                }
+
+                /// Create a non-zero if the given value is not zero.
+                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[inline]
+                pub fn new(n: $Int) -> Option<Self> {
+                    if n != 0 {
+                        Some($Ty(NonZero(n)))
+                    } else {
+                        None
+                    }
+                }
+
+                /// Returns the value as a primitive type.
+                #[stable(feature = "nonzero", since = "1.28.0")]
+                #[inline]
+                pub fn get(self) -> $Int {
+                    self.0 .0
+                }
+
+            }
+
+            impl_nonzero_fmt! { // { dg-error "unknown macro" }
+                (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
+            }
+        )+
+    }
+}
+
+nonzero_integers! {
+    NonZeroU8(u8);
+    NonZeroU16(u16);
+    NonZeroU32(u32);
+    NonZeroU64(u64);
+    NonZeroU128(u128);
+    NonZeroUsize(usize);
+}
-- 
2.39.1

Reply via email to