aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2023-02-23 15:11:04 +0100
committerCohenArthur <arthur.cohen@embecosm.com>2023-02-27 09:52:33 +0000
commitce43f55e9976929f9ff2388c8971a65afd24e26d (patch)
tree6df3152421ed8f15efbffe46b957060dcba575cd /gcc
parent0d4a4475e9fbd972bdbcf8e0bcf6f3be3db2f00f (diff)
downloadgcc-ce43f55e9976929f9ff2388c8971a65afd24e26d.zip
gcc-ce43f55e9976929f9ff2388c8971a65afd24e26d.tar.gz
gcc-ce43f55e9976929f9ff2388c8971a65afd24e26d.tar.bz2
parser: Parse `default` impl Functions and Methods
gcc/rust/ChangeLog: * ast/rust-item.h (class Method): Add `is_default` field. (class Function): Likewise. * parse/rust-parse-impl.h (Parser::parse_item): Add nice error when parsing `default` outside of an `impl` block (Parser::parse_trait_impl_item): Allow parsing functions or methods when seeing `default`. gcc/testsuite/ChangeLog: * rust/compile/parse_invalid_specialization.rs: New test. * rust/compile/parse_specialization.rs: New test. * rust/compile/default_not_a_kw.rs: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-item.h22
-rw-r--r--gcc/rust/parse/rust-parse-impl.h127
-rw-r--r--gcc/testsuite/rust/compile/default_not_a_kw.rs2
-rw-r--r--gcc/testsuite/rust/compile/parse_invalid_specialization.rs4
-rw-r--r--gcc/testsuite/rust/compile/parse_specialization.rs11
5 files changed, 80 insertions, 86 deletions
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index ab7d323..065ca1e 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -743,6 +743,7 @@ class Method : public InherentImplItem, public TraitImplItem
std::unique_ptr<BlockExpr> function_body;
Location locus;
NodeId node_id;
+ bool is_default;
public:
// Returns whether the method is in an error state.
@@ -783,7 +784,8 @@ public:
SelfParam self_param, std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
- std::vector<Attribute> outer_attrs, Location locus)
+ std::vector<Attribute> outer_attrs, Location locus,
+ bool is_default = false)
: outer_attrs (std::move (outer_attrs)), vis (std::move (vis)),
qualifiers (std::move (qualifiers)),
method_name (std::move (method_name)),
@@ -793,7 +795,8 @@ public:
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_body (std::move (function_body)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ()->get_next_node_id ()),
+ is_default (is_default)
{}
// TODO: add constructor with less fields
@@ -803,7 +806,8 @@ public:
: outer_attrs (other.outer_attrs), vis (other.vis),
qualifiers (other.qualifiers), method_name (other.method_name),
self_param (other.self_param), function_params (other.function_params),
- where_clause (other.where_clause), locus (other.locus)
+ where_clause (other.where_clause), locus (other.locus),
+ is_default (other.is_default)
{
// guard to prevent null dereference (always required)
if (other.return_type != nullptr)
@@ -831,6 +835,7 @@ public:
function_params = other.function_params;
where_clause = other.where_clause;
locus = other.locus;
+ is_default = other.is_default;
// guard to prevent null dereference (always required)
if (other.return_type != nullptr)
@@ -1526,6 +1531,7 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem
WhereClause where_clause;
std::unique_ptr<BlockExpr> function_body;
Location locus;
+ bool is_default;
public:
std::string as_string () const override;
@@ -1548,7 +1554,8 @@ public:
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
- std::vector<Attribute> outer_attrs, Location locus)
+ std::vector<Attribute> outer_attrs, Location locus,
+ bool is_default = false)
: VisItem (std::move (vis), std::move (outer_attrs)),
qualifiers (std::move (qualifiers)),
function_name (std::move (function_name)),
@@ -1556,7 +1563,8 @@ public:
function_params (std::move (function_params)),
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
- function_body (std::move (function_body)), locus (locus)
+ function_body (std::move (function_body)), locus (locus),
+ is_default (is_default)
{}
// TODO: add constructor with less fields
@@ -1566,7 +1574,8 @@ public:
: VisItem (other), qualifiers (other.qualifiers),
function_name (other.function_name),
function_params (other.function_params),
- where_clause (other.where_clause), locus (other.locus)
+ where_clause (other.where_clause), locus (other.locus),
+ is_default (other.is_default)
{
// guard to prevent null dereference (always required)
if (other.return_type != nullptr)
@@ -1592,6 +1601,7 @@ public:
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ is_default = other.is_default;
// guard to prevent null dereference (always required)
if (other.return_type != nullptr)
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 0841db4..7807d75 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1086,6 +1086,13 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement)
return parse_vis_item (std::move (outer_attrs));
// or should this go straight to parsing union?
}
+ else if (t->get_str () == "default")
+ {
+ add_error (Error (t->get_locus (),
+ "%qs is only allowed on items within %qs blocks",
+ "default", "impl"));
+ return nullptr;
+ }
else if (t->get_str () == "macro_rules")
{
// macro_rules! macro item
@@ -5538,13 +5545,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
// parse outer attributes (if they exist)
AST::AttrVec outer_attrs = parse_outer_attributes ();
- // TODO: clean this function up, it is basically unreadable hacks
+ auto visibility = AST::Visibility::create_private ();
+ if (lexer.peek_token ()->get_id () == PUB)
+ visibility = parse_visibility ();
// branch on next token:
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case IDENTIFIER:
case SUPER:
case SELF:
case CRATE:
@@ -5552,67 +5560,20 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
// these seem to be SimplePath tokens, so this is a macro invocation
// semi
return parse_macro_invocation_semi (std::move (outer_attrs));
+ case IDENTIFIER:
+ if (lexer.peek_token ()->get_str () == "default")
+ return parse_trait_impl_function_or_method (visibility,
+ std::move (outer_attrs));
+ else
+ return parse_macro_invocation_semi (std::move (outer_attrs));
case TYPE:
- return parse_type_alias (AST::Visibility::create_private (),
- std::move (outer_attrs));
- case PUB: {
- // visibility, so not a macro invocation semi - must be constant,
- // function, or method
- AST::Visibility vis = parse_visibility ();
-
- // TODO: is a recursive call to parse_trait_impl_item better?
- switch (lexer.peek_token ()->get_id ())
- {
- case TYPE:
- return parse_type_alias (std::move (vis), std::move (outer_attrs));
- case EXTERN_TOK:
- case UNSAFE:
- case FN_TOK:
- // function or method
- return parse_trait_impl_function_or_method (std::move (vis),
- std::move (
- outer_attrs));
- case CONST:
- // lookahead to resolve production - could be function/method or
- // const item
- t = lexer.peek_token (1);
-
- switch (t->get_id ())
- {
- case IDENTIFIER:
- case UNDERSCORE:
- return parse_const_item (std::move (vis),
- std::move (outer_attrs));
- case UNSAFE:
- case EXTERN_TOK:
- case FN_TOK:
- return parse_trait_impl_function_or_method (std::move (vis),
- std::move (
- outer_attrs));
- default:
- add_error (Error (t->get_locus (),
- "unexpected token %qs in some sort of const "
- "item in trait impl",
- t->get_token_description ()));
-
- lexer.skip_token (1); // TODO: is this right thing to do?
- return nullptr;
- }
- default:
- add_error (Error (t->get_locus (),
- "unrecognised token %qs for item in trait impl",
- t->get_token_description ()));
-
- // skip?
- return nullptr;
- }
- }
+ return parse_type_alias (visibility, std::move (outer_attrs));
case EXTERN_TOK:
case UNSAFE:
case FN_TOK:
// function or method
- return parse_trait_impl_function_or_method (
- AST::Visibility::create_private (), std::move (outer_attrs));
+ return parse_trait_impl_function_or_method (visibility,
+ std::move (outer_attrs));
case CONST:
// lookahead to resolve production - could be function/method or const
// item
@@ -5622,13 +5583,12 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
{
case IDENTIFIER:
case UNDERSCORE:
- return parse_const_item (AST::Visibility::create_private (),
- std::move (outer_attrs));
+ return parse_const_item (visibility, std::move (outer_attrs));
case UNSAFE:
case EXTERN_TOK:
case FN_TOK:
- return parse_trait_impl_function_or_method (
- AST::Visibility::create_private (), std::move (outer_attrs));
+ return parse_trait_impl_function_or_method (visibility,
+ std::move (outer_attrs));
default:
add_error (Error (
t->get_locus (),
@@ -5640,13 +5600,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_item ()
}
gcc_unreachable ();
default:
- add_error (Error (t->get_locus (),
- "unrecognised token %qs for item in trait impl",
- t->get_token_description ()));
-
- // skip?
- return nullptr;
+ break;
}
+ add_error (Error (t->get_locus (),
+ "unrecognised token %qs for item in trait impl",
+ t->get_token_description ()));
+
+ // skip?
+ return nullptr;
}
/* For internal use only by parse_trait_impl_item() - splits giant method into
@@ -5665,6 +5626,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
// parse function or method qualifiers
AST::FunctionQualifiers qualifiers = parse_function_qualifiers ();
+ auto is_default = false;
+ auto t = lexer.peek_token ();
+ if (t->get_id () == IDENTIFIER && t->get_str () == "default")
+ {
+ is_default = true;
+ lexer.skip_token ();
+ }
+
skip_token (FN_TOK);
// parse function or method name
@@ -5789,21 +5758,19 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
// do actual if instead of ternary for return value optimisation
if (is_method)
{
- return std::unique_ptr<AST::Method> (
- new AST::Method (std::move (ident), std::move (qualifiers),
- std::move (generic_params), std::move (self_param),
- std::move (function_params), std::move (return_type),
- std::move (where_clause), std::move (body),
- std::move (vis), std::move (outer_attrs), locus));
+ return std::unique_ptr<AST::Method> (new AST::Method (
+ std::move (ident), std::move (qualifiers), std::move (generic_params),
+ std::move (self_param), std::move (function_params),
+ std::move (return_type), std::move (where_clause), std::move (body),
+ std::move (vis), std::move (outer_attrs), locus, is_default));
}
else
{
- return std::unique_ptr<AST::Function> (
- new AST::Function (std::move (ident), std::move (qualifiers),
- std::move (generic_params),
- std::move (function_params), std::move (return_type),
- std::move (where_clause), std::move (body),
- std::move (vis), std::move (outer_attrs), locus));
+ return std::unique_ptr<AST::Function> (new AST::Function (
+ std::move (ident), std::move (qualifiers), std::move (generic_params),
+ std::move (function_params), std::move (return_type),
+ std::move (where_clause), std::move (body), std::move (vis),
+ std::move (outer_attrs), locus, is_default));
}
}
diff --git a/gcc/testsuite/rust/compile/default_not_a_kw.rs b/gcc/testsuite/rust/compile/default_not_a_kw.rs
new file mode 100644
index 0000000..b79b39d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/default_not_a_kw.rs
@@ -0,0 +1,2 @@
+// allowed
+pub fn default() {}
diff --git a/gcc/testsuite/rust/compile/parse_invalid_specialization.rs b/gcc/testsuite/rust/compile/parse_invalid_specialization.rs
new file mode 100644
index 0000000..1ce7384
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_invalid_specialization.rs
@@ -0,0 +1,4 @@
+default fn f() {
+ // { dg-error ".default. is only allowed on items within .impl. blocks" "" { target *-*-* } .-1 }
+ // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/parse_specialization.rs b/gcc/testsuite/rust/compile/parse_specialization.rs
new file mode 100644
index 0000000..5de1f6a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_specialization.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fsyntax-only" }
+
+trait Foo {
+ fn bar();
+}
+
+struct S;
+
+impl Foo for S {
+ default fn bar() {}
+}