Use colon instead of as to cast
This commit is contained in:
@ -43,6 +43,94 @@ namespace gcc
|
||||
this->symbol_map = symbol_table;
|
||||
}
|
||||
|
||||
void generic_visitor::build_procedure_call(location_t call_location,
|
||||
tree symbol, const std::vector<boot::expression *>& arguments)
|
||||
{
|
||||
vec<tree, va_gc> *argument_trees = nullptr;
|
||||
tree current_parameter = TYPE_ARG_TYPES(TREE_TYPE(symbol));
|
||||
|
||||
vec_alloc(argument_trees, arguments.size());
|
||||
for (boot::expression *const argument : arguments)
|
||||
{
|
||||
location_t argument_location = get_location(&argument->position());
|
||||
if (is_void_type(TREE_VALUE(current_parameter)))
|
||||
{
|
||||
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
||||
list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
break;
|
||||
}
|
||||
argument->accept(this);
|
||||
if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
|
||||
{
|
||||
error_at(argument_location,
|
||||
"cannot assign value of type '%s' to variable of type '%s'",
|
||||
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||
print_type(TREE_VALUE(current_parameter)).c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
current_parameter = TREE_CHAIN(current_parameter);
|
||||
argument_trees->quick_push(this->current_expression);
|
||||
}
|
||||
tree stmt = build_call_expr_loc_vec(call_location, symbol, argument_trees);
|
||||
|
||||
if (!is_void_type(TREE_VALUE(current_parameter)))
|
||||
{
|
||||
error_at(call_location, "too few arguments, expected %i, got %lu",
|
||||
list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
else if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
|
||||
{
|
||||
append_statement(stmt);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = stmt;
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::build_record_call(location_t call_location,
|
||||
tree symbol, const std::vector<boot::expression *>& arguments)
|
||||
{
|
||||
vec<constructor_elt, va_gc> *tree_arguments = nullptr;
|
||||
tree record_fields = TYPE_FIELDS(symbol);
|
||||
for (boot::expression *const argument : arguments)
|
||||
{
|
||||
location_t argument_location = get_location(&argument->position());
|
||||
|
||||
if (is_void_type(record_fields))
|
||||
{
|
||||
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
||||
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
break;
|
||||
}
|
||||
argument->accept(this);
|
||||
if (!is_assignable_from(TREE_TYPE(record_fields), this->current_expression))
|
||||
{
|
||||
error_at(argument_location,
|
||||
"cannot assign value of type '%s' to variable of type '%s'",
|
||||
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||
print_type(TREE_TYPE(record_fields)).c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
CONSTRUCTOR_APPEND_ELT(tree_arguments, record_fields, this->current_expression);
|
||||
record_fields = TREE_CHAIN(record_fields);
|
||||
}
|
||||
if (!is_void_type(record_fields))
|
||||
{
|
||||
error_at(call_location, "too few arguments, expected %i, got %lu",
|
||||
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = build_constructor(symbol, tree_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::call_expression *expression)
|
||||
{
|
||||
tree symbol = this->lookup(expression->name());
|
||||
@ -56,37 +144,11 @@ namespace gcc
|
||||
}
|
||||
else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
|
||||
{
|
||||
vec<tree, va_gc> *arguments = nullptr;
|
||||
|
||||
vec_alloc(arguments, expression->arguments().size());
|
||||
for (boot::expression *const argument : expression->arguments())
|
||||
{
|
||||
argument->accept(this);
|
||||
arguments->quick_push(this->current_expression);
|
||||
}
|
||||
tree stmt = build_call_expr_loc_vec(get_location(&expression->position()), symbol, arguments);
|
||||
|
||||
if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
|
||||
{
|
||||
append_statement(stmt);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = stmt;
|
||||
}
|
||||
build_procedure_call(call_location, symbol, expression->arguments());
|
||||
}
|
||||
else if (TYPE_P(symbol) && is_record_type(symbol))
|
||||
{
|
||||
vec<constructor_elt, va_gc> *arguments = nullptr;
|
||||
tree record_fields = TYPE_FIELDS(symbol);
|
||||
for (boot::expression *const argument : expression->arguments())
|
||||
{
|
||||
argument->accept(this);
|
||||
CONSTRUCTOR_APPEND_ELT(arguments, record_fields, this->current_expression);
|
||||
record_fields = TREE_CHAIN(record_fields);
|
||||
}
|
||||
this->current_expression = build_constructor(symbol, arguments);
|
||||
build_record_call(call_location, symbol, expression->arguments());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -475,7 +537,9 @@ namespace gcc
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (left_type != right_type && !are_compatible_pointers(left, right) && !are_compatible_pointers(right, left))
|
||||
if (left_type != right_type
|
||||
&& !are_compatible_pointers(left_type, right)
|
||||
&& !are_compatible_pointers(right_type, left))
|
||||
{
|
||||
error_at(expression_location,
|
||||
"invalid operands of type %s and %s for operator %s",
|
||||
@ -848,8 +912,7 @@ namespace gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
if (TREE_TYPE(this->current_expression) == TREE_TYPE(lvalue)
|
||||
|| are_compatible_pointers(lvalue, this->current_expression))
|
||||
if (is_assignable_from(TREE_TYPE(lvalue), this->current_expression))
|
||||
{
|
||||
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||
void_type_node, lvalue, this->current_expression);
|
||||
|
@ -67,15 +67,21 @@ namespace gcc
|
||||
return TREE_CODE(type) == RECORD_TYPE;
|
||||
}
|
||||
|
||||
bool are_compatible_pointers(tree lhs, tree rhs)
|
||||
bool are_compatible_pointers(tree lhs_type, tree rhs)
|
||||
{
|
||||
tree lhs_type = TREE_TYPE(lhs);
|
||||
gcc_assert(TYPE_P(lhs_type));
|
||||
tree rhs_type = TREE_TYPE(rhs);
|
||||
|
||||
return (is_pointer_type(lhs_type) && rhs == elna_pointer_nil_node)
|
||||
|| (is_pointer_type(lhs_type) && lhs_type == rhs_type);
|
||||
}
|
||||
|
||||
bool is_assignable_from(tree assignee, tree assignment)
|
||||
{
|
||||
return TREE_TYPE(assignment) == assignee
|
||||
|| are_compatible_pointers(assignee, assignment);
|
||||
}
|
||||
|
||||
void append_statement(tree statement_tree)
|
||||
{
|
||||
if (!vec_safe_is_empty(f_binding_level->defers))
|
||||
|
Reference in New Issue
Block a user