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 --- include/elna/boot/name_analysis.h | 32 ++++++++++++++++++++++++++++++++ include/elna/boot/type_check.h | 15 --------------- include/elna/gcc/elna-builtins.h | 3 ++- 3 files changed, 34 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index cd3c4f7..8e945b2 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#include namespace elna::boot { @@ -65,6 +66,19 @@ namespace elna::boot payload_type payload; }; + /** + * Cyclic type declaration. + */ + class cyclic_declaration_error final : public diagnostic + { + std::vector cycle; + + public: + cyclic_declaration_error(const source_position position, const std::vector& cycle); + + std::string what() const override; + }; + /** * \c const qualifier used incorrectly — wrong position or duplicate. */ @@ -222,6 +236,24 @@ namespace elna::boot { using resolving_visitor::visit; + // Traversal state of the recursive type walk: + struct walk_state + { + // Whether the path passed through a record. + bool record_seen{ false }; + // Whether the current occurrence is behind a pointer or a slice. + bool guarded{ false }; + }; + + // Returns the cycle path if wiring the referent closes an illegal + // cycle, nothing otherwise. + static std::optional> find_alias_cycle( + const std::shared_ptr& being_resolved, const type& referent); + + // Returns whether the referent is well-founded. + static bool find_alias_cycle(const std::shared_ptr& being_resolved, + const type& referent, std::vector& alias_path, walk_state state); + public: declaration_visitor(symbol_bag& bag, const target_info& target, const std::filesystem::path& module_path); diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 0b62a4a..330de44 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -106,19 +106,6 @@ namespace elna::boot kind m_kind; }; - /** - * Cyclic type declaration. - */ - class cyclic_declaration_error final : public diagnostic - { - std::vector cycle; - - public: - cyclic_declaration_error(const source_position position, const std::vector& cycle); - - std::string what() const override; - }; - /** * Argument count in a procedure call or array constructor doesn't match * the expected number of parameters or elements. @@ -222,8 +209,6 @@ namespace elna::boot */ static bool is_assignable_from(const type& assignee, const type& assignment); static bool is_equality_compatible(const type& left, const type& right); - static bool check_unresolved_symbol(const std::shared_ptr& alias, - std::vector& path); void visit_and_validate_condition(expression& condition); diff --git a/include/elna/gcc/elna-builtins.h b/include/elna/gcc/elna-builtins.h index 9f24b00..75b409d 100644 --- a/include/elna/gcc/elna-builtins.h +++ b/include/elna/gcc/elna-builtins.h @@ -37,7 +37,8 @@ namespace elna::gcc tree handle_symbol(const std::string& symbol_name, const std::shared_ptr& reference, const std::shared_ptr& symbols); - 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 = NULL_TREE); void declare_procedure(const std::string& name, const boot::procedure_info& info, const std::shared_ptr& symbols); tree declare_variable(const std::string& name, const boot::variable_info& info, -- cgit v1.2.3