Commit 2b88441295

Andrew Kelley <superjoe30@gmail.com>
2017-02-02 20:55:01
fix behavior when initializing struct with undefined
1 parent b78c919
src/analyze.cpp
@@ -275,6 +275,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
     if (*parent_pointer) {
         return *parent_pointer;
     } else {
+        type_ensure_zero_bits_known(g, child_type);
+
         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);
 
         const char *const_str = is_const ? "const " : "";
@@ -3190,7 +3192,7 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
 }
 
 
-void init_const_undefined(ConstExprValue *const_val) {
+void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
     TypeTableEntry *canon_wanted_type = get_underlying_type(const_val->type);
     if (canon_wanted_type->id == TypeTableEntryIdArray) {
         const_val->special = ConstValSpecialStatic;
@@ -3200,12 +3202,24 @@ void init_const_undefined(ConstExprValue *const_val) {
         for (size_t i = 0; i < elem_count; i += 1) {
             ConstExprValue *element_val = &const_val->data.x_array.elements[i];
             element_val->type = canon_wanted_type->data.array.child_type;
-            init_const_undefined(element_val);
+            init_const_undefined(g, element_val);
             if (get_underlying_type(element_val->type)->id == TypeTableEntryIdArray) {
                 element_val->data.x_array.parent_array = const_val;
                 element_val->data.x_array.parent_array_index = i;
             }
         }
+    } else if (canon_wanted_type->id == TypeTableEntryIdStruct) {
+        ensure_complete_type(g, canon_wanted_type);
+
+        const_val->special = ConstValSpecialStatic;
+        size_t field_count = canon_wanted_type->data.structure.src_field_count;
+        const_val->data.x_struct.fields = allocate<ConstExprValue>(field_count);
+        for (size_t i = 0; i < field_count; i += 1) {
+            ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
+            field_val->type = canon_wanted_type->data.structure.fields[i].type_entry;
+            assert(field_val->type);
+            init_const_undefined(g, field_val);
+        }
     } else {
         const_val->special = ConstValSpecialUndef;
     }
src/analyze.hpp
@@ -136,6 +136,6 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
 void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);
 ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end);
 
-void init_const_undefined(ConstExprValue *const_val);
+void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
 
 #endif
src/ir.cpp
@@ -6352,7 +6352,7 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc
 {
     IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
             source_instr->source_node, wanted_type, target->value.depends_on_compile_var);
-    init_const_undefined(&result->value);
+    init_const_undefined(ira->codegen, &result->value);
     return result;
 }
 
test/cases/eval.zig
@@ -252,29 +252,3 @@ fn comptimeIterateOverFnPtrList() {
     assert(performFn('o', 0) == 1);
     assert(performFn('w', 99) == 99);
 }
-
-
-fn initStaticArray() -> [10]i32 {
-    var array: [10]i32 = undefined;
-    array[0] = 1;
-    array[4] = 2;
-    array[7] = 3;
-    array[9] = 4;
-    return array;
-}
-const static_array = initStaticArray();
-fn initStaticArrayToUndefined() {
-    @setFnTest(this);
-
-    assert(static_array[0] == 1);
-    assert(static_array[4] == 2);
-    assert(static_array[7] == 3);
-    assert(static_array[9] == 4);
-
-    comptime {
-        assert(static_array[0] == 1);
-        assert(static_array[4] == 2);
-        assert(static_array[7] == 3);
-        assert(static_array[9] == 4);
-    }
-}
test/cases/undefined.zig
@@ -0,0 +1,49 @@
+const assert = @import("std").debug.assert;
+
+fn initStaticArray() -> [10]i32 {
+    var array: [10]i32 = undefined;
+    array[0] = 1;
+    array[4] = 2;
+    array[7] = 3;
+    array[9] = 4;
+    return array;
+}
+const static_array = initStaticArray();
+fn initStaticArrayToUndefined() {
+    @setFnTest(this);
+
+    assert(static_array[0] == 1);
+    assert(static_array[4] == 2);
+    assert(static_array[7] == 3);
+    assert(static_array[9] == 4);
+
+    comptime {
+        assert(static_array[0] == 1);
+        assert(static_array[4] == 2);
+        assert(static_array[7] == 3);
+        assert(static_array[9] == 4);
+    }
+}
+
+const Foo = struct {
+    x: i32,
+};
+
+fn setFooX(foo: &Foo) {
+    foo.x = 2;
+}
+
+fn assignUndefinedToStruct() {
+    @setFnTest(this);
+
+    comptime {
+        var foo: Foo = undefined;
+        setFooX(&foo);
+        assert(foo.x == 2);
+    }
+    {
+        var foo: Foo = undefined;
+        setFooX(&foo);
+        assert(foo.x == 2);
+    }
+}
test/self_hosted.zig
@@ -28,5 +28,6 @@ const test_switch = @import("cases/switch.zig");
 const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig");
 const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig");
 const test_this = @import("cases/this.zig");
+const test_undefined = @import("cases/undefined.zig");
 const test_var_args = @import("cases/var_args.zig");
 const test_while = @import("cases/while.zig");