aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-18 09:25:36 +0200
committerEugen Wissner <belka@caraus.de>2026-10-18 22:54:00 +0200
commit7440060f179e35fe63155a149bb5003c97e12013 (patch)
treeabdcb8aa74513312b2cc92d4c2b2b986c29fbc03 /boot
parent81043b67437445dcf83055098490e04cc88ff7ee (diff)
downloadelna-7440060f179e35fe63155a149bb5003c97e12013.tar.gz
Fix ICE on variable declarations in case branches
Diffstat (limited to 'boot')
-rw-r--r--boot/ast.cc29
-rw-r--r--boot/name_analysis.cc3
-rw-r--r--boot/type_check.cc42
3 files changed, 31 insertions, 43 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index 15e4928..e712f16 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -243,7 +243,7 @@ namespace elna::boot
}
if (declaration->body.has_value())
{
- traverse_block(this, declaration->body.value());
+ boot::traverse_block(this, declaration->body.value());
if (declaration->body.value().return_expression != nullptr)
{
declaration->body.value().return_expression->accept(this);
@@ -257,54 +257,59 @@ namespace elna::boot
statement->rvalue().accept(this);
}
+ void walking_visitor::traverse_block(const block& body)
+ {
+ boot::traverse_block(this, body);
+ }
+
void walking_visitor::visit(if_statement *statement)
{
statement->branch().prerequisite().accept(this);
- traverse_block(this, statement->branch().body);
+ traverse_block(statement->branch().body);
for (conditional_statements& branch : statement->branches)
{
branch.prerequisite().accept(this);
- traverse_block(this, branch.body);
+ traverse_block(branch.body);
}
if (statement->alternative != nullptr)
{
- traverse_block(this, *statement->alternative);
+ traverse_block(*statement->alternative);
}
}
void walking_visitor::visit(while_statement *statement)
{
statement->branch().prerequisite().accept(this);
- traverse_block(this, statement->branch().body);
+ traverse_block(statement->branch().body);
for (conditional_statements& branch : statement->branches)
{
branch.prerequisite().accept(this);
- traverse_block(this, branch.body);
+ traverse_block(branch.body);
}
}
void walking_visitor::visit(repeat_statement *statement)
{
statement->condition().accept(this);
- traverse_block(this, statement->body);
+ traverse_block(statement->body);
}
void walking_visitor::visit(for_statement *statement)
{
statement->range().accept(this);
- traverse_block(this, statement->body);
+ traverse_block(statement->body);
}
void walking_visitor::visit(defer_statement *statement)
{
- traverse_block(this, statement->body);
+ traverse_block(statement->body);
}
void walking_visitor::visit(block_statement *statement)
{
- traverse_block(this, statement->body);
+ traverse_block(statement->body);
}
void walking_visitor::visit(break_statement *)
@@ -321,11 +326,11 @@ namespace elna::boot
for (const switch_case& case_block : statement->cases)
{
visit_all(this, case_block.labels);
- traverse_block(this, case_block.body);
+ traverse_block(case_block.body);
}
if (statement->alternative != nullptr)
{
- traverse_block(this, *statement->alternative);
+ traverse_block(*statement->alternative);
}
}
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 9305cd2..11380db 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -1628,7 +1628,8 @@ namespace elna::boot
this->bag.leave();
info_object->parameters = type_parameters;
info_object->exported = declaration->identifier.exported();
- info_object->position.emplace(declaration->position());
+ info_object->position.emplace(declaration->position().start(),
+ declaration->heading().position().end());
info_object->file = this->module_file;
info_object->noreturn = noreturn;
diff --git a/boot/type_check.cc b/boot/type_check.cc
index 5a8170a..5033ffd 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -494,9 +494,8 @@ namespace elna::boot
return is_assignable_from(left, right) || is_assignable_from(right, left);
}
- void type_analysis_visitor::visit_and_validate_condition(expression& condition)
+ void type_analysis_visitor::validate_condition(const expression& condition)
{
- condition.accept(this);
if (!is_primitive_type(condition.type_decoration, "Bool"))
{
add_error<type_requirement_error>(condition.position(),
@@ -824,7 +823,7 @@ namespace elna::boot
void type_analysis_visitor::visit(for_statement *statement)
{
- statement->range().accept(this);
+ walking_visitor::visit(statement);
const type resolved_range = resolve_underlying_type(statement->range().type_decoration);
if (!get_range_base_type(resolved_range))
@@ -832,47 +831,40 @@ namespace elna::boot
add_error<type_requirement_error>(statement->range().position(),
statement->range().type_decoration, type_requirement_error::kind::for_range);
}
- traverse_block(statement->body);
}
- void type_analysis_visitor::traverse_block(block& body)
+ void type_analysis_visitor::traverse_block(const block& body)
{
this->bag.enter(body.symbols);
- boot::traverse_block(this, body);
+ walking_visitor::traverse_block(body);
this->bag.leave();
}
void type_analysis_visitor::visit(repeat_statement *statement)
{
- visit_and_validate_condition(statement->condition());
- traverse_block(statement->body);
+ walking_visitor::visit(statement);
+ validate_condition(statement->condition());
}
void type_analysis_visitor::visit(while_statement *statement)
{
- visit_and_validate_condition(statement->branch().prerequisite());
- traverse_block(statement->branch().body);
+ walking_visitor::visit(statement);
+ validate_condition(statement->branch().prerequisite());
for (conditional_statements& branch : statement->branches)
{
- visit_and_validate_condition(branch.prerequisite());
- traverse_block(branch.body);
+ validate_condition(branch.prerequisite());
}
}
void type_analysis_visitor::visit(if_statement *statement)
{
- visit_and_validate_condition(statement->branch().prerequisite());
- traverse_block(statement->branch().body);
+ walking_visitor::visit(statement);
+ validate_condition(statement->branch().prerequisite());
for (conditional_statements& branch : statement->branches)
{
- visit_and_validate_condition(branch.prerequisite());
- traverse_block(branch.body);
- }
- if (statement->alternative != nullptr)
- {
- traverse_block(*statement->alternative);
+ validate_condition(branch.prerequisite());
}
}
@@ -1462,16 +1454,6 @@ namespace elna::boot
}
// else callable is not declared, or inference failed and reported.
}
-
- void type_analysis_visitor::visit(defer_statement *statement)
- {
- traverse_block(statement->body);
- }
-
- void type_analysis_visitor::visit(block_statement *statement)
- {
- traverse_block(statement->body);
- }
void type_analysis_visitor::visit(record_constructor_expression *expression)
{