Commit ba5cbea0c3

kkHAIKE <kkhaike@gmail.com>
2022-09-27 12:23:51
Sema: fix segfault when union init with empty field
1 parent f7f15e9
Changed files (2)
src/Sema.zig
@@ -15885,6 +15885,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
         .Struct => return sema.structInitEmpty(block, obj_ty, src, src),
         .Array, .Vector => return sema.arrayInitEmpty(block, src, obj_ty),
         .Void => return sema.addConstant(obj_ty, Value.void),
+        .Union => return sema.fail(block, src, "union initializer must initialize one field", .{}),
         else => return sema.failWithArrayInitNotSupported(block, src, obj_ty),
     }
 }
@@ -25854,14 +25855,19 @@ fn coerceAnonStructToUnion(
     inst_src: LazySrcLoc,
 ) !Air.Inst.Ref {
     const inst_ty = sema.typeOf(inst);
-    const anon_struct = inst_ty.castTag(.anon_struct).?.data;
-    if (anon_struct.types.len != 1) {
+    const field_count = inst_ty.structFieldCount();
+    if (field_count != 1) {
         const msg = msg: {
-            const msg = try sema.errMsg(
+            const msg = if (field_count > 1) try sema.errMsg(
                 block,
                 inst_src,
                 "cannot initialize multiple union fields at once, unions can only have one active field",
                 .{},
+            ) else try sema.errMsg(
+                block,
+                inst_src,
+                "union initializer must initialize one field",
+                .{},
             );
             errdefer msg.destroy(sema.gpa);
 
@@ -25874,6 +25880,7 @@ fn coerceAnonStructToUnion(
         return sema.failWithOwnedErrorMsg(msg);
     }
 
+    const anon_struct = inst_ty.castTag(.anon_struct).?.data;
     const field_name = anon_struct.names[0];
     const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
     return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
test/cases/compile_errors/union_init_with_none_or_multiple_fields.zig
@@ -0,0 +1,37 @@
+const U1 = union {
+    a: u8,
+    b: i8,
+};
+const U2 = union(enum) {
+    a: u8,
+    b: i8,
+};
+export fn u1z() void {
+    const x: U1 = .{};
+    _ = x;
+}
+export fn u1m() void {
+    const x: U1 = .{ .a = 1, .b = 1 };
+    _ = x;
+}
+export fn u2z() void {
+    const x: U2 = U2{};
+    _ = x;
+}
+export fn u2m() void {
+    const x: U2 = .{ .a = 1, .b = 1 };
+    _ = x;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :9:1: error: union initializer must initialize one field
+// :14:20: error: cannot initialize multiple union fields at once, unions can only have one active field
+// :14:31: note: additional initializer here
+// :18:21: error: union initializer must initialize one field
+// :22:20: error: cannot initialize multiple union fields at once, unions can only have one active field
+// :22:31: note: additional initializer here
+// :1:12: note: union declared here
+// :5:12: note: union declared here