aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-31 00:49:46 +0200
committerEugen Wissner <belka@caraus.de>2026-08-31 00:49:46 +0200
commitd905e48d6af0445c7941cd2e638461db2f4d9ee8 (patch)
tree7af05b7c798864d745fc3bd831e7227c0a51b567 /boot
parent26a1b9ad9f347315bc14f2bf3ee064ede51794fc (diff)
downloadelna-d905e48d6af0445c7941cd2e638461db2f4d9ee8.tar.gz
Type check for value addressability
Diffstat (limited to 'boot')
-rw-r--r--boot/type_check.cc41
1 files changed, 36 insertions, 5 deletions
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<type_requirement_error>(statement->position(),
+ statement->lvalue().type_decoration,
+ type_requirement_error::kind::not_addressable);
+ }
+ else if (contains_constant_member(statement->lvalue().type_decoration))
{
add_error<type_mismatch_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<type_mismatch_error>(expression->position(),
+ add_error<type_requirement_error>(expression->position(),
expression->operand().type_decoration,
- type_mismatch_error::unary{ .operation = operation });
+ type_requirement_error::kind::not_addressable);
}
}
}