From 2b88441295d39d3e988c0771b6ad64531948ff0a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 2 Feb 2017 14:55:01 -0500 Subject: [PATCH] fix behavior when initializing struct with undefined --- src/analyze.cpp | 18 +++++++++++++-- src/analyze.hpp | 2 +- src/ir.cpp | 2 +- test/cases/eval.zig | 26 --------------------- test/cases/undefined.zig | 49 ++++++++++++++++++++++++++++++++++++++++ test/self_hosted.zig | 1 + 6 files changed, 68 insertions(+), 30 deletions(-) create mode 100644 test/cases/undefined.zig diff --git a/src/analyze.cpp b/src/analyze.cpp index 25065e9f88..9278ddd555 100644 --- a/src/analyze.cpp +++ b/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(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; } diff --git a/src/analyze.hpp b/src/analyze.hpp index c22835f038..7c83030c51 100644 --- a/src/analyze.hpp +++ b/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 diff --git a/src/ir.cpp b/src/ir.cpp index 85afc93245..b0908dd7cf 100644 --- a/src/ir.cpp +++ b/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; } diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 0e5c0b37f9..629fb6366b 100644 --- a/test/cases/eval.zig +++ b/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); - } -} diff --git a/test/cases/undefined.zig b/test/cases/undefined.zig new file mode 100644 index 0000000000..6d8d7391b2 --- /dev/null +++ b/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); + } +} diff --git a/test/self_hosted.zig b/test/self_hosted.zig index a6a2f41274..6276633fd4 100644 --- a/test/self_hosted.zig +++ b/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");