authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-01 18:55:35-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-01 18:55:35-05:00
log080316cd4f9a20fb4cf493ee071f672416b5864c
treef890d96193e40410b2f958fad37f1e028b006b8d
parentc2cee40aec5a65fa1c0d716f4a0660492717c356
signaturelock-open Commit is signed but in an unrecognized format.

fix assigning to an unwrapped optional field in an inline loop


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

src/ir.cpp+19-1
...@@ -11356,10 +11356,24 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -11356,10 +11356,24 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
11356 }11356 }
11357}11357}
1135811358
11359// Returns whether the x_optional field of ZigValue is active.
11360static bool type_has_optional_repr(ZigType *ty) {
11361 if (ty->id != ZigTypeIdOptional) {
11362 return false;
11363 } else if (get_codegen_ptr_type(ty) != nullptr) {
11364 return false;
11365 } else if (is_opt_err_set(ty)) {
11366 return false;
11367 } else {
11368 return true;
11369 }
11370}
11371
11359static void copy_const_val(ZigValue *dest, ZigValue *src) {11372static void copy_const_val(ZigValue *dest, ZigValue *src) {
11360 memcpy(dest, src, sizeof(ZigValue));11373 memcpy(dest, src, sizeof(ZigValue));
11361 if (src->special != ConstValSpecialStatic)11374 if (src->special != ConstValSpecialStatic)
11362 return;11375 return;
11376 dest->parent.id = ConstParentIdNone;
11363 if (dest->type->id == ZigTypeIdStruct) {11377 if (dest->type->id == ZigTypeIdStruct) {
11364 dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);11378 dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);
11365 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {11379 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
...@@ -11368,8 +11382,12 @@ static void copy_const_val(ZigValue *dest, ZigValue *src) {...@@ -11368,8 +11382,12 @@ static void copy_const_val(ZigValue *dest, ZigValue *src) {
11368 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;11382 dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
11369 dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;11383 dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
11370 }11384 }
11385 } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
11386 dest->data.x_optional = create_const_vals(1);
11387 copy_const_val(dest->data.x_optional, src->data.x_optional);
11388 dest->data.x_optional->parent.id = ConstParentIdOptionalPayload;
11389 dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest;
11371 }11390 }
11372 dest->parent.id = ConstParentIdNone;
11373}11391}
1137411392
11375static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr,11393static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr,
test/stage1/behavior/optional.zig+11
...@@ -119,3 +119,14 @@ test "self-referential struct through a slice of optional" {...@@ -119,3 +119,14 @@ test "self-referential struct through a slice of optional" {
119 var n = S.Node.new();119 var n = S.Node.new();
120 expect(n.data == null);120 expect(n.data == null);
121}121}
122
123test "assigning to an unwrapped optional field in an inline loop" {
124 comptime var maybe_pos_arg: ?comptime_int = null;
125 inline for ("ab") |x| {
126 maybe_pos_arg = 0;
127 if (maybe_pos_arg.? != 0) {
128 @compileError("bad");
129 }
130 maybe_pos_arg.? = 10;
131 }
132}