public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
From: Arthur Cohen <arthur.cohen@embecosm.com>
To: gcc-patches@gcc.gnu.org
Cc: gcc-rust@gcc.gnu.org, Arthur Cohen <arthur.cohen@embecosm.com>
Subject: [COMMITTED] gccrs: macros: Handle matchers properly in repetitions
Date: Tue, 31 Jan 2023 14:24:41 +0100	[thread overview]
Message-ID: <20230131132441.661608-1-arthur.cohen@embecosm.com> (raw)

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	other threads:[~2023-01-31 13:20 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230131132441.661608-1-arthur.cohen@embecosm.com \
    --to=arthur.cohen@embecosm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=gcc-rust@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).