| ... | ... | @@ -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 | 2359 | pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { |
| 2356 | 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 | 3117 | try sema.validateDeref(block, src, operand, operand_ty); |
| 3114 | 3118 | |
| 3115 | 3119 | const ptr_info = operand_ty.ptrInfo(zcu); |
| 3116 | | return switch (ptr_info.flags.size) { |
| 3117 | | .many, .slice => unreachable, // cannot be dereferenced |
| 3118 | | .c => single_ptr: { |
| 3120 | return single_ptr: switch (ptr_info.flags.size) { |
| 3121 | .many => unreachable, // cannot be dereferenced directly |
| 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 | 3128 | const single_ptr_ty = try pt.ptrType(p: { |
| 3120 | 3129 | var p = ptr_info; |
| 3121 | 3130 | p.flags.size = .one; |
| ... | ... | @@ -3149,18 +3158,26 @@ fn validateDeref( |
| 3149 | 3158 | ) CompileError!void { |
| 3150 | 3159 | const pt = sema.pt; |
| 3151 | 3160 | const zcu = pt.zcu; |
| 3161 | const ip = &zcu.intern_pool; |
| 3152 | 3162 | if (ty.zigTypeTag(zcu) != .pointer) { |
| 3153 | 3163 | return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); |
| 3154 | | } else switch (ty.ptrSize(zcu)) { |
| 3155 | | .one, .c => {}, |
| 3164 | } |
| 3165 | const size = ty.ptrSize(zcu); |
| 3166 | switch (size) { |
| 3156 | 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 | 3170 | if (sema.resolveValue(ref)) |val| { |
| 3160 | 3171 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. |
| 3161 | 3172 | if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { |
| 3162 | 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 | 13587 | const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu)) |
| 13571 | 13588 | try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :rs lhs_src |
| 13572 | 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 | 13591 | else |
| 13575 | 13592 | lhs_val; |
| 13576 | 13593 | |
| 13577 | 13594 | const rhs_sub_val = if (rhs_ty.isSinglePointer(zcu)) |
| 13578 | 13595 | try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty) orelse break :rs rhs_src |
| 13579 | 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 | 13598 | else |
| 13582 | 13599 | rhs_val; |
| 13583 | 13600 | |
| ... | ... | @@ -30940,8 +30957,11 @@ fn analyzeLoad( |
| 30940 | 30957 | }; |
| 30941 | 30958 | |
| 30942 | 30959 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 30943 | | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { |
| 30944 | | return Air.internedToRef(elem_val.toIntern()); |
| 30960 | if (switch (ptr_ty.ptrSize(zcu)) { |
| 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 | 34578 | .slice => { |
| 34559 | 34579 | // If the slice contents are runtime-known, reification will fail later on with a |
| 34560 | 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 | 34582 | return sema.anyUndef(block, src, arr); |
| 34563 | 34583 | }, |
| 34564 | 34584 | .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| { |
| ... | ... | @@ -34599,7 +34619,7 @@ fn derefSliceAsArray( |
| 34599 | 34619 | /// being comptime-resolved is that the block is being comptime-evaluated. |
| 34600 | 34620 | reason: ?ComptimeReason, |
| 34601 | 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 | 34623 | return sema.failWithNeededComptime(block, src, reason); |
| 34604 | 34624 | }; |
| 34605 | 34625 | } |
| ... | ... | @@ -34612,37 +34632,23 @@ fn maybeDerefSliceAsArray( |
| 34612 | 34632 | block: *Block, |
| 34613 | 34633 | src: LazySrcLoc, |
| 34614 | 34634 | slice_val: Value, |
| 34635 | slice_ty: Type, |
| 34615 | 34636 | ) CompileError!?Value { |
| 34616 | 34637 | const pt = sema.pt; |
| 34617 | 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 | 34639 | switch (slice_ty.ptrInfo(zcu).flags.size) { |
| 34622 | 34640 | .slice => {}, |
| 34623 | 34641 | .one => return sema.pointerDeref(block, src, slice_val, slice_ty), |
| 34624 | 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 | 34645 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 34628 | 34646 | .slice => |slice| slice, |
| 34629 | 34647 | else => unreachable, |
| 34630 | 34648 | }; |
| 34631 | | const elem_ty = Type.fromInterned(slice.ty).childType(zcu); |
| 34632 | | const len = Value.fromInterned(slice.len).toUnsignedInt(zcu); |
| 34633 | | const array_ty = try pt.arrayType(.{ |
| 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); |
| 34649 | if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src); |
| 34650 | const casted_ptr = try pt.sliceToArrayPtr(slice); |
| 34651 | return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu)); |
| 34646 | 34652 | } |
| 34647 | 34653 | |
| 34648 | 34654 | fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { |