From: 0xn4utilus <gyanendrabanja...@gmail.com> gcc/rust/ChangeLog:
* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add external function validation support. Add ErrorCode::E0130. * parse/rust-parse-impl.h (Parser::parse_function): Parse external functions from `parse_function`. (Parser::parse_external_item): Clang format. (Parser::parse_pattern): Clang format. * parse/rust-parse.h: Add default parameter `is_external` in `parse_function`. Signed-off-by: 0xn4utilus <gyanendrabanja...@gmail.com> --- gcc/rust/checks/errors/rust-ast-validation.cc | 62 +++++++++++++++---- gcc/rust/parse/rust-parse-impl.h | 9 +-- gcc/rust/parse/rust-parse.h | 3 +- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index bf70ca5d96f..f5a97b0d350 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -122,23 +122,61 @@ ASTValidation::visit (AST::Function &function) function.get_self_param ()->get_locus (), "%<self%> parameter is only allowed in associated functions"); - if (!function.has_body ()) + if (function.is_external ()) { - if (context.back () == Context::INHERENT_IMPL - || context.back () == Context::TRAIT_IMPL) + if (function.has_body ()) + rust_error_at (function.get_locus (), "cannot have a body"); + + auto ¶ms = function.get_function_params (); + + if (params.size () == 1 && function.is_variadic ()) rust_error_at (function.get_locus (), - "associated function in %<impl%> without body"); - else if (context.back () != Context::TRAIT) - rust_error_at (function.get_locus (), "free function without a body"); + "C-variadic function must be declared with at least one " + "named argument"); + + for (auto it = params.begin (); it != params.end (); it++) + { + if (it->get ()->is_variadic () && it + 1 != params.end ()) + rust_error_at ( + it->get ()->get_locus (), + "%<...%> must be the last argument of a C-variadic function"); + + // if functional parameter + if (!it->get ()->is_self () && !it->get ()->is_variadic ()) + { + auto param = static_cast<AST::FunctionParam *> (it->get ()); + auto kind = param->get_pattern ()->get_pattern_kind (); + + if (kind != AST::Pattern::Kind::Identifier + && kind != AST::Pattern::Kind::Wildcard) + rust_error_at (it->get ()->get_locus (), ErrorCode::E0130, + "pattern not allowed in foreign function"); + } + } } - auto &function_params = function.get_function_params (); - for (auto it = function_params.begin (); it != function_params.end (); it++) + else { - if (it->get ()->is_variadic ()) - rust_error_at (it->get ()->get_locus (), - "only foreign or %<unsafe extern \"C\"%> functions may " - "be C-variadic"); + if (!function.has_body ()) + { + if (context.back () == Context::INHERENT_IMPL + || context.back () == Context::TRAIT_IMPL) + rust_error_at (function.get_locus (), + "associated function in %<impl%> without body"); + else if (context.back () != Context::TRAIT) + rust_error_at (function.get_locus (), + "free function without a body"); + } + auto &function_params = function.get_function_params (); + for (auto it = function_params.begin (); it != function_params.end (); + it++) + { + if (it->get ()->is_variadic ()) + rust_error_at ( + it->get ()->get_locus (), + "only foreign or %<unsafe extern \"C\"%> functions may " + "be C-variadic"); + } } AST::ContextualASTVisitor::visit (function); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9d9722e9714..c8a87a11766 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2908,7 +2908,8 @@ Parser<ManagedTokenSource>::parse_use_tree () template <typename ManagedTokenSource> std::unique_ptr<AST::Function> Parser<ManagedTokenSource>::parse_function (AST::Visibility vis, - AST::AttrVec outer_attrs) + AST::AttrVec outer_attrs, + bool is_external) { location_t locus = lexer.peek_token ()->get_locus (); // Get qualifiers for function if they exist @@ -2992,7 +2993,7 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis, 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)); + std::move (outer_attrs), locus, false, is_external)); } // Parses function or method qualifiers (i.e. const, unsafe, and extern). @@ -6166,6 +6167,7 @@ Parser<ManagedTokenSource>::parse_external_item () case FN_KW: return parse_external_function_item (std::move (vis), std::move (outer_attrs)); + case TYPE: return parse_external_type_item (std::move (vis), std::move (outer_attrs)); @@ -10474,8 +10476,7 @@ Parser<ManagedTokenSource>::parse_pattern () { lexer.skip_token (); alts.push_back (parse_pattern_no_alt ()); - } - while (lexer.peek_token ()->get_id () == PIPE); + } while (lexer.peek_token ()->get_id () == PIPE); /* alternates */ return std::unique_ptr<AST::Pattern> ( diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 8c8bf96eb8d..cdddfa6dff9 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -253,7 +253,8 @@ private: parse_use_decl (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr<AST::UseTree> parse_use_tree (); std::unique_ptr<AST::Function> parse_function (AST::Visibility vis, - AST::AttrVec outer_attrs); + AST::AttrVec outer_attrs, + bool is_external = false); AST::FunctionQualifiers parse_function_qualifiers (); std::vector<std::unique_ptr<AST::GenericParam>> parse_generic_params_in_angles (); -- 2.45.2