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 &params = 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

Reply via email to