authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-10-25 11:25:02+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-10-28 21:13:32+02:00
log6d2f103bfb8931e2e65ca7f79d62389b69781492
treef7f6d1fbbaffea1f1cfe9d743008c0e6e977424a
parent1a171a143aaa1be843b6f028cbb8e82aaec79e2c

stage1: Fix crash in comptime struct value copy

Comptime fields are never materialized in the ZigValue so pay attention when iterating over the fields array. Fixes #6800

2 files changed, 30 insertions(+), 1 deletions(-)

src/stage1/analyze.cpp+12-1
...@@ -5686,7 +5686,13 @@ static bool can_mutate_comptime_var_state(ZigValue *value) {...@@ -5686,7 +5686,13 @@ static bool can_mutate_comptime_var_state(ZigValue *value) {
5686 zig_unreachable();5686 zig_unreachable();
5687 case ZigTypeIdStruct:5687 case ZigTypeIdStruct:
5688 for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) {5688 for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) {
5689 if (can_mutate_comptime_var_state(value->data.x_struct.fields[i]))5689 TypeStructField *type_struct_field = value->type->data.structure.fields[i];
5690
5691 ZigValue *field_value = type_struct_field->is_comptime ?
5692 type_struct_field->init_val :
5693 value->data.x_struct.fields[i];
5694
5695 if (can_mutate_comptime_var_state(field_value))
5690 return true;5696 return true;
5691 }5697 }
5692 return false;5698 return false;
...@@ -9690,6 +9696,11 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {...@@ -9690,6 +9696,11 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
9690 if (dest->type->id == ZigTypeIdStruct) {9696 if (dest->type->id == ZigTypeIdStruct) {
9691 dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count);9697 dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count);
9692 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {9698 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
9699 TypeStructField *type_struct_field = dest->type->data.structure.fields[i];
9700 // comptime-known values are stored in the field init_val inside
9701 // the struct type.
9702 if (type_struct_field->is_comptime)
9703 continue;
9693 copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);9704 copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);
9694 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;9705 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;
9695 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;9706 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
test/stage1/behavior/tuple.zig+18
...@@ -93,3 +93,21 @@ test "pass tuple to comptime var parameter" {...@@ -93,3 +93,21 @@ test "pass tuple to comptime var parameter" {
93 S.doTheTest();93 S.doTheTest();
94 comptime S.doTheTest();94 comptime S.doTheTest();
95}95}
96
97test "tuple initializer for var" {
98 const S = struct {
99 fn doTheTest() void {
100 const Bytes = struct {
101 id: usize,
102 };
103
104 var tmp = .{
105 .id = @as(usize, 2),
106 .name = Bytes{ .id = 20 },
107 };
108 }
109 };
110
111 S.doTheTest();
112 comptime S.doTheTest();
113}