Compiler didn't check foreach over flexible array member, and folding a flexible array member was allowed #2164.

This commit is contained in:
Christoffer Lerno
2025-05-28 22:21:06 +02:00
parent 349d9ef3cf
commit 00f1206f3c
6 changed files with 27 additions and 2 deletions

View File

@@ -52,6 +52,7 @@
- `$$sat_mul` was missing.
- `for` with incorrect `var` declaration caused crash #2154.
- Check pointer/slice/etc on `[out]` and `&` params. #2156.
- Compiler didn't check foreach over flexible array member, and folding a flexible array member was allowed #2164.
### Stdlib changes
- Added `String.quick_ztr` and `String.is_zstr`

View File

@@ -2374,7 +2374,7 @@ static inline bool unit_add_method(SemaContext *context, Type *parent_type, Decl
other = sema_resolve_method(unit, parent, name, &ambiguous, &private);
if (other)
{
if (unit->module->generic_module && other->unit->module->generic_module == unit->module->generic_module)
if (unit->module->generic_module && other->unit->module->generic_module == unit->module->generic_module && other->unit->module != unit->module)
{
const char *module_name = unit->module->generic_module->name->module;
RETURN_SEMA_ERROR(method, "The same method is generated by multiple instances of '%s': '%s%s' and '%s%s'. "

View File

@@ -4981,6 +4981,7 @@ EVAL:
switch (result->kind)
{
case CONST_INIT_ZERO:
if (member->type->type_kind == TYPE_FLEXIBLE_ARRAY) return false;
expr_rewrite_to_const_zero(expr, member->type);
break;
case CONST_INIT_STRUCT:
@@ -5688,6 +5689,10 @@ CHECK_DEEPER:
{
if (!sema_expr_fold_to_member(expr, current_parent, member))
{
if (member->type->type_kind == TYPE_FLEXIBLE_ARRAY)
{
RETURN_SEMA_ERROR(expr, "Could not fold to member '%s', it's a flexible array member which is always empty.", member->name);
}
RETURN_SEMA_ERROR(expr, "Could not fold to member '%s' it wasn't the last assigned member.", member->name);
}
return true;

View File

@@ -1497,6 +1497,10 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
// At this point we should have dereferenced any pointer or bailed.
ASSERT_SPAN(enumerator, !type_is_pointer(enumerator->type));
if (enumerator->type->type_kind == TYPE_FLEXIBLE_ARRAY)
{
RETURN_SEMA_ERROR(enumerator, "It is not possible to enumerate over a flexible array member.", type_quoted_error_string(enumerator->type));
}
// Check that we can even index this expression, this will dig into the flattened type.
Type *value_type = type_get_indexed_type(enumerator->type);

View File

@@ -10,7 +10,7 @@ struct Widget
List {any} children;
}
fn void Widget{Label}.draw(Widget* self) // #error: This identifier is recursively using gui::widget
fn void Widget{Label}.draw(Widget* self) // #error: The same method is generated by multiple instances
{
io::printfn("Hello Label");
}

View File

@@ -0,0 +1,15 @@
struct Abc
{
int a;
int[*] b;
}
fn void test()
{
Abc y = {};
foreach (x : y.b) {} // #error: It is not possible to enumerate over a flexible
}
fn int main()
{
foreach (x : (Abc){}.b) {} // #error: it's a flexible array member
return 0;
}