[committed,25/88] gccrs: parser: Allow parsing multiple reference types

Message ID 20230405140411.3016563-26-arthur.cohen@embecosm.com
State Accepted
Headers
Series [committed,01/88] gccrs: fatal_error_flag: Fix typo in error message |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Arthur Cohen April 5, 2023, 2:03 p.m. UTC
  From: Arthur Cohen <arthur.cohen@embecosm.com>

The parser now recursively tries to parse a reference type after seeing
a `&` or `&&` token.

gcc/rust/ChangeLog:

	* parse/rust-parse-impl.h (Parser::parse_type): Handle double ampersan
	properly
	(Parser::parse_reference_type): Call into `parse_reference_type_inner`
	and wrap double reference types in another `AST::ReferenceType` node
	(Parser::parse_reference_type_inner): Add parsing implementation
	which does not care about the leading token (& or  &&)
	(Parser::parse_type_no_bounds): Handle double ampersand properly
	* parse/rust-parse.h: Declare `parse_reference_type_inner`

gcc/testsuite/ChangeLog:

	* rust/compile/multi_reference_type.rs: New test.
---
 gcc/rust/parse/rust-parse-impl.h              | 33 +++++++++++++++----
 gcc/rust/parse/rust-parse.h                   |  2 ++
 .../rust/compile/multi_reference_type.rs      | 12 +++++++
 3 files changed, 41 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/multi_reference_type.rs
  

Patch

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index a0bc2e10d2f..23b033fb26e 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -9237,6 +9237,7 @@  Parser<ManagedTokenSource>::parse_type (bool save_errors)
       // raw pointer type
       return parse_raw_pointer_type ();
     case AMP: // does this also include AMP_AMP?
+    case LOGICAL_AND:
       // reference type
       return parse_reference_type ();
       case LIFETIME: {
@@ -9886,14 +9887,10 @@  Parser<ManagedTokenSource>::parse_bare_function_type (
 			       std::move (return_type), best_try_locus));
 }
 
-// Parses a reference type (mutable or immutable, with given lifetime).
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::ReferenceType>
-Parser<ManagedTokenSource>::parse_reference_type ()
+Parser<ManagedTokenSource>::parse_reference_type_inner (Location locus)
 {
-  Location locus = lexer.peek_token ()->get_locus ();
-  skip_token (AMP);
-
   // parse optional lifetime
   AST::Lifetime lifetime = AST::Lifetime::error ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
@@ -9932,6 +9929,29 @@  Parser<ManagedTokenSource>::parse_reference_type ()
 			    std::move (lifetime)));
 }
 
+// Parses a reference type (mutable or immutable, with given lifetime).
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::ReferenceType>
+Parser<ManagedTokenSource>::parse_reference_type ()
+{
+  auto t = lexer.peek_token ();
+  auto locus = t->get_locus ();
+
+  switch (t->get_id ())
+    {
+    case AMP:
+      skip_token (AMP);
+      return parse_reference_type_inner (locus);
+    case LOGICAL_AND:
+      skip_token (LOGICAL_AND);
+      return std::unique_ptr<AST::ReferenceType> (
+	new AST::ReferenceType (false, parse_reference_type_inner (locus),
+				locus));
+    default:
+      gcc_unreachable ();
+    }
+}
+
 // Parses a raw (unsafe) pointer type.
 template <typename ManagedTokenSource>
 std::unique_ptr<AST::RawPointerType>
@@ -10079,7 +10099,8 @@  Parser<ManagedTokenSource>::parse_type_no_bounds ()
     case ASTERISK:
       // raw pointer type
       return parse_raw_pointer_type ();
-    case AMP: // does this also include AMP_AMP?
+    case AMP: // does this also include AMP_AMP? Yes! Which is... LOGICAL_AND?
+    case LOGICAL_AND:
       // reference type
       return parse_reference_type ();
     case LIFETIME:
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 5c0fcc3f174..2f767bb2a53 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -604,6 +604,8 @@  private:
   std::unique_ptr<AST::TypeNoBounds> parse_type_no_bounds ();
   std::unique_ptr<AST::TypeNoBounds> parse_slice_or_array_type ();
   std::unique_ptr<AST::RawPointerType> parse_raw_pointer_type ();
+  std::unique_ptr<AST::ReferenceType>
+  parse_reference_type_inner (Location locus);
   std::unique_ptr<AST::ReferenceType> parse_reference_type ();
   std::unique_ptr<AST::BareFunctionType>
   parse_bare_function_type (std::vector<AST::LifetimeParam> for_lifetimes);
diff --git a/gcc/testsuite/rust/compile/multi_reference_type.rs b/gcc/testsuite/rust/compile/multi_reference_type.rs
new file mode 100644
index 00000000000..5ad7d84adbc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/multi_reference_type.rs
@@ -0,0 +1,12 @@ 
+fn main() {
+    let a = 15u8;
+    let a: &u8 = &a;
+    let a: &&u8 = &a;
+    let a: &&&u8 = &a;
+    let _: &&&&u8 = &a;
+
+    let _: &&u8;
+    let _: &mut &u8;
+    let _: &&mut u8;
+    let _: &mut &mut &u8;
+}