Skip parameter names in procedure type expressions
This commit is contained in:
@ -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(¶meter_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(¶meter->position()), PARM_DECL,
|
||||
get_identifier(parameter->identifier.c_str()), function_args_iter_cond(¶meter_type));
|
||||
get_identifier(parameter_name->c_str()), function_args_iter_cond(¶meter_type));
|
||||
DECL_CONTEXT(declaration_tree) = fndecl;
|
||||
DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(¶meter_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(¶meter_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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user