From 491e62664394a8689a3f8904fbe8dbc3dea05524 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 30 Aug 2026 02:08:45 +0200 Subject: Fix ICEs with recursive type declarations --- gcc/gcc/elna-builtins.cc | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index c728a00..3d10c44 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -170,7 +170,8 @@ namespace elna::gcc static_cast(procedure.parameters.size()), parameter_types.data()); } - tree get_inner_alias(const boot::type& type, const std::shared_ptr& symbols) + tree get_inner_alias(const boot::type& type, const std::shared_ptr& symbols, + tree placeholder) { if (auto reference = type.get()) { @@ -181,7 +182,7 @@ namespace elna::gcc } else if (auto reference = type.get()) { - tree composite_type_node = make_node(RECORD_TYPE); + tree composite_type_node = placeholder != NULL_TREE ? placeholder : make_node(RECORD_TYPE); if (!reference->base.empty()) { @@ -217,17 +218,17 @@ namespace elna::gcc } else if (auto reference = type.get()) { - return build_pointer_type(get_inner_alias(reference->base, symbols)); + return build_pointer_type(get_inner_alias(reference->base, symbols, placeholder)); } else if (auto reference = type.get()) { - tree base = get_inner_alias(reference->base, symbols); + tree base = get_inner_alias(reference->base, symbols, placeholder); return build_static_array_type(base, reference->size); } else if (auto reference = type.get()) { - tree base_type = get_inner_alias(reference->base, symbols); + tree base_type = get_inner_alias(reference->base, symbols, placeholder); tree slice_record = make_node(RECORD_TYPE); tree ptr_field = build_field(UNKNOWN_LOCATION, slice_record, "ptr", build_pointer_type(base_type)); @@ -246,7 +247,7 @@ namespace elna::gcc } else if (auto reference = type.get()) { - tree unqualified = get_inner_alias(reference->unqualified, symbols); + tree unqualified = get_inner_alias(reference->unqualified, symbols, placeholder); return build_qualified_type(unqualified, TYPE_QUAL_CONST); } else if (auto reference = type.get()) @@ -264,15 +265,28 @@ namespace elna::gcc if (looked_up == NULL_TREE) { - tree type_tree = get_inner_alias(reference->referent, symbols); + /* + * Enter a placeholder before converting the referent: a + * self-reference through a pointer or a slice then finds the + * in-progress declaration and breaks the conversion recursion. + */ + tree placeholder = make_node(RECORD_TYPE); + looked_up = build_decl(UNKNOWN_LOCATION, TYPE_DECL, + get_identifier(symbol_name.c_str()), placeholder); + + TREE_PUBLIC(looked_up) = 1; + TYPE_NAME(placeholder) = DECL_NAME(looked_up); + symbols->enter(symbol_name, looked_up); + + tree type_tree = get_inner_alias(reference->referent, symbols, placeholder); if (type_tree == error_mark_node) { return error_mark_node; } - looked_up = build_decl(UNKNOWN_LOCATION, TYPE_DECL, - get_identifier(symbol_name.c_str()), type_tree); - - TREE_PUBLIC(looked_up) = 1; + if (type_tree != placeholder) + { + TREE_TYPE(looked_up) = type_tree; + } if (is_unique_type(type_tree)) { TYPE_NAME(type_tree) = DECL_NAME(looked_up); @@ -282,7 +296,6 @@ namespace elna::gcc { TYPE_NAME(type_tree) = looked_up; } - symbols->enter(symbol_name, looked_up); } return looked_up; } -- cgit v1.2.3