Commit c61e0a078c

Andrew Kelley <andrew@ziglang.org>
2019-06-25 17:31:38
fix union init with void payload
all std lib tests passing now
1 parent 3021e5c
Changed files (6)
src/analyze.cpp
@@ -5001,12 +5001,9 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
             field_val->type = wanted_type->data.structure.fields[i].type_entry;
             assert(field_val->type);
             init_const_undefined(g, field_val);
-            ConstParent *parent = get_const_val_parent(g, field_val);
-            if (parent != nullptr) {
-                parent->id = ConstParentIdStruct;
-                parent->data.p_struct.struct_val = const_val;
-                parent->data.p_struct.field_index = i;
-            }
+            field_val->parent.id = ConstParentIdStruct;
+            field_val->parent.data.p_struct.struct_val = const_val;
+            field_val->parent.data.p_struct.field_index = i;
         }
     } else {
         const_val->special = ConstValSpecialUndef;
@@ -5842,11 +5839,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
     zig_unreachable();
 }
 
-// Deprecated. Reference the parent field directly.
-ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
-    return &value->parent;
-}
-
 static const ZigTypeId all_type_ids[] = {
     ZigTypeIdMetaType,
     ZigTypeIdVoid,
src/analyze.hpp
@@ -180,7 +180,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
 ConstExprValue *create_const_vals(size_t count);
 
 ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
-ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
 void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
 void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
 
src/codegen.cpp
@@ -3873,8 +3873,20 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
 
     TypeUnionField *field = instruction->field;
 
-    if (!type_has_bits(field->type_entry))
+    if (!type_has_bits(field->type_entry)) {
+        if (union_type->data.unionation.gen_tag_index == SIZE_MAX) {
+            return nullptr;
+        }
+        if (instruction->initializing) {
+            LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
+            LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
+                    union_type->data.unionation.gen_tag_index, "");
+            LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
+                    &field->enum_field->value);
+            gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
+        }
         return nullptr;
+    }
 
     LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
     LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0);
src/ir.cpp
@@ -17425,11 +17425,9 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
                     ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
                     field_val->special = ConstValSpecialUndef;
                     field_val->type = struct_type->data.structure.fields[i].type_entry;
-                    ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
-                    assert(parent != nullptr);
-                    parent->id = ConstParentIdStruct;
-                    parent->data.p_struct.struct_val = struct_val;
-                    parent->data.p_struct.field_index = i;
+                    field_val->parent.id = ConstParentIdStruct;
+                    field_val->parent.data.p_struct.struct_val = struct_val;
+                    field_val->parent.data.p_struct.field_index = i;
                 }
             }
             IrInstruction *result;
@@ -17507,11 +17505,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
                     ConstExprValue *payload_val = create_const_vals(1);
                     payload_val->special = ConstValSpecialUndef;
                     payload_val->type = field->type_entry;
-                    ConstParent *parent = get_const_val_parent(ira->codegen, payload_val);
-                    if (parent != nullptr) {
-                        parent->id = ConstParentIdUnion;
-                        parent->data.p_union.union_val = union_val;
-                    }
+                    payload_val->parent.id = ConstParentIdUnion;
+                    payload_val->parent.data.p_union.union_val = union_val;
 
                     union_val->special = ConstValSpecialStatic;
                     bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
@@ -25289,7 +25284,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
         case IrInstructionIdReturnPtr:
         case IrInstructionIdTypeOf:
         case IrInstructionIdStructFieldPtr:
-        case IrInstructionIdUnionFieldPtr:
         case IrInstructionIdArrayType:
         case IrInstructionIdPromiseType:
         case IrInstructionIdSliceType:
@@ -25389,6 +25383,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
             }
         case IrInstructionIdUnwrapErrCode:
             return reinterpret_cast<IrInstructionUnwrapErrCode *>(instruction)->initializing;
+        case IrInstructionIdUnionFieldPtr:
+            return reinterpret_cast<IrInstructionUnionFieldPtr *>(instruction)->initializing;
         case IrInstructionIdErrWrapPayload:
             return reinterpret_cast<IrInstructionErrWrapPayload *>(instruction)->result_loc != nullptr;
         case IrInstructionIdErrWrapCode:
std/zig/parser_test.zig
@@ -1,4 +1,4 @@
-// TODO remove `use` keyword eventually
+// TODO remove `use` keyword eventually: https://github.com/ziglang/zig/issues/2591
 test "zig fmt: change use to usingnamespace" {
     try testTransform(
         \\use @import("std");
@@ -105,7 +105,6 @@ test "zig fmt: linksection" {
 }
 
 test "zig fmt: correctly move doc comments on struct fields" {
-    if (true) return error.SkipZigTest; // TODO
     try testTransform(
         \\pub const section_64 = extern struct {
         \\    sectname: [16]u8, /// name of this section
@@ -917,7 +916,6 @@ test "zig fmt: statements with empty line between" {
 }
 
 test "zig fmt: ptr deref operator and unwrap optional operator" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\const a = b.*;
         \\const a = b.?;
@@ -1020,7 +1018,6 @@ test "zig fmt: same-line comment after a statement" {
 }
 
 test "zig fmt: same-line comment after var decl in struct" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\pub const vfs_cap_data = extern struct {
         \\    const Data = struct {}; // when on disk.
@@ -1030,7 +1027,6 @@ test "zig fmt: same-line comment after var decl in struct" {
 }
 
 test "zig fmt: same-line comment after field decl" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\pub const dirent = extern struct {
         \\    d_name: u8,
@@ -1106,7 +1102,6 @@ test "zig fmt: line comments in struct initializer" {
 }
 
 test "zig fmt: first line comment in struct initializer" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\pub async fn acquire(self: *Self) HeldLock {
         \\    return HeldLock{
@@ -1120,7 +1115,6 @@ test "zig fmt: first line comment in struct initializer" {
 }
 
 test "zig fmt: doc comments before struct field" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\pub const Allocator = struct {
         \\    /// Allocate byte_count bytes and return them in a slice, with the
@@ -1218,7 +1212,6 @@ test "zig fmt: comments before switch prong" {
 }
 
 test "zig fmt: comments before var decl in struct" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\pub const vfs_cap_data = extern struct {
         \\    // All of these are mandated as little endian
@@ -1609,7 +1602,6 @@ test "zig fmt: indexing" {
 }
 
 test "zig fmt: struct declaration" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\const S = struct {
         \\    const Self = @This();
@@ -1641,7 +1633,6 @@ test "zig fmt: struct declaration" {
 }
 
 test "zig fmt: enum declaration" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\const E = enum {
         \\    Ok,
@@ -1670,7 +1661,6 @@ test "zig fmt: enum declaration" {
 }
 
 test "zig fmt: union declaration" {
-    if (true) return error.SkipZigTest; // TODO
     try testCanonical(
         \\const U = union {
         \\    Int: u8,
test/stage1/behavior/union.zig
@@ -402,3 +402,23 @@ test "comptime union field value equality" {
     expect(a0 != a1);
     expect(b0 != b1);
 }
+
+test "return union init with void payload" {
+    const S = struct {
+        fn entry() void {
+            expect(func().state == State.one);
+        }
+        const Outer = union(enum) {
+            state: State,
+        };
+        const State = union(enum) {
+            one: void,
+            two: u32,
+        };
+        fn func() Outer {
+            return Outer{ .state = State{ .one = {} }};
+        }
+    };
+    S.entry();
+    comptime S.entry();
+}