Prevent foo.bar = {} when bar is a flexible array member.

This commit is contained in:
Christoffer Lerno
2025-09-29 01:59:38 +02:00
parent da67cd4eb0
commit cb2d0e798e
4 changed files with 38 additions and 0 deletions

View File

@@ -41,6 +41,7 @@
- Issue not correctly aborting compilation on recursive generics.
- Crash during codegen when taking the typeid of an empty enum with associated values.
- Assert when the binary doesn't get created and --run-once is used. #2502
- Prevent `foo.bar = {}` when `bar` is a flexible array member.
### Stdlib changes
- Added generic `InterfaceList` to store a list of values that implement a specific interface

View File

@@ -6862,6 +6862,10 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef
default:
break;
}
if (left->type && left->type->type_kind == TYPE_FLEXIBLE_ARRAY)
{
RETURN_SEMA_ERROR(left, "You can't assign to a flexible array member, but you may index into it and mutate it that way.");
}
// 2. Check assignability
if (!sema_expr_check_assign(context, left, failed_ref)) return false;
@@ -7174,7 +7178,13 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr *
break;
}
if (left->type->type_kind == TYPE_FLEXIBLE_ARRAY)
{
RETURN_SEMA_ERROR(left, "You can't assign to a flexible array member, but you may index into it and mutate it that way.");
}
// 2. Verify that the left side is assignable.
if (!sema_expr_check_assign(context, left, NULL)) return false;
Type *left_type_canonical = left->type->canonical;

View File

@@ -275,6 +275,8 @@ static inline StorageType sema_resolve_storage_type(SemaContext *context, Type *
if (!sema_analyse_decl(context, type->decl)) return false;
type = type->decl->distinct->type;
goto RETRY;
case TYPE_FLEXIBLE_ARRAY:
return STORAGE_UNKNOWN;
default:
return STORAGE_NORMAL;
}

View File

@@ -0,0 +1,25 @@
module main;
struct OwnedString
{
usz len;
char[*] data;
}
fn void test1()
{
OwnedString owned;
owned.data = {}; // #error: You can't assign to a flexible array member
}
fn void test2()
{
$typefrom(OwnedString.data.typeid) x = 1; // #error: 'char[*]' has unknown size, and
}
fn int main()
{
OwnedString owned;
owned.data[0] = 1;
return 0;
}