From d905e48d6af0445c7941cd2e638461db2f4d9ee8 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Mon, 31 Aug 2026 00:49:46 +0200 Subject: Type check for value addressability --- boot/type_check.cc | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'boot') diff --git a/boot/type_check.cc b/boot/type_check.cc index abee91f..5b0547b 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -216,6 +216,9 @@ namespace elna::boot case zero_sized: return "Zero-sized type '" + this->actual.to_string() + "' cannot be declared"; + case not_addressable: + return "Expression of type '" + this->actual.to_string() + + "' is not addressable"; default: __builtin_unreachable(); } @@ -353,6 +356,29 @@ namespace elna::boot return std::nullopt; } + // Checks whether the expression designates a storage location: a named + // expression, a dereference, or a field or array access of an addressable + // base. Slicing produces a value, not a location. + static bool is_addressable(expression& subject) + { + if (auto *designator = subject.is_designator()) + { + if (designator->is_named() != nullptr || designator->is_dereference() != nullptr) + { + return true; + } + else if (auto *field_access = designator->is_field_access()) + { + return is_addressable(field_access->base()); + } + else if (auto *array_access = designator->is_array_access()) + { + return is_addressable(array_access->base()); + } + } + return false; + } + bool type_analysis_visitor::is_equality_compatible(const type& left, const type& right) { auto resolved_left = resolve_underlying_type(left); @@ -614,7 +640,13 @@ namespace elna::boot { walking_visitor::visit(statement); - if (contains_constant_member(statement->lvalue().type_decoration)) + if (!is_addressable(statement->lvalue())) + { + add_error(statement->position(), + statement->lvalue().type_decoration, + type_requirement_error::kind::not_addressable); + } + else if (contains_constant_member(statement->lvalue().type_decoration)) { add_error(statement->position(), statement->lvalue().type_decoration, type_mismatch_error::constant_assignment{}); @@ -1016,12 +1048,11 @@ namespace elna::boot } else if (operation == unary_operator::reference) { - auto *designator = expression->operand().is_designator(); - if (designator == nullptr || designator->is_slicing() != nullptr) + if (!is_addressable(expression->operand())) { - add_error(expression->position(), + add_error(expression->position(), expression->operand().type_decoration, - type_mismatch_error::unary{ .operation = operation }); + type_requirement_error::kind::not_addressable); } } } -- cgit v1.2.3