Skip parameter names in procedure type expressions

This commit is contained in:
2025-03-18 11:37:10 +01:00
parent 6eb4e91b2c
commit 5e8555b4f4
20 changed files with 469 additions and 490 deletions

View File

@ -34,9 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const.h"
#include "langhooks.h"
namespace elna
{
namespace gcc
namespace elna::gcc
{
tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols)
{
@ -317,7 +315,7 @@ namespace gcc
tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
this->symbols->enter(definition->identifier, fndecl);
if (definition->heading().no_return)
if (definition->heading().return_type.no_return)
{
TREE_THIS_VOLATILE(fndecl) = 1;
}
@ -336,19 +334,22 @@ namespace gcc
function_args_iterator parameter_type;
function_args_iter_init(&parameter_type, declaration_type);
for (const boot::variable_declaration *parameter : definition->heading().parameters)
std::vector<std::string>::const_iterator parameter_name = definition->parameter_names.cbegin();
for (std::shared_ptr<boot::type_expression> parameter : definition->heading().parameters)
{
tree declaration_tree = build_decl(get_location(&parameter->position()), PARM_DECL,
get_identifier(parameter->identifier.c_str()), function_args_iter_cond(&parameter_type));
get_identifier(parameter_name->c_str()), function_args_iter_cond(&parameter_type));
DECL_CONTEXT(declaration_tree) = fndecl;
DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(&parameter_type);
if (definition->body != nullptr)
{
this->symbols->enter(parameter->identifier, declaration_tree);
this->symbols->enter(*parameter_name, declaration_tree);
}
argument_chain = chainon(argument_chain, declaration_tree);
function_args_iter_next(&parameter_type);
++parameter_name;
}
DECL_ARGUMENTS(fndecl) = argument_chain;
TREE_PUBLIC(fndecl) = definition->exported;
@ -409,17 +410,17 @@ namespace gcc
return bind_expr;
}
void generic_visitor::visit(boot::number_literal<std::int32_t> *literal)
void generic_visitor::visit(boot::literal<std::int32_t> *literal)
{
this->current_expression = build_int_cst(elna_int_type_node, literal->value);
}
void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal)
void generic_visitor::visit(boot::literal<std::uint32_t> *literal)
{
this->current_expression = build_int_cstu(elna_word_type_node, literal->value);
}
void generic_visitor::visit(boot::number_literal<double> *literal)
void generic_visitor::visit(boot::literal<double> *literal)
{
REAL_VALUE_TYPE real_value1;
@ -434,22 +435,22 @@ namespace gcc
mpfr_clear(number);
}
void generic_visitor::visit(boot::number_literal<bool> *boolean)
void generic_visitor::visit(boot::literal<bool> *boolean)
{
this->current_expression = boolean->value ? boolean_true_node : boolean_false_node;
}
void generic_visitor::visit(boot::number_literal<unsigned char> *character)
void generic_visitor::visit(boot::literal<unsigned char> *character)
{
this->current_expression = build_int_cstu(elna_char_type_node, character->value);
}
void generic_visitor::visit(boot::number_literal<nullptr_t> *)
void generic_visitor::visit(boot::literal<nullptr_t> *)
{
this->current_expression = elna_pointer_nil_node;
}
void generic_visitor::visit(boot::number_literal<std::string> *string)
void generic_visitor::visit(boot::literal<std::string> *string)
{
tree index_constant = build_int_cstu(elna_word_type_node, string->value.size());
tree string_type = build_array_type(elna_char_type_node, build_index_type(index_constant));
@ -779,15 +780,14 @@ namespace gcc
for (std::size_t i = 0; i < type.parameters.size(); ++i)
{
boot::type_expression& parameter_type = type.parameters.at(i)->variable_type();
parameter_type.accept(this);
type.parameters.at(i)->accept(this);
parameter_types[i] = this->current_expression;
}
tree return_type = void_type_node;
if (type.return_type != nullptr)
if (type.return_type.type != nullptr)
{
type.return_type->accept(this);
type.return_type.type->accept(this);
return_type = this->current_expression;
}
this->current_expression = NULL_TREE;
@ -924,32 +924,105 @@ namespace gcc
}
}
bool generic_visitor::expect_trait_type_only(boot::traits_expression *trait)
{
if (trait->parameters.size() != 1)
{
error_at(get_location(&trait->position()), "Trait '%s' expects 1 argument, got %lu",
trait->name.c_str(), trait->parameters.size());
this->current_expression = error_mark_node;
return false;
}
trait->parameters.front()->accept(this);
return this->current_expression != error_mark_node;
}
bool generic_visitor::expect_trait_for_integral_type(boot::traits_expression *trait)
{
if (!expect_trait_type_only(trait))
{
return false;
}
else if (!is_integral_type(this->current_expression))
{
error_at(get_location(&trait->position()), "Type '%s' does not support trait '%s'",
print_type(this->current_expression).c_str(), trait->name.c_str());
this->current_expression = error_mark_node;
return false;
}
return true;
}
void generic_visitor::visit(boot::traits_expression *trait)
{
trait->type().accept(this);
location_t trait_location = get_location(&trait->position());
if (trait->name == "size")
{
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node,
size_in_bytes(this->current_expression));
if (expect_trait_type_only(trait))
{
this->current_expression = build1_loc(trait_location, CONVERT_EXPR, elna_word_type_node,
size_in_bytes(this->current_expression));
}
}
else if (trait->name == "alignment")
{
this->current_expression = build_int_cstu(elna_word_type_node,
TYPE_ALIGN_UNIT(this->current_expression));
if (expect_trait_type_only(trait))
{
this->current_expression = build_int_cstu(elna_word_type_node,
TYPE_ALIGN_UNIT(this->current_expression));
}
}
else if (trait->name == "min" && is_integral_type(this->current_expression))
else if (trait->name == "min")
{
this->current_expression = TYPE_MIN_VALUE(this->current_expression);
if (expect_trait_for_integral_type(trait))
{
this->current_expression = TYPE_MIN_VALUE(this->current_expression);
}
}
else if (trait->name == "max" && is_integral_type(this->current_expression))
else if (trait->name == "max")
{
this->current_expression = TYPE_MAX_VALUE(this->current_expression);
if (expect_trait_for_integral_type(trait))
{
this->current_expression = TYPE_MAX_VALUE(this->current_expression);
}
}
else if (trait->name == "offset")
{
if (trait->parameters.size() != 2)
{
error_at(trait_location, "Trait '%s' expects 2 arguments, got %lu",
trait->name.c_str(), trait->parameters.size());
this->current_expression = error_mark_node;
return;
}
trait->parameters.front()->accept(this);
auto field_type = trait->parameters.at(1)->is_primitive();
if (field_type == nullptr)
{
error_at(trait_location,
"The second argument to the offset trait is expected to be a field name,"
"got a type expression");
this->current_expression = error_mark_node;
return;
}
tree field_declaration = find_field_by_name(trait_location, this->current_expression, field_type->name);
if (field_declaration != error_mark_node)
{
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node,
byte_position(field_declaration));
}
else
{
this->current_expression = error_mark_node;
}
}
else
{
error_at(get_location(&trait->position()), "type '%s' does not have property '%s'",
print_type(this->current_expression).c_str(), trait->name.c_str());
error_at(get_location(&trait->position()), "Trait '%s' is unknown", trait->name.c_str());
this->current_expression = error_mark_node;
}
}
@ -958,41 +1031,14 @@ namespace gcc
{
expression->base().accept(this);
location_t expression_location = get_location(&expression->position());
tree field_declaration = find_field_by_name(expression_location,
TREE_TYPE(this->current_expression), expression->field());
if (is_aggregate_type(TREE_TYPE(this->current_expression)))
if (field_declaration != error_mark_node)
{
tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression));
while (field_declaration != NULL_TREE)
{
tree declaration_name = DECL_NAME(field_declaration);
const char *identifier_pointer = IDENTIFIER_POINTER(declaration_name);
if (expression->field() == identifier_pointer)
{
break;
}
field_declaration = TREE_CHAIN(field_declaration);
}
if (field_declaration == NULL_TREE)
{
error_at(expression_location,
"record type does not have a field named '%s'",
expression->field().c_str());
this->current_expression = error_mark_node;
}
else
{
this->current_expression = build3_loc(expression_location, COMPONENT_REF,
TREE_TYPE(field_declaration), this->current_expression,
field_declaration, NULL_TREE);
}
}
else
{
error_at(expression_location, "type '%s' does not have a field named '%s'",
print_type(TREE_TYPE(this->current_expression)).c_str(), expression->field().c_str());
this->current_expression = error_mark_node;
this->current_expression = build3_loc(expression_location, COMPONENT_REF,
TREE_TYPE(field_declaration), this->current_expression,
field_declaration, NULL_TREE);
}
}
@ -1226,4 +1272,3 @@ namespace gcc
defer(leave_scope());
}
}
}