diff --git a/releasenotes.md b/releasenotes.md index 912f30507..875169097 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -126,6 +126,7 @@ - Early exit in macro call crashes codegen #2820 - Empty enums would return the values as zero sized arrays #2838 - Store of zero in lowering did not properly handle optionals in some cases #2837 +- Bitstruct accidentally allowed other arrays than char arrays #2836 ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index adb5793b3..6d6c35f80 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1107,11 +1107,10 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl, bool *erase decl->strukt.little_endian = false; } Type *base_type = type->type_kind == TYPE_ARRAY ? type_flatten(type->array.base) : type; - if (!type_is_integer(base_type)) + if (!type_is_integer(base_type) || (type->type_kind == TYPE_ARRAY && type_size(type->array.base) > 1)) { - SEMA_ERROR(decl->strukt.container_type, "The type of the bitstruct cannot be %s but must be an integer or an array of integers.", - type_quoted_error_string(decl->strukt.container_type->type)); - return false; + RETURN_SEMA_ERROR(decl->strukt.container_type, "The type of the bitstruct cannot be %s but must be an integer or an array of chars.", + type_quoted_error_string(decl->strukt.container_type->type)); } Decl **members = decl->strukt.members; unsigned member_count = vec_size(members); diff --git a/test/test_suite/bitstruct/bitstruct_on_unresolved_decl.c3 b/test/test_suite/bitstruct/bitstruct_on_unresolved_decl.c3 index 46d282af8..0f0e90c0b 100644 --- a/test/test_suite/bitstruct/bitstruct_on_unresolved_decl.c3 +++ b/test/test_suite/bitstruct/bitstruct_on_unresolved_decl.c3 @@ -1,3 +1,3 @@ -bitstruct Foo : FixedBlockPool // #error: The type of the bitstruct cannot be 'FixedBlockPool' but must be an integer or an array of integers +bitstruct Foo : FixedBlockPool // #error: The type of the bitstruct cannot be 'FixedBlockPool' but must be an integer { } \ No newline at end of file diff --git a/test/test_suite/bitstruct/bitstruct_other_int_array.c3 b/test/test_suite/bitstruct/bitstruct_other_int_array.c3 new file mode 100644 index 000000000..b248f1eba --- /dev/null +++ b/test/test_suite/bitstruct/bitstruct_other_int_array.c3 @@ -0,0 +1,10 @@ +bitstruct Foo2 : int[2] // #error: The type of the bitstruct cannot be 'int[2]' but must be an +{ + bool enable_version; +} +fn void main() +{ + Foo2 a2 = { }; + Foo2 b2 = { .enable_version, }; + if (!(a2 & b2)) return; +} \ No newline at end of file diff --git a/test/test_suite/bitstruct/invalid_bitstruct_type.c3 b/test/test_suite/bitstruct/invalid_bitstruct_type.c3 index d4d616ec0..d195909ce 100644 --- a/test/test_suite/bitstruct/invalid_bitstruct_type.c3 +++ b/test/test_suite/bitstruct/invalid_bitstruct_type.c3 @@ -1,5 +1,5 @@ -bitstruct Test : float // #error: The type of the bitstruct cannot be 'float' but must be an integer or an array of integers. +bitstruct Test : float // #error: The type of the bitstruct cannot be 'float' but must be an integer { int a : 1..3; int b : 5..10;