| ... | @@ -2352,6 +2352,10 @@ pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_in | ... | @@ -2352,6 +2352,10 @@ pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_in |
| 2352 | }); | 2352 | }); |
| 2353 | } | 2353 | } |
| 2354 | | 2354 | |
| | 2355 | pub fn failWithUndefSliceLen(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { |
| | 2356 | return sema.fail(block, src, "use of slice with undefined length here causes illegal behavior", .{}); |
| | 2357 | } |
| | 2358 | |
| 2355 | pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { | 2359 | pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { |
| 2356 | return sema.fail(block, src, "division by zero here causes illegal behavior", .{}); | 2360 | return sema.fail(block, src, "division by zero here causes illegal behavior", .{}); |
| 2357 | } | 2361 | } |
| ... | @@ -3113,9 +3117,14 @@ fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -3113,9 +3117,14 @@ fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 3113 | try sema.validateDeref(block, src, operand, operand_ty); | 3117 | try sema.validateDeref(block, src, operand, operand_ty); |
| 3114 | | 3118 | |
| 3115 | const ptr_info = operand_ty.ptrInfo(zcu); | 3119 | const ptr_info = operand_ty.ptrInfo(zcu); |
| 3116 | return switch (ptr_info.flags.size) { | 3120 | return single_ptr: switch (ptr_info.flags.size) { |
| 3117 | .many, .slice => unreachable, // cannot be dereferenced | 3121 | .many => unreachable, // cannot be dereferenced directly |
| 3118 | .c => single_ptr: { | 3122 | .slice => { |
| | 3123 | const slice_val = sema.resolveValue(operand).?; |
| | 3124 | const slice = zcu.intern_pool.indexToKey(slice_val.toIntern()).slice; |
| | 3125 | break :single_ptr .fromValue(try pt.sliceToArrayPtr(slice)); |
| | 3126 | }, |
| | 3127 | .c => { |
| 3119 | const single_ptr_ty = try pt.ptrType(p: { | 3128 | const single_ptr_ty = try pt.ptrType(p: { |
| 3120 | var p = ptr_info; | 3129 | var p = ptr_info; |
| 3121 | p.flags.size = .one; | 3130 | p.flags.size = .one; |
| ... | @@ -3149,18 +3158,26 @@ fn validateDeref( | ... | @@ -3149,18 +3158,26 @@ fn validateDeref( |
| 3149 | ) CompileError!void { | 3158 | ) CompileError!void { |
| 3150 | const pt = sema.pt; | 3159 | const pt = sema.pt; |
| 3151 | const zcu = pt.zcu; | 3160 | const zcu = pt.zcu; |
| | 3161 | const ip = &zcu.intern_pool; |
| 3152 | if (ty.zigTypeTag(zcu) != .pointer) { | 3162 | if (ty.zigTypeTag(zcu) != .pointer) { |
| 3153 | return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); | 3163 | return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); |
| 3154 | } else switch (ty.ptrSize(zcu)) { | 3164 | } |
| 3155 | .one, .c => {}, | 3165 | const size = ty.ptrSize(zcu); |
| | 3166 | switch (size) { |
| 3156 | .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}), | 3167 | .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}), |
| 3157 | .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{ty.fmt(pt)}), | 3168 | .one, .c, .slice => {}, |
| 3158 | } | 3169 | } |
| 3159 | if (sema.resolveValue(ref)) |val| { | 3170 | if (sema.resolveValue(ref)) |val| { |
| 3160 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. | 3171 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. |
| 3161 | if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { | 3172 | if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { |
| 3162 | return sema.fail(block, src, "cannot dereference undefined value", .{}); | 3173 | return sema.fail(block, src, "cannot dereference undefined value", .{}); |
| 3163 | } | 3174 | } |
| | 3175 | // We need a defined slice length for the array type the slice should be dereferenced to. |
| | 3176 | if (size == .slice and ip.indexToKey(val.toIntern()).slice.len == .undef_usize) { |
| | 3177 | return sema.fail(block, src, "cannot dereference slice with undefined length", .{}); |
| | 3178 | } |
| | 3179 | } else if (size == .slice) { |
| | 3180 | return sema.fail(block, src, "index syntax required to access runtime-known slice", .{}); |
| 3164 | } | 3181 | } |
| 3165 | } | 3182 | } |
| 3166 | | 3183 | |
| ... | @@ -13570,14 +13587,14 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -13570,14 +13587,14 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13570 | const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu)) | 13587 | const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu)) |
| 13571 | try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src | 13588 | try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src |
| 13572 | else if (lhs_ty.isSlice(zcu)) | 13589 | else if (lhs_ty.isSlice(zcu)) |
| 13573 | try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val) orelse break :rs lhs_src | 13590 | try sema.maybeDerefSliceAsArray(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src |
| 13574 | else | 13591 | else |
| 13575 | lhs_val; | 13592 | lhs_val; |
| 13576 | | 13593 | |
| 13577 | const rhs_sub_val = if (rhs_ty.isSinglePointer(zcu)) | 13594 | const rhs_sub_val = if (rhs_ty.isSinglePointer(zcu)) |
| 13578 | try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src | 13595 | try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src |
| 13579 | else if (rhs_ty.isSlice(zcu)) | 13596 | else if (rhs_ty.isSlice(zcu)) |
| 13580 | try sema.maybeDerefSliceAsArray(block, rhs_src, rhs_val) orelse break :rs rhs_src | 13597 | try sema.maybeDerefSliceAsArray(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src |
| 13581 | else | 13598 | else |
| 13582 | rhs_val; | 13599 | rhs_val; |
| 13583 | | 13600 | |
| ... | @@ -30940,8 +30957,11 @@ fn analyzeLoad( | ... | @@ -30940,8 +30957,11 @@ fn analyzeLoad( |
| 30940 | }; | 30957 | }; |
| 30941 | | 30958 | |
| 30942 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { | 30959 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 30943 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { | 30960 | if (switch (ptr_ty.ptrSize(zcu)) { |
| 30944 | return Air.internedToRef(elem_val.toIntern()); | 30961 | .slice => try sema.maybeDerefSliceAsArray(block, src, ptr_val, ptr_ty), |
| | 30962 | else => try sema.pointerDeref(block, src, ptr_val, ptr_ty), |
| | 30963 | }) |elem_val| { |
| | 30964 | return .fromValue(elem_val); |
| 30945 | } | 30965 | } |
| 30946 | } | 30966 | } |
| 30947 | | 30967 | |
| ... | @@ -34558,7 +34578,7 @@ fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool { | ... | @@ -34558,7 +34578,7 @@ fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool { |
| 34558 | .slice => { | 34578 | .slice => { |
| 34559 | // If the slice contents are runtime-known, reification will fail later on with a | 34579 | // If the slice contents are runtime-known, reification will fail later on with a |
| 34560 | // specific error message. | 34580 | // specific error message. |
| 34561 | const arr = try sema.maybeDerefSliceAsArray(block, src, val) orelse return false; | 34581 | const arr = try sema.maybeDerefSliceAsArray(block, src, val, val.typeOf(zcu)) orelse return false; |
| 34562 | return sema.anyUndef(block, src, arr); | 34582 | return sema.anyUndef(block, src, arr); |
| 34563 | }, | 34583 | }, |
| 34564 | .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| { | 34584 | .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| { |
| ... | @@ -34599,7 +34619,7 @@ fn derefSliceAsArray( | ... | @@ -34599,7 +34619,7 @@ fn derefSliceAsArray( |
| 34599 | /// being comptime-resolved is that the block is being comptime-evaluated. | 34619 | /// being comptime-resolved is that the block is being comptime-evaluated. |
| 34600 | reason: ?ComptimeReason, | 34620 | reason: ?ComptimeReason, |
| 34601 | ) CompileError!Value { | 34621 | ) CompileError!Value { |
| 34602 | return try sema.maybeDerefSliceAsArray(block, src, slice_val) orelse { | 34622 | return try sema.maybeDerefSliceAsArray(block, src, slice_val, slice_val.typeOf(sema.pt.zcu)) orelse { |
| 34603 | return sema.failWithNeededComptime(block, src, reason); | 34623 | return sema.failWithNeededComptime(block, src, reason); |
| 34604 | }; | 34624 | }; |
| 34605 | } | 34625 | } |
| ... | @@ -34612,37 +34632,23 @@ fn maybeDerefSliceAsArray( | ... | @@ -34612,37 +34632,23 @@ fn maybeDerefSliceAsArray( |
| 34612 | block: *Block, | 34632 | block: *Block, |
| 34613 | src: LazySrcLoc, | 34633 | src: LazySrcLoc, |
| 34614 | slice_val: Value, | 34634 | slice_val: Value, |
| | 34635 | slice_ty: Type, |
| 34615 | ) CompileError!?Value { | 34636 | ) CompileError!?Value { |
| 34616 | const pt = sema.pt; | 34637 | const pt = sema.pt; |
| 34617 | const zcu = pt.zcu; | 34638 | const zcu = pt.zcu; |
| 34618 | const ip = &zcu.intern_pool; | | |
| 34619 | const slice_ty = slice_val.typeOf(zcu); | | |
| 34620 | assert(slice_ty.zigTypeTag(zcu) == .pointer); | | |
| 34621 | switch (slice_ty.ptrInfo(zcu).flags.size) { | 34639 | switch (slice_ty.ptrInfo(zcu).flags.size) { |
| 34622 | .slice => {}, | 34640 | .slice => {}, |
| 34623 | .one => return sema.pointerDeref(block, src, slice_val, slice_ty), | 34641 | .one => return sema.pointerDeref(block, src, slice_val, slice_ty), |
| 34624 | .many, .c => unreachable, | 34642 | .many, .c => unreachable, |
| 34625 | } | 34643 | } |
| 34626 | const slice = switch (ip.indexToKey(slice_val.toIntern())) { | 34644 | const slice = switch (zcu.intern_pool.indexToKey(slice_val.toIntern())) { |
| 34627 | .undef => return sema.failWithUseOfUndef(block, src, null), | 34645 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 34628 | .slice => |slice| slice, | 34646 | .slice => |slice| slice, |
| 34629 | else => unreachable, | 34647 | else => unreachable, |
| 34630 | }; | 34648 | }; |
| 34631 | const elem_ty = Type.fromInterned(slice.ty).childType(zcu); | 34649 | if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src); |
| 34632 | const len = Value.fromInterned(slice.len).toUnsignedInt(zcu); | 34650 | const casted_ptr = try pt.sliceToArrayPtr(slice); |
| 34633 | const array_ty = try pt.arrayType(.{ | 34651 | return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu)); |
| 34634 | .child = elem_ty.toIntern(), | | |
| 34635 | .len = len, | | |
| 34636 | }); | | |
| 34637 | const ptr_ty = try pt.ptrType(p: { | | |
| 34638 | var p = Type.fromInterned(slice.ty).ptrInfo(zcu); | | |
| 34639 | p.flags.size = .one; | | |
| 34640 | p.child = array_ty.toIntern(); | | |
| 34641 | p.sentinel = .none; | | |
| 34642 | break :p p; | | |
| 34643 | }); | | |
| 34644 | const casted_ptr = try pt.getCoerced(Value.fromInterned(slice.ptr), ptr_ty); | | |
| 34645 | return sema.pointerDeref(block, src, casted_ptr, ptr_ty); | | |
| 34646 | } | 34652 | } |
| 34647 | | 34653 | |
| 34648 | fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { | 34654 | fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { |