aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-30 02:08:45 +0200
committerEugen Wissner <belka@caraus.de>2026-08-30 02:08:45 +0200
commit491e62664394a8689a3f8904fbe8dbc3dea05524 (patch)
tree7142cf8d94fc6f9cf953d42d9c136b77f65d8034 /include
parent08d9c4292ebba3e320c1dbaca4fa06c83f6fc7fb (diff)
downloadelna-491e62664394a8689a3f8904fbe8dbc3dea05524.tar.gz
Fix ICEs with recursive type declarations
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/name_analysis.h32
-rw-r--r--include/elna/boot/type_check.h15
-rw-r--r--include/elna/gcc/elna-builtins.h3
3 files changed, 34 insertions, 16 deletions
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 <memory>
#include <optional>
#include <variant>
+#include <vector>
namespace elna::boot
{
@@ -66,6 +67,19 @@ namespace elna::boot
};
/**
+ * Cyclic type declaration.
+ */
+ class cyclic_declaration_error final : public diagnostic
+ {
+ std::vector<std::string> cycle;
+
+ public:
+ cyclic_declaration_error(const source_position position, const std::vector<std::string>& cycle);
+
+ std::string what() const override;
+ };
+
+ /**
* \c const qualifier used incorrectly — wrong position or duplicate.
*/
class const_qualifier_error final : public diagnostic
@@ -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<std::vector<std::string>> find_alias_cycle(
+ const std::shared_ptr<alias_type>& being_resolved, const type& referent);
+
+ // Returns whether the referent is well-founded.
+ static bool find_alias_cycle(const std::shared_ptr<alias_type>& being_resolved,
+ const type& referent, std::vector<std::string>& 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
@@ -107,19 +107,6 @@ namespace elna::boot
};
/**
- * Cyclic type declaration.
- */
- class cyclic_declaration_error final : public diagnostic
- {
- std::vector<std::string> cycle;
-
- public:
- cyclic_declaration_error(const source_position position, const std::vector<std::string>& 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_type>& alias,
- std::vector<std::string>& 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<boot::alias_type>& reference,
const std::shared_ptr<symbol_table>& symbols);
- tree get_inner_alias(const boot::type& type, const std::shared_ptr<symbol_table>& symbols);
+ tree get_inner_alias(const boot::type& type, const std::shared_ptr<symbol_table>& symbols,
+ tree placeholder = NULL_TREE);
void declare_procedure(const std::string& name, const boot::procedure_info& info,
const std::shared_ptr<symbol_table>& symbols);
tree declare_variable(const std::string& name, const boot::variable_info& info,