aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2023-02-01 11:40:13 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2023-02-01 11:47:28 +0100
commitcddb1f2d9f965aa6386a71369109edd61506118e (patch)
tree805aa6eeba52144e2ddd3d14c80d8a77bbc9a233
parentd12a38da686e39952e083821f1d77116f3ed91af (diff)
downloadgcc-cddb1f2d9f965aa6386a71369109edd61506118e.zip
gcc-cddb1f2d9f965aa6386a71369109edd61506118e.tar.gz
gcc-cddb1f2d9f965aa6386a71369109edd61506118e.tar.bz2
parser: Allow parsing multiple reference types
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.
-rw-r--r--gcc/rust/parse/rust-parse-impl.h33
-rw-r--r--gcc/rust/parse/rust-parse.h2
-rw-r--r--gcc/testsuite/rust/compile/multi_reference_type.rs12
3 files changed, 41 insertions, 6 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index c19fe9b..19743c6 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -9239,6 +9239,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: {
@@ -9889,14 +9890,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)
@@ -9935,6 +9932,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>
@@ -10082,7 +10102,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 5c0fcc3..2f767bb 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 0000000..5ad7d84
--- /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;
+}