diff --git a/releasenotes.md b/releasenotes.md index 298dffd39..40e7278ca 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -16,6 +16,7 @@ - Generic modules parameterized with constants would sometimes get the wrong parameterized module name causing conversion errors #1192. - Duplicate emit of expressions on negation would incorrectly compile negated macros. - Casting a slice address to its pointer type should not compile #1193. +- Union is not properly zero-initialized with designated initializer #1194. ### Stdlib changes - Add 'zstr' variants for `string::new_format` / `string::tformat`. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 0172514e8..59c5835b7 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2124,14 +2124,12 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa llvm_emit_initialize_reference_designated_bitstruct(c, ref, type->decl, elements); return; } - // Getting ready to initialize, get the real type. - Type *real_type = type_lowering(ref->type); // Make sure we have an address. llvm_value_addr(c, ref); - // Clear the memory if not union. - if (real_type->type_kind != TYPE_UNION) llvm_store_zero(c, ref); + // Clear the memory + llvm_store_zero(c, ref); // Now walk through the elements. VECEACH(elements, i) diff --git a/test/test_suite/union/designated_union_zeroing.c3t b/test/test_suite/union/designated_union_zeroing.c3t new file mode 100644 index 000000000..1b3fdf78b --- /dev/null +++ b/test/test_suite/union/designated_union_zeroing.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +module test; +union Rect { + struct { float[<2>] min, max; } +} + +fn Rect test_rect(float[<2>] max) { + Rect rect = {.max = max}; + assert(rect.min == {}); + return rect; +} + +/* #expect: test.ll + +%Rect = type { %.anon } +%.anon = type { <2 x float>, <2 x float> } + +define { double, double } @test.test_rect(double %0) #0 { +entry: + %max = alloca <2 x float>, align 8 + %rect = alloca %Rect, align 8 + store double %0, ptr %max, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %rect, i8 0, i64 16, i1 false) + %ptradd = getelementptr inbounds i8, ptr %rect, i64 8 + %1 = load <2 x float>, ptr %max, align 8 + store <2 x float> %1, ptr %ptradd, align 8 + %2 = load <2 x float>, ptr %rect, align 8 + %eq = fcmp oeq <2 x float> %2, zeroinitializer + %3 = call i1 @llvm.vector.reduce.and.v2i1(<2 x i1> %eq) + call void @llvm.assume(i1 %3) + %4 = load { double, double }, ptr %rect, align 8 + ret { double, double } %4 +} diff --git a/test/test_suite/union/union_codegen_const.c3t b/test/test_suite/union/union_codegen_const.c3t index 4704fddf0..0374cf7fc 100644 --- a/test/test_suite/union/union_codegen_const.c3t +++ b/test/test_suite/union/union_codegen_const.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 module test; union Foo diff --git a/test/test_suite/union/union_codegen_empty.c3t b/test/test_suite/union/union_codegen_empty.c3t index bd460b762..9e86916b1 100644 --- a/test/test_suite/union/union_codegen_empty.c3t +++ b/test/test_suite/union/union_codegen_empty.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 union UnionA { int a; diff --git a/test/test_suite/union/union_codegen_overwrite_call.c3t b/test/test_suite/union/union_codegen_overwrite_call.c3t index 305840dc5..91ebc0ebb 100644 --- a/test/test_suite/union/union_codegen_overwrite_call.c3t +++ b/test/test_suite/union/union_codegen_overwrite_call.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 module test; union UnionB