aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-09-01 01:55:44 +0200
committerEugen Wissner <belka@caraus.de>2026-09-01 01:55:44 +0200
commitb3a7a5731285625aa9fc6a347841591757860edb (patch)
tree94b267ea425a15e7c9bc63c15d8d5580048dd545 /boot
parent0f5e9f00b07606871a6289060fa904555d41ae7d (diff)
downloadelna-cpp.tar.gz
Fix const extern variable declarationsHEADcpp
Diffstat (limited to 'boot')
-rw-r--r--boot/name_analysis.cc2
-rw-r--r--boot/type_check.cc28
2 files changed, 29 insertions, 1 deletions
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 70b9031..3c4c6f8 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -420,7 +420,7 @@ namespace elna::boot
non_constant_expression_error::initializer{ extract_identifiers(declaration->identifiers) });
}
}
- else if (resolve_aliases(variable_type).get<constant_type>() != nullptr)
+ else if (!declaration->is_extern && resolve_aliases(variable_type).get<constant_type>() != nullptr)
{
auto position_span = source_position(declaration->identifiers.front().id().position().start(),
declaration->identifiers.back().id().position().end());
diff --git a/boot/type_check.cc b/boot/type_check.cc
index 068d958..74c8176 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -513,12 +513,40 @@ namespace elna::boot
return verdict::pass;
}
+ assign_check::verdict assign_check::check_array_conversion() const
+ {
+ auto assignee_array = ctx.resolved_assignee.get<array_type>();
+ auto assignment_array = ctx.resolved_assignment.get<array_type>();
+
+ if (assignee_array == nullptr || assignment_array == nullptr
+ || assignee_array->size != assignment_array->size)
+ {
+ return verdict::pass;
+ }
+ auto assignee_element_const = resolve_aliases(assignee_array->base).get<constant_type>();
+ auto assignment_element_const = resolve_aliases(assignment_array->base).get<constant_type>();
+
+ // An array is copied by value, so const can be added to the element type,
+ // but not removed. Writing to such an array is rejected on the lvalue.
+ if (assignee_element_const != nullptr
+ && assignee_element_const->unqualified == assignment_array->base)
+ {
+ return verdict::accept;
+ }
+ if (assignment_element_const != nullptr && assignee_element_const == nullptr)
+ {
+ return verdict::reject;
+ }
+ return verdict::pass;
+ }
+
bool assign_check::run()
{
auto const assign_handlers = {
&assign_check::guard_const_laundering,
&assign_check::check_exact_match,
&assign_check::check_slice_conversion,
+ &assign_check::check_array_conversion,
&assign_check::check_pointer_hatch,
&assign_check::check_pointer_conversion
};