authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-05 16:22:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-05 16:22:40-07:00
logb3225a755a78502245bc9c7d7419ebeb67201320
tree7e1e2d770f57dd563caaebdc66a1edd1690fb515
parent0ff9a4d21c1b65c574659be295446f2dd7591723

stage1: avoid incorrectly reading ZigValue data

Hashing, equality checking, and expanding lazy values were not inspecting the is_comptime field of structs, causing incorrect behavior for tuples. When looking at a comptime value of a struct, if the is_comptime field is true, the value must be learned from the type rather than the value.

2 files changed, 23 insertions(+), 3 deletions(-)

src/stage1/analyze.cpp+18-3
...@@ -5719,6 +5719,12 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {...@@ -5719,6 +5719,12 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {
5719 size_t field_count = const_val->type->data.structure.src_field_count;5719 size_t field_count = const_val->type->data.structure.src_field_count;
5720 for (size_t i = 0; i < field_count; i += 1) {5720 for (size_t i = 0; i < field_count; i += 1) {
5721 ZigValue *field = const_val->data.x_struct.fields[i];5721 ZigValue *field = const_val->data.x_struct.fields[i];
5722 if (const_val->type->data.structure.fields[i]->is_comptime) {
5723 // The values of comptime struct fields are part of the
5724 // type, not the value, so they do not participate in equality
5725 // or hash of comptime values.
5726 continue;
5727 }
5722 hash_val = hash_combine_const_val(hash_val, field);5728 hash_val = hash_combine_const_val(hash_val, field);
5723 }5729 }
5724 return hash_val;5730 return hash_val;
...@@ -7321,6 +7327,12 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {...@@ -7321,6 +7327,12 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
7321 return const_values_equal_array(g, a, b, a->type->data.array.len);7327 return const_values_equal_array(g, a, b, a->type->data.array.len);
7322 case ZigTypeIdStruct:7328 case ZigTypeIdStruct:
7323 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {7329 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
7330 if (a->type->data.structure.fields[i]->is_comptime) {
7331 // The values of comptime struct fields are part of the
7332 // type, not the value, so they do not participate in equality
7333 // or hash of comptime values.
7334 continue;
7335 }
7324 ZigValue *field_a = a->data.x_struct.fields[i];7336 ZigValue *field_a = a->data.x_struct.fields[i];
7325 ZigValue *field_b = b->data.x_struct.fields[i];7337 ZigValue *field_b = b->data.x_struct.fields[i];
7326 if (!const_values_equal(g, field_a, field_b))7338 if (!const_values_equal(g, field_a, field_b))
...@@ -9945,10 +9957,13 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {...@@ -9945,10 +9957,13 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
9945 dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count);9957 dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count);
9946 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {9958 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
9947 TypeStructField *type_struct_field = dest->type->data.structure.fields[i];9959 TypeStructField *type_struct_field = dest->type->data.structure.fields[i];
9948 // comptime-known values are stored in the field init_val inside9960 if (type_struct_field->is_comptime) {
9949 // the struct type.9961 // comptime-known values are stored in the field init_val inside
9950 if (type_struct_field->is_comptime)9962 // the struct type. The data stored here is not supposed to be read
9963 // at all; the code should look at the type system and notice the field
9964 // is comptime and look at the type to learn the value.
9951 continue;9965 continue;
9966 }
9952 copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);9967 copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]);
9953 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;9968 dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct;
9954 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;9969 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
src/stage1/ir.cpp+5
...@@ -25620,6 +25620,11 @@ static Error ir_resolve_lazy_recurse(IrAnalyze *ira, AstNode *source_node, ZigVa...@@ -25620,6 +25620,11 @@ static Error ir_resolve_lazy_recurse(IrAnalyze *ira, AstNode *source_node, ZigVa
25620 case ZigTypeIdStruct:25620 case ZigTypeIdStruct:
25621 for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {25621 for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {
25622 ZigValue *field = val->data.x_struct.fields[i];25622 ZigValue *field = val->data.x_struct.fields[i];
25623 if (val->type->data.structure.fields[i]->is_comptime) {
25624 // comptime struct fields do not need to be resolved because
25625 // they are not part of the value.
25626 continue;
25627 }
25623 if ((err = ir_resolve_lazy_recurse(ira, source_node, field)))25628 if ((err = ir_resolve_lazy_recurse(ira, source_node, field)))
25624 return err;25629 return err;
25625 }25630 }