Commit bee4007ec9

Andrew Kelley <andrew@ziglang.org>
2020-02-28 21:49:19
fix crash with multiple comptime fn calls and...
...default initialized array to undefined closes #4578
1 parent 68dbba2
Changed files (2)
src
test
stage1
behavior
src/analyze.cpp
@@ -5429,6 +5429,8 @@ static bool can_mutate_comptime_var_state(ZigValue *value) {
             return value->data.x_ptr.mut == ConstPtrMutComptimeVar;
 
         case ZigTypeIdArray:
+            if (value->special == ConstValSpecialUndef)
+                return false;
             if (value->type->data.array.len == 0)
                 return false;
             switch (value->data.x_array.special) {
@@ -6701,8 +6703,16 @@ bool const_values_equal_ptr(ZigValue *a, ZigValue *b) {
 }
 
 static bool const_values_equal_array(CodeGen *g, ZigValue *a, ZigValue *b, size_t len) {
-    assert(a->data.x_array.special != ConstArraySpecialUndef);
-    assert(b->data.x_array.special != ConstArraySpecialUndef);
+    if (a->data.x_array.special == ConstArraySpecialUndef &&
+        b->data.x_array.special == ConstArraySpecialUndef)
+    {
+        return true;
+    }
+    if (a->data.x_array.special == ConstArraySpecialUndef ||
+        b->data.x_array.special == ConstArraySpecialUndef)
+    {
+        return false;
+    }
     if (a->data.x_array.special == ConstArraySpecialBuf &&
         b->data.x_array.special == ConstArraySpecialBuf)
     {
@@ -9398,13 +9408,24 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
             dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
         }
     } else if (dest->type->id == ZigTypeIdArray) {
-        if (dest->data.x_array.special == ConstArraySpecialNone) {
-            dest->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(dest->type->data.array.len);
-            for (uint64_t i = 0; i < dest->type->data.array.len; i += 1) {
-                copy_const_val(g, &dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]);
-                dest->data.x_array.data.s_none.elements[i].parent.id = ConstParentIdArray;
-                dest->data.x_array.data.s_none.elements[i].parent.data.p_array.array_val = dest;
-                dest->data.x_array.data.s_none.elements[i].parent.data.p_array.elem_index = i;
+        switch (dest->data.x_array.special) {
+            case ConstArraySpecialNone: {
+                dest->data.x_array.data.s_none.elements = g->pass1_arena->allocate<ZigValue>(dest->type->data.array.len);
+                for (uint64_t i = 0; i < dest->type->data.array.len; i += 1) {
+                    copy_const_val(g, &dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]);
+                    dest->data.x_array.data.s_none.elements[i].parent.id = ConstParentIdArray;
+                    dest->data.x_array.data.s_none.elements[i].parent.data.p_array.array_val = dest;
+                    dest->data.x_array.data.s_none.elements[i].parent.data.p_array.elem_index = i;
+                }
+                break;
+            }
+            case ConstArraySpecialUndef: {
+                // Nothing to copy; the above memcpy did everything we needed.
+                break;
+            }
+            case ConstArraySpecialBuf: {
+                dest->data.x_array.data.s_buf = buf_create_from_buf(src->data.x_array.data.s_buf);
+                break;
             }
         }
     } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
test/stage1/behavior/eval.zig
@@ -807,3 +807,28 @@ test "return 0 from function that has u0 return type" {
         }
     }
 }
+
+test "two comptime calls with array default initialized to undefined" {
+    const S = struct {
+        const CrossTarget = struct {
+            dynamic_linker: DynamicLinker = DynamicLinker{},
+
+            pub fn parse() void {
+                var result: CrossTarget = .{ };
+                result.getCpuArch();
+            }
+
+            pub fn getCpuArch(self: CrossTarget) void { }
+        };
+
+        const DynamicLinker = struct {
+            buffer: [255]u8 = undefined,
+        };
+
+    };
+
+    comptime {
+        S.CrossTarget.parse();
+        S.CrossTarget.parse();
+    }
+}