Implement enumeration type
This commit is contained in:
@ -129,6 +129,10 @@ namespace elna::gcc
|
||||
{
|
||||
return print_aggregate_name(unqualified_type, "union");
|
||||
}
|
||||
else if (TREE_CODE(type) == ENUMERAL_TYPE)
|
||||
{
|
||||
return print_aggregate_name(unqualified_type, "enumeration");
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<<unknown-type>>";
|
||||
|
@ -57,6 +57,10 @@ namespace elna::gcc
|
||||
{
|
||||
return make_node(UNION_TYPE);
|
||||
}
|
||||
else if (auto reference = type.get<boot::enumeration_type>())
|
||||
{
|
||||
return make_node(ENUMERAL_TYPE);
|
||||
}
|
||||
else if (auto reference = type.get<boot::pointer_type>())
|
||||
{
|
||||
return build_global_pointer_type(get_inner_alias(reference->base, symbols, unresolved, path));
|
||||
@ -247,8 +251,7 @@ namespace elna::gcc
|
||||
expression->value().accept(this);
|
||||
tree cast_source = TREE_TYPE(this->current_expression);
|
||||
|
||||
if ((is_primitive_type(cast_target) || is_pointer_type(cast_target))
|
||||
&& (is_primitive_type(cast_source) || is_pointer_type(cast_source)))
|
||||
if (is_castable_type(cast_target) && (is_castable_type(cast_source)))
|
||||
{
|
||||
this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
|
||||
cast_target, this->current_expression);
|
||||
@ -1030,7 +1033,7 @@ namespace elna::gcc
|
||||
return;
|
||||
}
|
||||
trait->parameters.front()->accept(this);
|
||||
auto field_type = trait->parameters.at(1)->is_primitive();
|
||||
auto field_type = trait->parameters.at(1)->is_named();
|
||||
|
||||
if (field_type == nullptr)
|
||||
{
|
||||
@ -1076,6 +1079,21 @@ namespace elna::gcc
|
||||
this->current_expression = build1(ADDR_EXPR,
|
||||
build_qualified_type(ptr_type, TYPE_QUAL_CONST), this->current_expression);
|
||||
}
|
||||
else if (TREE_CODE(aggregate_type) == ENUMERAL_TYPE)
|
||||
{
|
||||
tree iterator{ NULL_TREE };
|
||||
|
||||
for (iterator = TYPE_VALUES(aggregate_type); iterator != NULL_TREE; iterator = TREE_CHAIN(iterator))
|
||||
{
|
||||
if (IDENTIFIER_POINTER(TREE_PURPOSE(iterator)) == expression->field())
|
||||
{
|
||||
this->current_expression = TREE_VALUE(iterator);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->current_expression = error_mark_node;
|
||||
error_at(expression_location, "Unknown enumeration member '%s'", expression->field().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
tree field_declaration = find_field_by_name(expression_location,
|
||||
@ -1285,7 +1303,7 @@ namespace elna::gcc
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::primitive_type_expression *type)
|
||||
void generic_visitor::visit(boot::named_type_expression *type)
|
||||
{
|
||||
auto looked_up = this->unresolved.find(type->name);
|
||||
tree symbol;
|
||||
@ -1362,6 +1380,33 @@ namespace elna::gcc
|
||||
this->current_expression = build_global_pointer_type(procedure_type_node);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::enumeration_type_expression *type)
|
||||
{
|
||||
tree composite_type_node = this->current_expression == NULL_TREE
|
||||
? make_node(ENUMERAL_TYPE)
|
||||
: this->current_expression;
|
||||
location_t enum_location = get_location(&type->position());
|
||||
|
||||
ENUM_IS_SCOPED(composite_type_node) = 1;
|
||||
|
||||
tree *pp = &TYPE_VALUES(composite_type_node);
|
||||
std::size_t order{ 1 };
|
||||
|
||||
for (const std::string& member : type->members)
|
||||
{
|
||||
tree member_name = get_identifier(member.c_str());
|
||||
tree member_declaration = build_decl(enum_location, CONST_DECL, member_name, composite_type_node);
|
||||
|
||||
DECL_INITIAL(member_declaration) = build_int_cst_type(integer_type_node, order++);
|
||||
TREE_CONSTANT(member_declaration) = 1;
|
||||
TREE_READONLY(member_declaration) = 1;
|
||||
|
||||
*pp = build_tree_list(member_name, member_declaration);
|
||||
pp = &TREE_CHAIN(*pp);
|
||||
}
|
||||
layout_type(composite_type_node);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::defer_statement *statement)
|
||||
{
|
||||
enter_scope();
|
||||
|
@ -62,10 +62,12 @@ namespace elna::gcc
|
||||
return type == NULL_TREE || type == void_type_node;
|
||||
}
|
||||
|
||||
bool is_aggregate_type(tree type)
|
||||
bool is_castable_type(tree type)
|
||||
{
|
||||
gcc_assert(TYPE_P(type));
|
||||
return TREE_CODE(type) == RECORD_TYPE || TREE_CODE(type) == UNION_TYPE;
|
||||
auto code = TREE_CODE(type);
|
||||
|
||||
return is_primitive_type(type) || is_pointer_type(type) || code == ENUMERAL_TYPE;
|
||||
}
|
||||
|
||||
bool are_compatible_pointers(tree lhs_type, tree rhs)
|
||||
@ -224,9 +226,9 @@ namespace elna::gcc
|
||||
}
|
||||
tree field_declaration = TYPE_FIELDS(type);
|
||||
|
||||
if (!is_aggregate_type(type))
|
||||
if (!RECORD_OR_UNION_TYPE_P(type))
|
||||
{
|
||||
error_at(expression_location, "type '%s' does not have a field named '%s'",
|
||||
error_at(expression_location, "Type '%s' does not have a field named '%s'",
|
||||
print_type(type).c_str(), field_name.c_str());
|
||||
return error_mark_node;
|
||||
}
|
||||
@ -243,7 +245,7 @@ namespace elna::gcc
|
||||
}
|
||||
if (field_declaration == NULL_TREE)
|
||||
{
|
||||
error_at(expression_location, "record type does not have a field named '%s'", field_name.c_str());
|
||||
error_at(expression_location, "Aggregate type does not have a field '%s'", field_name.c_str());
|
||||
return error_mark_node;
|
||||
}
|
||||
return field_declaration;
|
||||
|
Reference in New Issue
Block a user