Commit d2b94afaf2

Andrew Kelley <superjoe30@gmail.com>
2017-01-30 05:35:34
fix compile time initialization of array with undefined
1 parent 3caf6ba
src/all_types.hpp
@@ -80,6 +80,7 @@ struct ConstArrayValue {
     ConstExprValue *elements;
     // This will be the same as `len` from the type, but we duplicate the information
     // in the constant value so that pointers pointing to arrays can see this size.
+    // TODO now that ConstExprValue has the type field we can use that instead of this.
     size_t size;
     // If the data for this array is supposed to be contained in a different constant
     // value, we link to the parent here. This way getting a pointer to this constant
src/analyze.cpp
@@ -3190,6 +3190,27 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
 }
 
 
+void init_const_undefined(ConstExprValue *const_val) {
+    TypeTableEntry *canon_wanted_type = get_underlying_type(const_val->type);
+    if (canon_wanted_type->id == TypeTableEntryIdArray) {
+        const_val->special = ConstValSpecialStatic;
+        size_t elem_count = canon_wanted_type->data.array.len;
+        const_val->data.x_array.elements = allocate<ConstExprValue>(elem_count);
+        const_val->data.x_array.size = elem_count;
+        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);
+            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 {
+        const_val->special = ConstValSpecialUndef;
+    }
+}
+
 void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) {
     if (type_entry->id == TypeTableEntryIdStruct) {
         if (!type_entry->data.structure.complete)
src/analyze.hpp
@@ -136,4 +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);
+
 #endif
src/ir.cpp
@@ -6347,6 +6347,15 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
     return result;
 }
 
+static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
+        IrInstruction *target, TypeTableEntry *wanted_type)
+{
+    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);
+    return result;
+}
+
 static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction *source_instr,
         IrInstruction *target, TypeTableEntry *wanted_type)
 {
@@ -6671,7 +6680,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
 
     // explicit cast from undefined to anything
     if (actual_type->id == TypeTableEntryIdUndefLit) {
-        return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
+        return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
     }
 
     // explicit cast from something to const pointer of it
test/cases/eval.zig
@@ -252,3 +252,29 @@ 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);
+    }
+}