Skip to content

Commit

Permalink
Unify ASTValidation::visit for ExternalFunctionItem and Function
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
0xn4utilus authored and P-E-P committed Mar 5, 2024
1 parent 1c467c0 commit 0177e3c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 17 deletions.
62 changes: 50 additions & 12 deletions gcc/rust/checks/errors/rust-ast-validation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 5 additions & 4 deletions gcc/rust/parse/rust-parse-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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> (
Expand Down
3 changes: 2 additions & 1 deletion gcc/rust/parse/rust-parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ template <typename ManagedTokenSource> class Parser
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 ();
Expand Down

0 comments on commit 0177e3c

Please sign in to comment.