Detect alias cycles
This commit is contained in:
@ -101,11 +101,11 @@ namespace elna::gcc
|
||||
}
|
||||
|
||||
tree build_composite_type(const std::vector<boot::type_field>& fields, tree composite_type_node,
|
||||
std::shared_ptr<symbol_table> symbols, std::vector<std::string>& path)
|
||||
std::shared_ptr<symbol_table> symbols)
|
||||
{
|
||||
for (auto& field : fields)
|
||||
{
|
||||
tree rewritten_field = get_inner_alias(field.second, symbols, path);
|
||||
tree rewritten_field = get_inner_alias(field.second, symbols);
|
||||
tree field_declaration = build_field(UNKNOWN_LOCATION,
|
||||
composite_type_node, field.first, rewritten_field);
|
||||
TYPE_FIELDS(composite_type_node) = chainon(TYPE_FIELDS(composite_type_node), field_declaration);
|
||||
@ -114,25 +114,24 @@ namespace elna::gcc
|
||||
return composite_type_node;
|
||||
}
|
||||
|
||||
tree build_procedure_type(const boot::procedure_type& procedure, std::shared_ptr<symbol_table> symbols,
|
||||
std::vector<std::string>& path)
|
||||
tree build_procedure_type(const boot::procedure_type& procedure, std::shared_ptr<symbol_table> symbols)
|
||||
{
|
||||
std::vector<tree> parameter_types(procedure.parameters.size());
|
||||
|
||||
for (std::size_t i = 0; i < procedure.parameters.size(); ++i)
|
||||
{
|
||||
parameter_types[i] = get_inner_alias(procedure.parameters.at(i), symbols, path);
|
||||
parameter_types[i] = get_inner_alias(procedure.parameters.at(i), symbols);
|
||||
}
|
||||
tree return_type = void_type_node;
|
||||
|
||||
if (!procedure.return_type.proper_type.empty())
|
||||
{
|
||||
return_type = get_inner_alias(procedure.return_type.proper_type, symbols, path);
|
||||
return_type = get_inner_alias(procedure.return_type.proper_type, symbols);
|
||||
}
|
||||
return build_function_type_array(return_type, procedure.parameters.size(), parameter_types.data());
|
||||
}
|
||||
|
||||
tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols, std::vector<std::string>& path)
|
||||
tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols)
|
||||
{
|
||||
if (auto reference = type.get<boot::primitive_type>())
|
||||
{
|
||||
@ -145,7 +144,7 @@ namespace elna::gcc
|
||||
{
|
||||
tree composite_type_node = make_node(RECORD_TYPE);
|
||||
|
||||
build_composite_type(reference->fields, composite_type_node, symbols, path);
|
||||
build_composite_type(reference->fields, composite_type_node, symbols);
|
||||
|
||||
return composite_type_node;
|
||||
}
|
||||
@ -153,7 +152,7 @@ namespace elna::gcc
|
||||
{
|
||||
tree composite_type_node = make_node(UNION_TYPE);
|
||||
|
||||
build_composite_type(reference->fields, composite_type_node, symbols, path);
|
||||
build_composite_type(reference->fields, composite_type_node, symbols);
|
||||
|
||||
return composite_type_node;
|
||||
}
|
||||
@ -163,42 +162,35 @@ namespace elna::gcc
|
||||
}
|
||||
else if (auto reference = type.get<boot::pointer_type>())
|
||||
{
|
||||
return build_global_pointer_type(get_inner_alias(reference->base, symbols, path));
|
||||
return build_global_pointer_type(get_inner_alias(reference->base, symbols));
|
||||
}
|
||||
else if (auto reference = type.get<boot::array_type>())
|
||||
{
|
||||
tree base = get_inner_alias(reference->base, symbols, path);
|
||||
tree base = get_inner_alias(reference->base, symbols);
|
||||
|
||||
return build_static_array_type(base, reference->size);
|
||||
}
|
||||
else if (auto reference = type.get<boot::procedure_type>())
|
||||
{
|
||||
auto procedure = build_procedure_type(*reference, symbols, path);
|
||||
auto procedure = build_procedure_type(*reference, symbols);
|
||||
|
||||
return build_global_pointer_type(procedure);
|
||||
}
|
||||
else if (auto reference = type.get<boot::alias_type>())
|
||||
{
|
||||
return handle_symbol(reference->name, reference, symbols, path);
|
||||
return handle_symbol(reference->name, reference, symbols);
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
tree handle_symbol(const std::string& symbol_name, std::shared_ptr<boot::alias_type> reference,
|
||||
std::shared_ptr<symbol_table> symbols, std::vector<std::string>& path)
|
||||
std::shared_ptr<symbol_table> symbols)
|
||||
{
|
||||
path.push_back(symbol_name);
|
||||
std::vector<std::string>::const_iterator head_peace = std::cbegin(path);
|
||||
|
||||
if (std::find(std::next(head_peace), std::cend(path), *head_peace) != std::cend(path))
|
||||
{
|
||||
return error_mark_node;
|
||||
}
|
||||
tree looked_up = symbols->lookup(symbol_name);
|
||||
|
||||
if (looked_up == NULL_TREE)
|
||||
{
|
||||
looked_up = get_inner_alias(reference->reference, symbols, path);
|
||||
looked_up = get_inner_alias(reference->reference, symbols);
|
||||
|
||||
symbols->enter(symbol_name, build_type_declaration(symbol_name, looked_up));
|
||||
}
|
||||
@ -212,8 +204,7 @@ namespace elna::gcc
|
||||
void declare_procedure(const std::string& name, const boot::procedure_info& info,
|
||||
std::shared_ptr<symbol_table> symbols)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
tree declaration_type = gcc::build_procedure_type(info.symbol, symbols, path);
|
||||
tree declaration_type = gcc::build_procedure_type(info.symbol, symbols);
|
||||
tree fndecl = build_fn_decl(name.c_str(), declaration_type);
|
||||
symbols->enter(name, fndecl);
|
||||
|
||||
@ -247,18 +238,16 @@ namespace elna::gcc
|
||||
DECL_EXTERNAL(fndecl) = info.symbols == nullptr;
|
||||
}
|
||||
|
||||
void do_semantic_analysis(std::shared_ptr<boot::symbol_table> info_table, std::shared_ptr<symbol_table> symbols)
|
||||
void rewrite_symbol_table(std::shared_ptr<boot::symbol_table> info_table, std::shared_ptr<symbol_table> symbols)
|
||||
{
|
||||
for (auto& [symbol_name, symbol_info] : *info_table)
|
||||
{
|
||||
std::vector<std::string> type_path;
|
||||
|
||||
if (auto type_info = symbol_info->is_type())
|
||||
{
|
||||
// The top level symbol table has basic (builtin) types in it which are not aliases.
|
||||
if (auto alias_type = type_info->symbol.get<boot::alias_type>())
|
||||
{
|
||||
handle_symbol(symbol_name, alias_type, symbols, type_path);
|
||||
handle_symbol(symbol_name, alias_type, symbols);
|
||||
}
|
||||
}
|
||||
else if (auto procedure_info = symbol_info->is_procedure())
|
||||
|
@ -145,8 +145,12 @@ namespace elna::gcc
|
||||
{
|
||||
for (const auto& error : errors)
|
||||
{
|
||||
auto gcc_location = elna::gcc::get_location(&error->position);
|
||||
location_t gcc_location{ UNKNOWN_LOCATION };
|
||||
|
||||
if (error->position.line != 0 || error->position.column != 0)
|
||||
{
|
||||
gcc_location = elna::gcc::get_location(&error->position);
|
||||
}
|
||||
error_at(gcc_location, error->what().c_str());
|
||||
}
|
||||
}
|
||||
|
@ -217,8 +217,7 @@ namespace elna::gcc
|
||||
|
||||
void generic_visitor::visit(boot::cast_expression *expression)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
tree cast_target = get_inner_alias(expression->expression_type, this->symbols->scope(), path);
|
||||
tree cast_target = get_inner_alias(expression->expression_type, this->symbols->scope());
|
||||
|
||||
expression->value().accept(this);
|
||||
tree cast_source = TREE_TYPE(this->current_expression);
|
||||
@ -746,10 +745,9 @@ namespace elna::gcc
|
||||
|
||||
void generic_visitor::visit(boot::variable_declaration *declaration)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
this->current_expression = get_inner_alias(
|
||||
this->info_table->lookup(declaration->identifier.identifier)->is_variable()->symbol,
|
||||
this->symbols->scope(), path);
|
||||
this->symbols->scope());
|
||||
|
||||
location_t declaration_location = get_location(&declaration->position());
|
||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
||||
@ -854,8 +852,7 @@ namespace elna::gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> path;
|
||||
this->current_expression = get_inner_alias(trait->types.front(), this->symbols, path);
|
||||
this->current_expression = get_inner_alias(trait->types.front(), this->symbols);
|
||||
|
||||
return this->current_expression != error_mark_node;
|
||||
}
|
||||
@ -919,8 +916,7 @@ namespace elna::gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> path;
|
||||
this->current_expression = get_inner_alias(trait->types.front(), this->symbols, path);
|
||||
this->current_expression = get_inner_alias(trait->types.front(), this->symbols);
|
||||
auto field_type = trait->parameters.at(1)->is_named();
|
||||
|
||||
if (field_type == nullptr)
|
||||
@ -1128,13 +1124,6 @@ namespace elna::gcc
|
||||
{
|
||||
make_if_branch(*branch, goto_check);
|
||||
}
|
||||
if (statement->alternative != nullptr)
|
||||
{
|
||||
enter_scope();
|
||||
visit_statements(*statement->alternative);
|
||||
tree mapping = leave_scope();
|
||||
append_statement(mapping);
|
||||
}
|
||||
append_statement(branch_end_expression);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ static void elna_parse_file(const char *filename)
|
||||
|
||||
if (name_analysis_visitor.errors().empty())
|
||||
{
|
||||
elna::gcc::do_semantic_analysis(info_table, symbol_table);
|
||||
elna::gcc::rewrite_symbol_table(info_table, symbol_table);
|
||||
|
||||
elna::gcc::generic_visitor generic_visitor{ symbol_table, info_table };
|
||||
generic_visitor.visit(module_tree.get());
|
||||
|
Reference in New Issue
Block a user