diff --git a/releasenotes.md b/releasenotes.md index 875169097..23c5fcb53 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -127,6 +127,7 @@ - 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 +- Bitstruct as substruct fails to properly work with designated initializers. #2827 ### 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_initializers.c b/src/compiler/sema_initializers.c index a4fe7c3bb..53fd17ba1 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -519,13 +519,11 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type } } Type *original = flattened->canonical; - bool is_bitstruct = original->type_kind == TYPE_BITSTRUCT; - bool is_structlike = type_is_union_or_strukt(original) || is_bitstruct; + bool is_structlike = type_is_union_or_strukt(original) || original->type_kind == TYPE_BITSTRUCT; ArrayIndex max_index = -1; bool optional = false; Type *inner_type = NULL; bool is_inferred = type_is_inferred(flattened); - int bitmember_count_without_value = 0; FOREACH(Expr *, expr, init_expressions) { Decl *member; @@ -535,10 +533,8 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type Expr *value = expr->designator_expr.value; if (!value && is_bitmember && member->var.start_bit == member->var.end_bit && type_flatten(result) == type_bool) { - ASSERT(is_bitstruct); value = expr_new_const_bool(INVALID_SPAN, type_bool, true); expr->designator_expr.value = value; - bitmember_count_without_value += 1; } if (!value) RETURN_SEMA_ERROR(expr, "This initializer needs a value."); if (!sema_analyse_expr_rhs(context, result, value, true, no_match_ref, false)) return false; @@ -553,10 +549,6 @@ static bool sema_expr_analyse_designated_initializer(SemaContext *context, Type inner_type = type_no_optional(value->type); } } - if (bitmember_count_without_value != 0 && bitmember_count_without_value != vec_size(init_expressions)) - { - RETURN_SEMA_ERROR(initializer, "Mixing the omission of initializers is not permitted."); - } Type *type; if (!is_structlike && is_inferred) { diff --git a/test/test_suite/bitstruct/bitstruct_designated_deep.c3t b/test/test_suite/bitstruct/bitstruct_designated_deep.c3t new file mode 100644 index 000000000..51abc5db9 --- /dev/null +++ b/test/test_suite/bitstruct/bitstruct_designated_deep.c3t @@ -0,0 +1,18 @@ +// #target: macos-x64 +module test; +struct Foo4 +{ + bitstruct : short + { + short expand : 1..7; + bool b : 8; + } +} +fn void main() +{ + Foo4 f4 = { .expand = 2, .b }; +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant %Foo4 { i16 260 }, align 2 diff --git a/test/test_suite/bitstruct/bitstruct_init.c3 b/test/test_suite/bitstruct/bitstruct_init.c3 index d042dcc4c..a7feeb72b 100644 --- a/test/test_suite/bitstruct/bitstruct_init.c3 +++ b/test/test_suite/bitstruct/bitstruct_init.c3 @@ -91,12 +91,10 @@ fn void test4() Flags1 flags1 = {.a, .b, .c}; flags1 = {.a}; flags1 = {.a = true, .b = true, .c = false}; - flags1 = {.a, .b = true, .c = true}; // #error: Mixing the omission Foo foo = { .x = 0, .z }; // #error: needs a value Flags2 flags2 = {.b, .d}; flags2 = {.b, .c, .d}; // #error: needs a value - flags2 = {.a, .c = 1, .d}; // #error: Mixing the omission Flags2_Struct flags2s; flags2s = {.b, .c, .d}; // #error: needs a value