From c7f0d54328c4836f7e492da8cf9ca67f6b99926a Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 18 May 2025 23:40:52 +0200 Subject: [PATCH] Designated const initializers with `{}` would overwrite the parent field. --- releasenotes.md | 1 + src/compiler/sema_initializers.c | 12 +++---- .../bitstruct/designated_initializer_bug.c3t | 31 +++++++++++++++++++ 3 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 test/test_suite/bitstruct/designated_initializer_bug.c3t diff --git a/releasenotes.md b/releasenotes.md index 417a77956..8a1bdd170 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -32,6 +32,7 @@ - $define did not correctly handle generic types #2140. - Incorrect parsing of call attributes #2144. - Error when using named argument on trailing macro body expansion #2139. +- Designated const initializers with `{}` would overwrite the parent field. ### Stdlib changes - Added `String.quick_ztr` and `String.is_zstr` diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index d18bbe3e6..52993c7e4 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -939,18 +939,16 @@ static inline void sema_update_const_initializer_with_designator_struct(ConstIni DesignatorElement **next_element = curr + 1; bool is_last_path_element = next_element == end; - // Optimize in case this is a zero, e.g. [12].b = {} - if (is_last_path_element && sema_initializer_list_is_empty(value)) - { - const_init->kind = CONST_INIT_ZERO; - ASSERT(type_flatten(value->type)->type_kind != TYPE_SLICE); - return; - } Decl **elements = const_init->type->decl->strukt.members; // Convert a zero struct and expand it into all its parts. if (const_init->kind == CONST_INIT_ZERO) { + if (is_last_path_element && sema_initializer_list_is_empty(value)) + { + // In this case we can ignore it. + return; + } const_init->init_struct = NULL; // Allocate array containing all elements { a, b, c ... } FOREACH_IDX(i, Decl *, el, elements) diff --git a/test/test_suite/bitstruct/designated_initializer_bug.c3t b/test/test_suite/bitstruct/designated_initializer_bug.c3t new file mode 100644 index 000000000..bacf09961 --- /dev/null +++ b/test/test_suite/bitstruct/designated_initializer_bug.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 + +module test; +typedef Kind = int; +const Kind KIND_0 = 0; +const Kind KIND_1 = 1; + +struct Foo +{ + int a; +} +struct Descriptor2 +{ + Kind kind; + Foo flags; +} + +Descriptor2 descriptor1 = { + .kind = KIND_1, + .flags = {}, +}; + +fn int main() +{ + Descriptor2 d = descriptor1; + return 0; +} + +/* #expect: test.ll + +@test.descriptor1 = local_unnamed_addr global %Descriptor2 { i32 1, %Foo zeroinitializer }, align 4