| author | |
| committer | |
| log | 62ecc154d9ad065aee57d81afd3a478dd8360fb7 |
| tree | 52f17b58d87a2ef83f2a1607f0aecbee31c33661 |
| parent | 521c753fda3cd5ebb79752287ef3c87d84f8d5c3 |
| parent | eef653904916dc19540458199366807f8837bf98 |
| signature |
stage2: pointer casting fixes and improvements34 files changed, 357 insertions(+), 227 deletions(-)
lib/std/json.zig+3-3| ... | @@ -1560,7 +1560,7 @@ fn parseInternal( | ... | @@ -1560,7 +1560,7 @@ fn parseInternal( |
| 1560 | } | 1560 | } |
| 1561 | } | 1561 | } |
| 1562 | if (field.is_comptime) { | 1562 | if (field.is_comptime) { |
| 1563 | if (!try parsesTo(field.field_type, @ptrCast(*const field.field_type, field.default_value.?).*, tokens, child_options)) { | 1563 | if (!try parsesTo(field.field_type, @ptrCast(*align(1) const field.field_type, field.default_value.?).*, tokens, child_options)) { |
| 1564 | return error.UnexpectedValue; | 1564 | return error.UnexpectedValue; |
| 1565 | } | 1565 | } |
| 1566 | } else { | 1566 | } else { |
| ... | @@ -1587,7 +1587,7 @@ fn parseInternal( | ... | @@ -1587,7 +1587,7 @@ fn parseInternal( |
| 1587 | if (!fields_seen[i]) { | 1587 | if (!fields_seen[i]) { |
| 1588 | if (field.default_value) |default_ptr| { | 1588 | if (field.default_value) |default_ptr| { |
| 1589 | if (!field.is_comptime) { | 1589 | if (!field.is_comptime) { |
| 1590 | const default = @ptrCast(*const field.field_type, default_ptr).*; | 1590 | const default = @ptrCast(*align(1) const field.field_type, default_ptr).*; |
| 1591 | @field(r, field.name) = default; | 1591 | @field(r, field.name) = default; |
| 1592 | } | 1592 | } |
| 1593 | } else { | 1593 | } else { |
| ... | @@ -1667,7 +1667,7 @@ fn parseInternal( | ... | @@ -1667,7 +1667,7 @@ fn parseInternal( |
| 1667 | } | 1667 | } |
| 1668 | 1668 | ||
| 1669 | if (ptrInfo.sentinel) |some| { | 1669 | if (ptrInfo.sentinel) |some| { |
| 1670 | const sentinel_value = @ptrCast(*const ptrInfo.child, some).*; | 1670 | const sentinel_value = @ptrCast(*align(1) const ptrInfo.child, some).*; |
| 1671 | try arraylist.append(sentinel_value); | 1671 | try arraylist.append(sentinel_value); |
| 1672 | const output = arraylist.toOwnedSlice(); | 1672 | const output = arraylist.toOwnedSlice(); |
| 1673 | return output[0 .. output.len - 1 :sentinel_value]; | 1673 | return output[0 .. output.len - 1 :sentinel_value]; |
lib/std/mem.zig+12-11| ... | @@ -297,7 +297,7 @@ pub fn zeroes(comptime T: type) T { | ... | @@ -297,7 +297,7 @@ pub fn zeroes(comptime T: type) T { |
| 297 | }, | 297 | }, |
| 298 | .Array => |info| { | 298 | .Array => |info| { |
| 299 | if (info.sentinel) |sentinel_ptr| { | 299 | if (info.sentinel) |sentinel_ptr| { |
| 300 | const sentinel = @ptrCast(*const info.child, sentinel_ptr).*; | 300 | const sentinel = @ptrCast(*align(1) const info.child, sentinel_ptr).*; |
| 301 | return [_:sentinel]info.child{zeroes(info.child)} ** info.len; | 301 | return [_:sentinel]info.child{zeroes(info.child)} ** info.len; |
| 302 | } | 302 | } |
| 303 | return [_]info.child{zeroes(info.child)} ** info.len; | 303 | return [_]info.child{zeroes(info.child)} ** info.len; |
| ... | @@ -443,7 +443,7 @@ pub fn zeroInit(comptime T: type, init: anytype) T { | ... | @@ -443,7 +443,7 @@ pub fn zeroInit(comptime T: type, init: anytype) T { |
| 443 | 443 | ||
| 444 | inline for (struct_info.fields) |field| { | 444 | inline for (struct_info.fields) |field| { |
| 445 | if (field.default_value) |default_value_ptr| { | 445 | if (field.default_value) |default_value_ptr| { |
| 446 | const default_value = @ptrCast(*const field.field_type, default_value_ptr).*; | 446 | const default_value = @ptrCast(*align(1) const field.field_type, default_value_ptr).*; |
| 447 | @field(value, field.name) = default_value; | 447 | @field(value, field.name) = default_value; |
| 448 | } | 448 | } |
| 449 | } | 449 | } |
| ... | @@ -687,7 +687,7 @@ pub fn span(ptr: anytype) Span(@TypeOf(ptr)) { | ... | @@ -687,7 +687,7 @@ pub fn span(ptr: anytype) Span(@TypeOf(ptr)) { |
| 687 | const l = len(ptr); | 687 | const l = len(ptr); |
| 688 | const ptr_info = @typeInfo(Result).Pointer; | 688 | const ptr_info = @typeInfo(Result).Pointer; |
| 689 | if (ptr_info.sentinel) |s_ptr| { | 689 | if (ptr_info.sentinel) |s_ptr| { |
| 690 | const s = @ptrCast(*const ptr_info.child, s_ptr).*; | 690 | const s = @ptrCast(*align(1) const ptr_info.child, s_ptr).*; |
| 691 | return ptr[0..l :s]; | 691 | return ptr[0..l :s]; |
| 692 | } else { | 692 | } else { |
| 693 | return ptr[0..l]; | 693 | return ptr[0..l]; |
| ... | @@ -719,7 +719,7 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type { | ... | @@ -719,7 +719,7 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type { |
| 719 | // to find the value searched for, which is only the case if it matches | 719 | // to find the value searched for, which is only the case if it matches |
| 720 | // the sentinel of the type passed. | 720 | // the sentinel of the type passed. |
| 721 | if (array_info.sentinel) |sentinel_ptr| { | 721 | if (array_info.sentinel) |sentinel_ptr| { |
| 722 | const sentinel = @ptrCast(*const array_info.child, sentinel_ptr).*; | 722 | const sentinel = @ptrCast(*align(1) const array_info.child, sentinel_ptr).*; |
| 723 | if (end == sentinel) { | 723 | if (end == sentinel) { |
| 724 | new_ptr_info.sentinel = &end; | 724 | new_ptr_info.sentinel = &end; |
| 725 | } else { | 725 | } else { |
| ... | @@ -734,7 +734,7 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type { | ... | @@ -734,7 +734,7 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type { |
| 734 | // to find the value searched for, which is only the case if it matches | 734 | // to find the value searched for, which is only the case if it matches |
| 735 | // the sentinel of the type passed. | 735 | // the sentinel of the type passed. |
| 736 | if (ptr_info.sentinel) |sentinel_ptr| { | 736 | if (ptr_info.sentinel) |sentinel_ptr| { |
| 737 | const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*; | 737 | const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*; |
| 738 | if (end == sentinel) { | 738 | if (end == sentinel) { |
| 739 | new_ptr_info.sentinel = &end; | 739 | new_ptr_info.sentinel = &end; |
| 740 | } else { | 740 | } else { |
| ... | @@ -772,7 +772,7 @@ pub fn sliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) SliceTo(@Typ | ... | @@ -772,7 +772,7 @@ pub fn sliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) SliceTo(@Typ |
| 772 | const length = lenSliceTo(ptr, end); | 772 | const length = lenSliceTo(ptr, end); |
| 773 | const ptr_info = @typeInfo(Result).Pointer; | 773 | const ptr_info = @typeInfo(Result).Pointer; |
| 774 | if (ptr_info.sentinel) |s_ptr| { | 774 | if (ptr_info.sentinel) |s_ptr| { |
| 775 | const s = @ptrCast(*const ptr_info.child, s_ptr).*; | 775 | const s = @ptrCast(*align(1) const ptr_info.child, s_ptr).*; |
| 776 | return ptr[0..length :s]; | 776 | return ptr[0..length :s]; |
| 777 | } else { | 777 | } else { |
| 778 | return ptr[0..length]; | 778 | return ptr[0..length]; |
| ... | @@ -825,7 +825,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { | ... | @@ -825,7 +825,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { |
| 825 | .One => switch (@typeInfo(ptr_info.child)) { | 825 | .One => switch (@typeInfo(ptr_info.child)) { |
| 826 | .Array => |array_info| { | 826 | .Array => |array_info| { |
| 827 | if (array_info.sentinel) |sentinel_ptr| { | 827 | if (array_info.sentinel) |sentinel_ptr| { |
| 828 | const sentinel = @ptrCast(*const array_info.child, sentinel_ptr).*; | 828 | const sentinel = @ptrCast(*align(1) const array_info.child, sentinel_ptr).*; |
| 829 | if (sentinel == end) { | 829 | if (sentinel == end) { |
| 830 | return indexOfSentinel(array_info.child, end, ptr); | 830 | return indexOfSentinel(array_info.child, end, ptr); |
| 831 | } | 831 | } |
| ... | @@ -835,7 +835,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { | ... | @@ -835,7 +835,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { |
| 835 | else => {}, | 835 | else => {}, |
| 836 | }, | 836 | }, |
| 837 | .Many => if (ptr_info.sentinel) |sentinel_ptr| { | 837 | .Many => if (ptr_info.sentinel) |sentinel_ptr| { |
| 838 | const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*; | 838 | const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*; |
| 839 | // We may be looking for something other than the sentinel, | 839 | // We may be looking for something other than the sentinel, |
| 840 | // but iterating past the sentinel would be a bug so we need | 840 | // but iterating past the sentinel would be a bug so we need |
| 841 | // to check for both. | 841 | // to check for both. |
| ... | @@ -849,7 +849,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { | ... | @@ -849,7 +849,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { |
| 849 | }, | 849 | }, |
| 850 | .Slice => { | 850 | .Slice => { |
| 851 | if (ptr_info.sentinel) |sentinel_ptr| { | 851 | if (ptr_info.sentinel) |sentinel_ptr| { |
| 852 | const sentinel = @ptrCast(*const ptr_info.child, sentinel_ptr).*; | 852 | const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*; |
| 853 | if (sentinel == end) { | 853 | if (sentinel == end) { |
| 854 | return indexOfSentinel(ptr_info.child, sentinel, ptr); | 854 | return indexOfSentinel(ptr_info.child, sentinel, ptr); |
| 855 | } | 855 | } |
| ... | @@ -911,7 +911,7 @@ pub fn len(value: anytype) usize { | ... | @@ -911,7 +911,7 @@ pub fn len(value: anytype) usize { |
| 911 | .Many => { | 911 | .Many => { |
| 912 | const sentinel_ptr = info.sentinel orelse | 912 | const sentinel_ptr = info.sentinel orelse |
| 913 | @compileError("length of pointer with no sentinel"); | 913 | @compileError("length of pointer with no sentinel"); |
| 914 | const sentinel = @ptrCast(*const info.child, sentinel_ptr).*; | 914 | const sentinel = @ptrCast(*align(1) const info.child, sentinel_ptr).*; |
| 915 | return indexOfSentinel(info.child, sentinel, value); | 915 | return indexOfSentinel(info.child, sentinel, value); |
| 916 | }, | 916 | }, |
| 917 | .C => { | 917 | .C => { |
| ... | @@ -2882,7 +2882,8 @@ fn AsBytesReturnType(comptime P: type) type { | ... | @@ -2882,7 +2882,8 @@ fn AsBytesReturnType(comptime P: type) type { |
| 2882 | /// Given a pointer to a single item, returns a slice of the underlying bytes, preserving pointer attributes. | 2882 | /// Given a pointer to a single item, returns a slice of the underlying bytes, preserving pointer attributes. |
| 2883 | pub fn asBytes(ptr: anytype) AsBytesReturnType(@TypeOf(ptr)) { | 2883 | pub fn asBytes(ptr: anytype) AsBytesReturnType(@TypeOf(ptr)) { |
| 2884 | const P = @TypeOf(ptr); | 2884 | const P = @TypeOf(ptr); |
| 2885 | return @ptrCast(AsBytesReturnType(P), ptr); | 2885 | const T = AsBytesReturnType(P); |
| 2886 | return @ptrCast(T, @alignCast(meta.alignment(T), ptr)); | ||
| 2886 | } | 2887 | } |
| 2887 | 2888 | ||
| 2888 | test "asBytes" { | 2889 | test "asBytes" { |
lib/std/meta.zig+2-2| ... | @@ -204,12 +204,12 @@ pub fn sentinel(comptime T: type) ?Elem(T) { | ... | @@ -204,12 +204,12 @@ pub fn sentinel(comptime T: type) ?Elem(T) { |
| 204 | switch (info.size) { | 204 | switch (info.size) { |
| 205 | .Many, .Slice => { | 205 | .Many, .Slice => { |
| 206 | const sentinel_ptr = info.sentinel orelse return null; | 206 | const sentinel_ptr = info.sentinel orelse return null; |
| 207 | return @ptrCast(*const info.child, sentinel_ptr).*; | 207 | return @ptrCast(*align(1) const info.child, sentinel_ptr).*; |
| 208 | }, | 208 | }, |
| 209 | .One => switch (@typeInfo(info.child)) { | 209 | .One => switch (@typeInfo(info.child)) { |
| 210 | .Array => |array_info| { | 210 | .Array => |array_info| { |
| 211 | const sentinel_ptr = array_info.sentinel orelse return null; | 211 | const sentinel_ptr = array_info.sentinel orelse return null; |
| 212 | return @ptrCast(*const array_info.child, sentinel_ptr).*; | 212 | return @ptrCast(*align(1) const array_info.child, sentinel_ptr).*; |
| 213 | }, | 213 | }, |
| 214 | else => {}, | 214 | else => {}, |
| 215 | }, | 215 | }, |
lib/std/os/linux.zig+1-1| ... | @@ -888,7 +888,7 @@ else | ... | @@ -888,7 +888,7 @@ else |
| 888 | const vdso_clock_gettime_ty = if (builtin.zig_backend == .stage1) | 888 | const vdso_clock_gettime_ty = if (builtin.zig_backend == .stage1) |
| 889 | fn (i32, *timespec) callconv(.C) usize | 889 | fn (i32, *timespec) callconv(.C) usize |
| 890 | else | 890 | else |
| 891 | *const fn (i32, *timespec) callconv(.C) usize; | 891 | *align(1) const fn (i32, *timespec) callconv(.C) usize; |
| 892 | 892 | ||
| 893 | pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { | 893 | pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { |
| 894 | if (@hasDecl(VDSO, "CGT_SYM")) { | 894 | if (@hasDecl(VDSO, "CGT_SYM")) { |
lib/std/zig/c_translation.zig+1-1| ... | @@ -193,7 +193,7 @@ pub fn sizeof(target: anytype) usize { | ... | @@ -193,7 +193,7 @@ pub fn sizeof(target: anytype) usize { |
| 193 | const array_info = @typeInfo(ptr.child).Array; | 193 | const array_info = @typeInfo(ptr.child).Array; |
| 194 | if ((array_info.child == u8 or array_info.child == u16) and | 194 | if ((array_info.child == u8 or array_info.child == u16) and |
| 195 | array_info.sentinel != null and | 195 | array_info.sentinel != null and |
| 196 | @ptrCast(*const array_info.child, array_info.sentinel.?).* == 0) | 196 | @ptrCast(*align(1) const array_info.child, array_info.sentinel.?).* == 0) |
| 197 | { | 197 | { |
| 198 | // length of the string plus one for the null terminator. | 198 | // length of the string plus one for the null terminator. |
| 199 | return (array_info.len + 1) * @sizeOf(array_info.child); | 199 | return (array_info.len + 1) * @sizeOf(array_info.child); |
src/Sema.zig+132-45| ... | @@ -16492,6 +16492,9 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -16492,6 +16492,9 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 16492 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 16492 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 16493 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 16493 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 16494 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); | 16494 | const ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 16495 | if (ty.isNoReturn()) { | ||
| 16496 | return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)}); | ||
| 16497 | } | ||
| 16495 | const target = sema.mod.getTarget(); | 16498 | const target = sema.mod.getTarget(); |
| 16496 | const val = try ty.lazyAbiAlignment(target, sema.arena); | 16499 | const val = try ty.lazyAbiAlignment(target, sema.arena); |
| 16497 | if (val.tag() == .lazy_align) { | 16500 | if (val.tag() == .lazy_align) { |
| ... | @@ -17772,6 +17775,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -17772,6 +17775,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17772 | 17775 | ||
| 17773 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 17776 | fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 17774 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 17777 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 17778 | const src = inst_data.src(); | ||
| 17775 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 17779 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 17776 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 17780 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 17777 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 17781 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| ... | @@ -17783,6 +17787,15 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17783,6 +17787,15 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17783 | try sema.checkPtrType(block, dest_ty_src, dest_ty); | 17787 | try sema.checkPtrType(block, dest_ty_src, dest_ty); |
| 17784 | try sema.checkPtrOperand(block, operand_src, operand_ty); | 17788 | try sema.checkPtrOperand(block, operand_src, operand_ty); |
| 17785 | 17789 | ||
| 17790 | const operand_info = operand_ty.ptrInfo().data; | ||
| 17791 | const dest_info = dest_ty.ptrInfo().data; | ||
| 17792 | if (!operand_info.mutable and dest_info.mutable) { | ||
| 17793 | return sema.fail(block, src, "cast discards const qualifier", .{}); | ||
| 17794 | } | ||
| 17795 | if (operand_info.@"volatile" and !dest_info.@"volatile") { | ||
| 17796 | return sema.fail(block, src, "cast discards volatile qualifier", .{}); | ||
| 17797 | } | ||
| 17798 | |||
| 17786 | const dest_is_slice = dest_ty.isSlice(); | 17799 | const dest_is_slice = dest_ty.isSlice(); |
| 17787 | const operand_is_slice = operand_ty.isSlice(); | 17800 | const operand_is_slice = operand_ty.isSlice(); |
| 17788 | if (dest_is_slice and !operand_is_slice) { | 17801 | if (dest_is_slice and !operand_is_slice) { |
| ... | @@ -17793,15 +17806,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17793,15 +17806,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17793 | else | 17806 | else |
| 17794 | operand; | 17807 | operand; |
| 17795 | 17808 | ||
| 17796 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { | ||
| 17797 | if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) { | ||
| 17798 | return sema.failWithUseOfUndef(block, operand_src); | ||
| 17799 | } | ||
| 17800 | if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { | ||
| 17801 | return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)}); | ||
| 17802 | } | ||
| 17803 | } | ||
| 17804 | |||
| 17805 | const dest_elem_ty = dest_ty.elemType2(); | 17809 | const dest_elem_ty = dest_ty.elemType2(); |
| 17806 | try sema.resolveTypeLayout(block, dest_ty_src, dest_elem_ty); | 17810 | try sema.resolveTypeLayout(block, dest_ty_src, dest_elem_ty); |
| 17807 | const dest_align = dest_ty.ptrAlignment(target); | 17811 | const dest_align = dest_ty.ptrAlignment(target); |
| ... | @@ -17835,7 +17839,47 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -17835,7 +17839,47 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 17835 | } | 17839 | } |
| 17836 | } | 17840 | } |
| 17837 | 17841 | ||
| 17838 | return sema.coerceCompatiblePtrs(block, aligned_dest_ty, ptr, operand_src); | 17842 | if (dest_align > operand_align) { |
| 17843 | const msg = msg: { | ||
| 17844 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); | ||
| 17845 | errdefer msg.destroy(sema.gpa); | ||
| 17846 | |||
| 17847 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ | ||
| 17848 | operand_ty.fmt(sema.mod), operand_align, | ||
| 17849 | }); | ||
| 17850 | try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{ | ||
| 17851 | dest_ty.fmt(sema.mod), dest_align, | ||
| 17852 | }); | ||
| 17853 | break :msg msg; | ||
| 17854 | }; | ||
| 17855 | return sema.failWithOwnedErrorMsg(msg); | ||
| 17856 | } | ||
| 17857 | |||
| 17858 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { | ||
| 17859 | if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) { | ||
| 17860 | return sema.failWithUseOfUndef(block, operand_src); | ||
| 17861 | } | ||
| 17862 | if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { | ||
| 17863 | return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)}); | ||
| 17864 | } | ||
| 17865 | return sema.addConstant(aligned_dest_ty, operand_val); | ||
| 17866 | } | ||
| 17867 | |||
| 17868 | try sema.requireRuntimeBlock(block, src, null); | ||
| 17869 | if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and | ||
| 17870 | try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2())) | ||
| 17871 | { | ||
| 17872 | const ptr_int = try block.addUnOp(.ptrtoint, ptr); | ||
| 17873 | const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); | ||
| 17874 | const ok = if (operand_is_slice) ok: { | ||
| 17875 | const len = try sema.analyzeSliceLen(block, operand_src, operand); | ||
| 17876 | const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); | ||
| 17877 | break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero); | ||
| 17878 | } else is_non_zero; | ||
| 17879 | try sema.addSafetyCheck(block, ok, .cast_to_null); | ||
| 17880 | } | ||
| 17881 | |||
| 17882 | return block.addBitCast(aligned_dest_ty, ptr); | ||
| 17839 | } | 17883 | } |
| 17840 | 17884 | ||
| 17841 | fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 17885 | fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -17931,23 +17975,14 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -17931,23 +17975,14 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 17931 | const ptr = try sema.resolveInst(extra.rhs); | 17975 | const ptr = try sema.resolveInst(extra.rhs); |
| 17932 | const ptr_ty = sema.typeOf(ptr); | 17976 | const ptr_ty = sema.typeOf(ptr); |
| 17933 | 17977 | ||
| 17934 | // TODO in addition to pointers, this instruction is supposed to work for | ||
| 17935 | // pointer-like optionals and slices. | ||
| 17936 | try sema.checkPtrOperand(block, ptr_src, ptr_ty); | 17978 | try sema.checkPtrOperand(block, ptr_src, ptr_ty); |
| 17937 | 17979 | ||
| 17938 | // TODO compile error if the result pointer is comptime known and would have an | 17980 | var ptr_info = ptr_ty.ptrInfo().data; |
| 17939 | // alignment that disagrees with the Decl's alignment. | 17981 | ptr_info.@"align" = dest_align; |
| 17940 | 17982 | var dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); | |
| 17941 | const ptr_info = ptr_ty.ptrInfo().data; | 17983 | if (ptr_ty.zigTypeTag() == .Optional) { |
| 17942 | const dest_ty = try Type.ptr(sema.arena, sema.mod, .{ | 17984 | dest_ty = try Type.Tag.optional.create(sema.arena, dest_ty); |
| 17943 | .pointee_type = ptr_info.pointee_type, | 17985 | } |
| 17944 | .@"align" = dest_align, | ||
| 17945 | .@"addrspace" = ptr_info.@"addrspace", | ||
| 17946 | .mutable = ptr_info.mutable, | ||
| 17947 | .@"allowzero" = ptr_info.@"allowzero", | ||
| 17948 | .@"volatile" = ptr_info.@"volatile", | ||
| 17949 | .size = ptr_info.size, | ||
| 17950 | }); | ||
| 17951 | 17986 | ||
| 17952 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| { | 17987 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| { |
| 17953 | if (try val.getUnsignedIntAdvanced(sema.mod.getTarget(), null)) |addr| { | 17988 | if (try val.getUnsignedIntAdvanced(sema.mod.getTarget(), null)) |addr| { |
| ... | @@ -17960,7 +17995,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -17960,7 +17995,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 17960 | 17995 | ||
| 17961 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); | 17996 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); |
| 17962 | if (block.wantSafety() and dest_align > 1 and | 17997 | if (block.wantSafety() and dest_align > 1 and |
| 17963 | try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2())) | 17998 | try sema.typeHasRuntimeBits(block, sema.src, ptr_info.pointee_type)) |
| 17964 | { | 17999 | { |
| 17965 | const val_payload = try sema.arena.create(Value.Payload.U64); | 18000 | const val_payload = try sema.arena.create(Value.Payload.U64); |
| 17966 | val_payload.* = .{ | 18001 | val_payload.* = .{ |
| ... | @@ -17985,7 +18020,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -17985,7 +18020,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 17985 | } else is_aligned; | 18020 | } else is_aligned; |
| 17986 | try sema.addSafetyCheck(block, ok, .incorrect_alignment); | 18021 | try sema.addSafetyCheck(block, ok, .incorrect_alignment); |
| 17987 | } | 18022 | } |
| 17988 | return sema.coerceCompatiblePtrs(block, dest_ty, ptr, ptr_src); | 18023 | return sema.bitCast(block, dest_ty, ptr, ptr_src); |
| 17989 | } | 18024 | } |
| 17990 | 18025 | ||
| 17991 | fn zirBitCount( | 18026 | fn zirBitCount( |
| ... | @@ -22660,7 +22695,7 @@ fn elemPtrSlice( | ... | @@ -22660,7 +22695,7 @@ fn elemPtrSlice( |
| 22660 | break :o index; | 22695 | break :o index; |
| 22661 | } else null; | 22696 | } else null; |
| 22662 | 22697 | ||
| 22663 | const elem_ptr_ty = try sema.elemPtrType(slice_ty, null); | 22698 | const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset); |
| 22664 | 22699 | ||
| 22665 | if (maybe_undef_slice_val) |slice_val| { | 22700 | if (maybe_undef_slice_val) |slice_val| { |
| 22666 | if (slice_val.isUndef()) { | 22701 | if (slice_val.isUndef()) { |
| ... | @@ -22779,6 +22814,7 @@ fn coerceExtra( | ... | @@ -22779,6 +22814,7 @@ fn coerceExtra( |
| 22779 | if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and | 22814 | if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and |
| 22780 | inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer) | 22815 | inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer) |
| 22781 | { | 22816 | { |
| 22817 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional; | ||
| 22782 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | 22818 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 22783 | } | 22819 | } |
| 22784 | 22820 | ||
| ... | @@ -22811,14 +22847,12 @@ fn coerceExtra( | ... | @@ -22811,14 +22847,12 @@ fn coerceExtra( |
| 22811 | single_item: { | 22847 | single_item: { |
| 22812 | if (dest_info.size != .One) break :single_item; | 22848 | if (dest_info.size != .One) break :single_item; |
| 22813 | if (!inst_ty.isSinglePointer()) break :single_item; | 22849 | if (!inst_ty.isSinglePointer()) break :single_item; |
| 22850 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; | ||
| 22814 | const ptr_elem_ty = inst_ty.childType(); | 22851 | const ptr_elem_ty = inst_ty.childType(); |
| 22815 | const array_ty = dest_info.pointee_type; | 22852 | const array_ty = dest_info.pointee_type; |
| 22816 | if (array_ty.zigTypeTag() != .Array) break :single_item; | 22853 | if (array_ty.zigTypeTag() != .Array) break :single_item; |
| 22817 | const array_elem_ty = array_ty.childType(); | 22854 | const array_elem_ty = array_ty.childType(); |
| 22818 | const dest_is_mut = dest_info.mutable; | 22855 | const dest_is_mut = dest_info.mutable; |
| 22819 | if (inst_ty.isConstPtr() and dest_is_mut) break :single_item; | ||
| 22820 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :single_item; | ||
| 22821 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :single_item; | ||
| 22822 | switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { | 22856 | switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) { |
| 22823 | .ok => {}, | 22857 | .ok => {}, |
| 22824 | else => break :single_item, | 22858 | else => break :single_item, |
| ... | @@ -22829,14 +22863,11 @@ fn coerceExtra( | ... | @@ -22829,14 +22863,11 @@ fn coerceExtra( |
| 22829 | // Coercions where the source is a single pointer to an array. | 22863 | // Coercions where the source is a single pointer to an array. |
| 22830 | src_array_ptr: { | 22864 | src_array_ptr: { |
| 22831 | if (!inst_ty.isSinglePointer()) break :src_array_ptr; | 22865 | if (!inst_ty.isSinglePointer()) break :src_array_ptr; |
| 22866 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; | ||
| 22832 | const array_ty = inst_ty.childType(); | 22867 | const array_ty = inst_ty.childType(); |
| 22833 | if (array_ty.zigTypeTag() != .Array) break :src_array_ptr; | 22868 | if (array_ty.zigTypeTag() != .Array) break :src_array_ptr; |
| 22834 | const len0 = array_ty.arrayLen() == 0; | ||
| 22835 | const array_elem_type = array_ty.childType(); | 22869 | const array_elem_type = array_ty.childType(); |
| 22836 | const dest_is_mut = dest_info.mutable; | 22870 | const dest_is_mut = dest_info.mutable; |
| 22837 | if (inst_ty.isConstPtr() and dest_is_mut and !len0) break :src_array_ptr; | ||
| 22838 | if (inst_ty.isVolatilePtr() and !dest_info.@"volatile") break :src_array_ptr; | ||
| 22839 | if (inst_ty.ptrAddressSpace() != dest_info.@"addrspace") break :src_array_ptr; | ||
| 22840 | 22871 | ||
| 22841 | const dst_elem_type = dest_info.pointee_type; | 22872 | const dst_elem_type = dest_info.pointee_type; |
| 22842 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) { | 22873 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src)) { |
| ... | @@ -22873,6 +22904,7 @@ fn coerceExtra( | ... | @@ -22873,6 +22904,7 @@ fn coerceExtra( |
| 22873 | 22904 | ||
| 22874 | // coercion from C pointer | 22905 | // coercion from C pointer |
| 22875 | if (inst_ty.isCPtr()) src_c_ptr: { | 22906 | if (inst_ty.isCPtr()) src_c_ptr: { |
| 22907 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :src_c_ptr; | ||
| 22876 | // In this case we must add a safety check because the C pointer | 22908 | // In this case we must add a safety check because the C pointer |
| 22877 | // could be null. | 22909 | // could be null. |
| 22878 | const src_elem_ty = inst_ty.childType(); | 22910 | const src_elem_ty = inst_ty.childType(); |
| ... | @@ -22888,7 +22920,7 @@ fn coerceExtra( | ... | @@ -22888,7 +22920,7 @@ fn coerceExtra( |
| 22888 | // cast from *T and [*]T to *anyopaque | 22920 | // cast from *T and [*]T to *anyopaque |
| 22889 | // but don't do it if the source type is a double pointer | 22921 | // but don't do it if the source type is a double pointer |
| 22890 | if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and | 22922 | if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and |
| 22891 | inst_ty.childType().zigTypeTag() != .Pointer) | 22923 | inst_ty.childType().zigTypeTag() != .Pointer and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) |
| 22892 | { | 22924 | { |
| 22893 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); | 22925 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 22894 | } | 22926 | } |
| ... | @@ -22922,6 +22954,7 @@ fn coerceExtra( | ... | @@ -22922,6 +22954,7 @@ fn coerceExtra( |
| 22922 | return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src); | 22954 | return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src); |
| 22923 | }, | 22955 | }, |
| 22924 | .Pointer => p: { | 22956 | .Pointer => p: { |
| 22957 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p; | ||
| 22925 | const inst_info = inst_ty.ptrInfo().data; | 22958 | const inst_info = inst_ty.ptrInfo().data; |
| 22926 | switch (try sema.coerceInMemoryAllowed( | 22959 | switch (try sema.coerceInMemoryAllowed( |
| 22927 | block, | 22960 | block, |
| ... | @@ -22952,7 +22985,7 @@ fn coerceExtra( | ... | @@ -22952,7 +22985,7 @@ fn coerceExtra( |
| 22952 | // pointer to anonymous struct to pointer to union | 22985 | // pointer to anonymous struct to pointer to union |
| 22953 | if (inst_ty.isSinglePointer() and | 22986 | if (inst_ty.isSinglePointer() and |
| 22954 | inst_ty.childType().isAnonStruct() and | 22987 | inst_ty.childType().isAnonStruct() and |
| 22955 | !dest_info.mutable) | 22988 | sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) |
| 22956 | { | 22989 | { |
| 22957 | return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src); | 22990 | return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 22958 | } | 22991 | } |
| ... | @@ -22961,7 +22994,7 @@ fn coerceExtra( | ... | @@ -22961,7 +22994,7 @@ fn coerceExtra( |
| 22961 | // pointer to anonymous struct to pointer to struct | 22994 | // pointer to anonymous struct to pointer to struct |
| 22962 | if (inst_ty.isSinglePointer() and | 22995 | if (inst_ty.isSinglePointer() and |
| 22963 | inst_ty.childType().isAnonStruct() and | 22996 | inst_ty.childType().isAnonStruct() and |
| 22964 | !dest_info.mutable) | 22997 | sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) |
| 22965 | { | 22998 | { |
| 22966 | return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src); | 22999 | return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 22967 | } | 23000 | } |
| ... | @@ -22970,7 +23003,7 @@ fn coerceExtra( | ... | @@ -22970,7 +23003,7 @@ fn coerceExtra( |
| 22970 | // pointer to tuple to pointer to array | 23003 | // pointer to tuple to pointer to array |
| 22971 | if (inst_ty.isSinglePointer() and | 23004 | if (inst_ty.isSinglePointer() and |
| 22972 | inst_ty.childType().isTuple() and | 23005 | inst_ty.childType().isTuple() and |
| 22973 | !dest_info.mutable) | 23006 | sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) |
| 22974 | { | 23007 | { |
| 22975 | return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src); | 23008 | return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 22976 | } | 23009 | } |
| ... | @@ -22979,10 +23012,8 @@ fn coerceExtra( | ... | @@ -22979,10 +23012,8 @@ fn coerceExtra( |
| 22979 | }, | 23012 | }, |
| 22980 | .Slice => { | 23013 | .Slice => { |
| 22981 | // pointer to tuple to slice | 23014 | // pointer to tuple to slice |
| 22982 | if (inst_ty.isSinglePointer() and | 23015 | if (inst_ty.isSinglePointer() and inst_ty.childType().isTuple() and dest_info.size == .Slice and |
| 22983 | inst_ty.childType().isTuple() and | 23016 | sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) |
| 22984 | (!dest_info.mutable or inst_ty.ptrIsMutable() or inst_ty.childType().tupleFields().types.len == 0) and | ||
| 22985 | dest_info.size == .Slice) | ||
| 22986 | { | 23017 | { |
| 22987 | return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src); | 23018 | return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 22988 | } | 23019 | } |
| ... | @@ -23011,6 +23042,7 @@ fn coerceExtra( | ... | @@ -23011,6 +23042,7 @@ fn coerceExtra( |
| 23011 | }, | 23042 | }, |
| 23012 | .Many => p: { | 23043 | .Many => p: { |
| 23013 | if (!inst_ty.isSlice()) break :p; | 23044 | if (!inst_ty.isSlice()) break :p; |
| 23045 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p; | ||
| 23014 | const inst_info = inst_ty.ptrInfo().data; | 23046 | const inst_info = inst_ty.ptrInfo().data; |
| 23015 | 23047 | ||
| 23016 | switch (try sema.coerceInMemoryAllowed( | 23048 | switch (try sema.coerceInMemoryAllowed( |
| ... | @@ -25158,6 +25190,11 @@ fn beginComptimePtrLoad( | ... | @@ -25158,6 +25190,11 @@ fn beginComptimePtrLoad( |
| 25158 | break :blk deref; | 25190 | break :blk deref; |
| 25159 | }, | 25191 | }, |
| 25160 | 25192 | ||
| 25193 | .slice => blk: { | ||
| 25194 | const slice = ptr_val.castTag(.slice).?.data; | ||
| 25195 | break :blk try beginComptimePtrLoad(sema, block, src, slice.ptr, null); | ||
| 25196 | }, | ||
| 25197 | |||
| 25161 | .field_ptr => blk: { | 25198 | .field_ptr => blk: { |
| 25162 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 25199 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 25163 | const field_index = @intCast(u32, field_ptr.field_index); | 25200 | const field_index = @intCast(u32, field_ptr.field_index); |
| ... | @@ -25406,6 +25443,57 @@ fn coerceArrayPtrToSlice( | ... | @@ -25406,6 +25443,57 @@ fn coerceArrayPtrToSlice( |
| 25406 | return block.addTyOp(.array_to_slice, dest_ty, inst); | 25443 | return block.addTyOp(.array_to_slice, dest_ty, inst); |
| 25407 | } | 25444 | } |
| 25408 | 25445 | ||
| 25446 | fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_result: *InMemoryCoercionResult) bool { | ||
| 25447 | const dest_info = dest_ty.ptrInfo().data; | ||
| 25448 | const inst_info = inst_ty.ptrInfo().data; | ||
| 25449 | const len0 = (inst_info.pointee_type.zigTypeTag() == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel() == 0 or | ||
| 25450 | (inst_info.pointee_type.arrayLen() == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or | ||
| 25451 | (inst_info.pointee_type.isTuple() and inst_info.pointee_type.tupleFields().types.len == 0); | ||
| 25452 | |||
| 25453 | const ok_cv_qualifiers = | ||
| 25454 | ((inst_info.mutable or !dest_info.mutable) or len0) and | ||
| 25455 | (!inst_info.@"volatile" or dest_info.@"volatile"); | ||
| 25456 | |||
| 25457 | if (!ok_cv_qualifiers) { | ||
| 25458 | in_memory_result.* = .{ .ptr_qualifiers = .{ | ||
| 25459 | .actual_const = !inst_info.mutable, | ||
| 25460 | .wanted_const = !dest_info.mutable, | ||
| 25461 | .actual_volatile = inst_info.@"volatile", | ||
| 25462 | .wanted_volatile = dest_info.@"volatile", | ||
| 25463 | } }; | ||
| 25464 | return false; | ||
| 25465 | } | ||
| 25466 | if (dest_info.@"addrspace" != inst_info.@"addrspace") { | ||
| 25467 | in_memory_result.* = .{ .ptr_addrspace = .{ | ||
| 25468 | .actual = inst_info.@"addrspace", | ||
| 25469 | .wanted = dest_info.@"addrspace", | ||
| 25470 | } }; | ||
| 25471 | return false; | ||
| 25472 | } | ||
| 25473 | if (inst_info.@"align" == 0 and dest_info.@"align" == 0) return true; | ||
| 25474 | if (len0) return true; | ||
| 25475 | const target = sema.mod.getTarget(); | ||
| 25476 | |||
| 25477 | const inst_align = if (inst_info.@"align" != 0) | ||
| 25478 | inst_info.@"align" | ||
| 25479 | else | ||
| 25480 | inst_info.pointee_type.abiAlignment(target); | ||
| 25481 | |||
| 25482 | const dest_align = if (dest_info.@"align" != 0) | ||
| 25483 | dest_info.@"align" | ||
| 25484 | else | ||
| 25485 | dest_info.pointee_type.abiAlignment(target); | ||
| 25486 | |||
| 25487 | if (dest_align > inst_align) { | ||
| 25488 | in_memory_result.* = .{ .ptr_alignment = .{ | ||
| 25489 | .actual = inst_align, | ||
| 25490 | .wanted = dest_align, | ||
| 25491 | } }; | ||
| 25492 | return false; | ||
| 25493 | } | ||
| 25494 | return true; | ||
| 25495 | } | ||
| 25496 | |||
| 25409 | fn coerceCompatiblePtrs( | 25497 | fn coerceCompatiblePtrs( |
| 25410 | sema: *Sema, | 25498 | sema: *Sema, |
| 25411 | block: *Block, | 25499 | block: *Block, |
| ... | @@ -25413,13 +25501,12 @@ fn coerceCompatiblePtrs( | ... | @@ -25413,13 +25501,12 @@ fn coerceCompatiblePtrs( |
| 25413 | inst: Air.Inst.Ref, | 25501 | inst: Air.Inst.Ref, |
| 25414 | inst_src: LazySrcLoc, | 25502 | inst_src: LazySrcLoc, |
| 25415 | ) !Air.Inst.Ref { | 25503 | ) !Air.Inst.Ref { |
| 25416 | // TODO check const/volatile/alignment | 25504 | const inst_ty = sema.typeOf(inst); |
| 25417 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 25505 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 25418 | // The comptime Value representation is compatible with both types. | 25506 | // The comptime Value representation is compatible with both types. |
| 25419 | return sema.addConstant(dest_ty, val); | 25507 | return sema.addConstant(dest_ty, val); |
| 25420 | } | 25508 | } |
| 25421 | try sema.requireRuntimeBlock(block, inst_src, null); | 25509 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 25422 | const inst_ty = sema.typeOf(inst); | ||
| 25423 | const inst_allows_zero = (inst_ty.zigTypeTag() == .Pointer and inst_ty.ptrAllowsZero()) or true; | 25510 | const inst_allows_zero = (inst_ty.zigTypeTag() == .Pointer and inst_ty.ptrAllowsZero()) or true; |
| 25424 | if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and | 25511 | if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and |
| 25425 | try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2())) | 25512 | try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2())) |
test/behavior/align.zig+13| ... | @@ -556,3 +556,16 @@ test "comptime alloc alignment" { | ... | @@ -556,3 +556,16 @@ test "comptime alloc alignment" { |
| 556 | var bytes2_addr = @ptrToInt(&bytes2); | 556 | var bytes2_addr = @ptrToInt(&bytes2); |
| 557 | try expect(bytes2_addr & 0xff == 0); | 557 | try expect(bytes2_addr & 0xff == 0); |
| 558 | } | 558 | } |
| 559 | |||
| 560 | test "@alignCast null" { | ||
| 561 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 562 | |||
| 563 | var ptr: ?*anyopaque = null; | ||
| 564 | const aligned: ?*anyopaque = @alignCast(@alignOf(?*anyopaque), ptr); | ||
| 565 | try expect(aligned == null); | ||
| 566 | } | ||
| 567 | |||
| 568 | test "alignment of slice element" { | ||
| 569 | const a: []align(1024) const u8 = undefined; | ||
| 570 | try expect(@TypeOf(&a[0]) == *align(1024) const u8); | ||
| 571 | } |
test/behavior/bugs/4328.zig+1-1| ... | @@ -13,7 +13,7 @@ extern fn fopen([*c]const u8, [*c]const u8) [*c]FILE; | ... | @@ -13,7 +13,7 @@ extern fn fopen([*c]const u8, [*c]const u8) [*c]FILE; |
| 13 | const S = extern struct { | 13 | const S = extern struct { |
| 14 | state: c_short, | 14 | state: c_short, |
| 15 | 15 | ||
| 16 | extern fn s_do_thing([*c]S, b: c_int) c_short; | 16 | extern fn s_do_thing([*c]const S, b: c_int) c_short; |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | test "Extern function calls in @TypeOf" { | 19 | test "Extern function calls in @TypeOf" { |
test/behavior/cast.zig+2-2| ... | @@ -1242,13 +1242,13 @@ test "implicit cast *[0]T to E![]const u8" { | ... | @@ -1242,13 +1242,13 @@ test "implicit cast *[0]T to E![]const u8" { |
| 1242 | 1242 | ||
| 1243 | var global_array: [4]u8 = undefined; | 1243 | var global_array: [4]u8 = undefined; |
| 1244 | test "cast from array reference to fn: comptime fn ptr" { | 1244 | test "cast from array reference to fn: comptime fn ptr" { |
| 1245 | const f = @ptrCast(*const fn () callconv(.C) void, &global_array); | 1245 | const f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); |
| 1246 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | 1246 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); |
| 1247 | } | 1247 | } |
| 1248 | test "cast from array reference to fn: runtime fn ptr" { | 1248 | test "cast from array reference to fn: runtime fn ptr" { |
| 1249 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1249 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1250 | 1250 | ||
| 1251 | var f = @ptrCast(*const fn () callconv(.C) void, &global_array); | 1251 | var f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array); |
| 1252 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | 1252 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); |
| 1253 | } | 1253 | } |
| 1254 | 1254 |
test/behavior/slice.zig+2-1| ... | @@ -322,11 +322,12 @@ test "empty array to slice" { | ... | @@ -322,11 +322,12 @@ test "empty array to slice" { |
| 322 | 322 | ||
| 323 | test "@ptrCast slice to pointer" { | 323 | test "@ptrCast slice to pointer" { |
| 324 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 324 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 325 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 325 | 326 | ||
| 326 | const S = struct { | 327 | const S = struct { |
| 327 | fn doTheTest() !void { | 328 | fn doTheTest() !void { |
| 328 | var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff }; | 329 | var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff }; |
| 329 | var slice: []u8 = &array; | 330 | var slice: []align(@alignOf(u16)) u8 = &array; |
| 330 | var ptr = @ptrCast(*u16, slice); | 331 | var ptr = @ptrCast(*u16, slice); |
| 331 | try expect(ptr.* == 65535); | 332 | try expect(ptr.* == 65535); |
| 332 | } | 333 | } |
test/behavior/struct.zig+1-1| ... | @@ -521,7 +521,7 @@ test "packed struct fields are ordered from LSB to MSB" { | ... | @@ -521,7 +521,7 @@ test "packed struct fields are ordered from LSB to MSB" { |
| 521 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 521 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 522 | 522 | ||
| 523 | var all: u64 = 0x7765443322221111; | 523 | var all: u64 = 0x7765443322221111; |
| 524 | var bytes: [8]u8 = undefined; | 524 | var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined; |
| 525 | @memcpy(&bytes, @ptrCast([*]u8, &all), 8); | 525 | @memcpy(&bytes, @ptrCast([*]u8, &all), 8); |
| 526 | var bitfields = @ptrCast(*Bitfields, &bytes).*; | 526 | var bitfields = @ptrCast(*Bitfields, &bytes).*; |
| 527 | 527 |
test/behavior/type.zig+2-2| ... | @@ -293,7 +293,7 @@ test "Type.Struct" { | ... | @@ -293,7 +293,7 @@ test "Type.Struct" { |
| 293 | try testing.expectEqual(@as(?*const anyopaque, null), infoB.fields[0].default_value); | 293 | try testing.expectEqual(@as(?*const anyopaque, null), infoB.fields[0].default_value); |
| 294 | try testing.expectEqualSlices(u8, "y", infoB.fields[1].name); | 294 | try testing.expectEqualSlices(u8, "y", infoB.fields[1].name); |
| 295 | try testing.expectEqual(u32, infoB.fields[1].field_type); | 295 | try testing.expectEqual(u32, infoB.fields[1].field_type); |
| 296 | try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoB.fields[1].default_value.?).*); | 296 | try testing.expectEqual(@as(u32, 5), @ptrCast(*align(1) const u32, infoB.fields[1].default_value.?).*); |
| 297 | try testing.expectEqual(@as(usize, 0), infoB.decls.len); | 297 | try testing.expectEqual(@as(usize, 0), infoB.decls.len); |
| 298 | try testing.expectEqual(@as(bool, false), infoB.is_tuple); | 298 | try testing.expectEqual(@as(bool, false), infoB.is_tuple); |
| 299 | 299 | ||
| ... | @@ -305,7 +305,7 @@ test "Type.Struct" { | ... | @@ -305,7 +305,7 @@ test "Type.Struct" { |
| 305 | try testing.expectEqual(@as(u8, 3), @ptrCast(*const u8, infoC.fields[0].default_value.?).*); | 305 | try testing.expectEqual(@as(u8, 3), @ptrCast(*const u8, infoC.fields[0].default_value.?).*); |
| 306 | try testing.expectEqualSlices(u8, "y", infoC.fields[1].name); | 306 | try testing.expectEqualSlices(u8, "y", infoC.fields[1].name); |
| 307 | try testing.expectEqual(u32, infoC.fields[1].field_type); | 307 | try testing.expectEqual(u32, infoC.fields[1].field_type); |
| 308 | try testing.expectEqual(@as(u32, 5), @ptrCast(*const u32, infoC.fields[1].default_value.?).*); | 308 | try testing.expectEqual(@as(u32, 5), @ptrCast(*align(1) const u32, infoC.fields[1].default_value.?).*); |
| 309 | try testing.expectEqual(@as(usize, 0), infoC.decls.len); | 309 | try testing.expectEqual(@as(usize, 0), infoC.decls.len); |
| 310 | try testing.expectEqual(@as(bool, false), infoC.is_tuple); | 310 | try testing.expectEqual(@as(bool, false), infoC.is_tuple); |
| 311 | 311 |
test/behavior/type_info.zig+3-3| ... | @@ -295,8 +295,8 @@ fn testStruct() !void { | ... | @@ -295,8 +295,8 @@ fn testStruct() !void { |
| 295 | try expect(unpacked_struct_info.Struct.is_tuple == false); | 295 | try expect(unpacked_struct_info.Struct.is_tuple == false); |
| 296 | try expect(unpacked_struct_info.Struct.backing_integer == null); | 296 | try expect(unpacked_struct_info.Struct.backing_integer == null); |
| 297 | try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32)); | 297 | try expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32)); |
| 298 | try expect(@ptrCast(*const u32, unpacked_struct_info.Struct.fields[0].default_value.?).* == 4); | 298 | try expect(@ptrCast(*align(1) const u32, unpacked_struct_info.Struct.fields[0].default_value.?).* == 4); |
| 299 | try expect(mem.eql(u8, "foobar", @ptrCast(*const *const [6:0]u8, unpacked_struct_info.Struct.fields[1].default_value.?).*)); | 299 | try expect(mem.eql(u8, "foobar", @ptrCast(*align(1) const *const [6:0]u8, unpacked_struct_info.Struct.fields[1].default_value.?).*)); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | const TestStruct = struct { | 302 | const TestStruct = struct { |
| ... | @@ -321,7 +321,7 @@ fn testPackedStruct() !void { | ... | @@ -321,7 +321,7 @@ fn testPackedStruct() !void { |
| 321 | try expect(struct_info.Struct.fields[0].alignment == 0); | 321 | try expect(struct_info.Struct.fields[0].alignment == 0); |
| 322 | try expect(struct_info.Struct.fields[2].field_type == f32); | 322 | try expect(struct_info.Struct.fields[2].field_type == f32); |
| 323 | try expect(struct_info.Struct.fields[2].default_value == null); | 323 | try expect(struct_info.Struct.fields[2].default_value == null); |
| 324 | try expect(@ptrCast(*const u32, struct_info.Struct.fields[3].default_value.?).* == 4); | 324 | try expect(@ptrCast(*align(1) const u32, struct_info.Struct.fields[3].default_value.?).* == 4); |
| 325 | try expect(struct_info.Struct.fields[3].alignment == 0); | 325 | try expect(struct_info.Struct.fields[3].alignment == 0); |
| 326 | try expect(struct_info.Struct.decls.len == 2); | 326 | try expect(struct_info.Struct.decls.len == 2); |
| 327 | try expect(struct_info.Struct.decls[0].is_pub); | 327 | try expect(struct_info.Struct.decls[0].is_pub); |
test/cases/compile_errors/alignOf_bad_type.zig created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | export fn entry() usize { | ||
| 2 | return @alignOf(noreturn); | ||
| 3 | } | ||
| 4 | |||
| 5 | // error | ||
| 6 | // backend=stage2 | ||
| 7 | // target=native | ||
| 8 | // | ||
| 9 | // :2:21: error: no align available for type 'noreturn' | ||
test/cases/compile_errors/attempted_implicit_cast_from_const_T_to_sliceT.zig+1| ... | @@ -9,3 +9,4 @@ export fn entry() void { | ... | @@ -9,3 +9,4 @@ export fn entry() void { |
| 9 | // target=native | 9 | // target=native |
| 10 | // | 10 | // |
| 11 | // :3:22: error: expected type '[]u32', found '*const u32' | 11 | // :3:22: error: expected type '[]u32', found '*const u32' |
| 12 | // :3:22: note: cast discards const qualifier |
test/cases/compile_errors/implicit_cast_between_C_pointer_and_Zig_pointer-bad_const-align-child.zig created+47| ... | @@ -0,0 +1,47 @@ | ||
| 1 | export fn a() void { | ||
| 2 | var x: [*c]u8 = undefined; | ||
| 3 | var y: *align(4) u8 = x; | ||
| 4 | _ = y; | ||
| 5 | } | ||
| 6 | export fn b() void { | ||
| 7 | var x: [*c]const u8 = undefined; | ||
| 8 | var y: *u8 = x; | ||
| 9 | _ = y; | ||
| 10 | } | ||
| 11 | export fn c() void { | ||
| 12 | var x: [*c]u8 = undefined; | ||
| 13 | var y: *u32 = x; | ||
| 14 | _ = y; | ||
| 15 | } | ||
| 16 | export fn d() void { | ||
| 17 | var y: *align(1) u32 = undefined; | ||
| 18 | var x: [*c]u32 = y; | ||
| 19 | _ = x; | ||
| 20 | } | ||
| 21 | export fn e() void { | ||
| 22 | var y: *const u8 = undefined; | ||
| 23 | var x: [*c]u8 = y; | ||
| 24 | _ = x; | ||
| 25 | } | ||
| 26 | export fn f() void { | ||
| 27 | var y: *u8 = undefined; | ||
| 28 | var x: [*c]u32 = y; | ||
| 29 | _ = x; | ||
| 30 | } | ||
| 31 | |||
| 32 | // error | ||
| 33 | // backend=stage2 | ||
| 34 | // target=native | ||
| 35 | // | ||
| 36 | // :3:27: error: expected type '*align(4) u8', found '[*c]u8' | ||
| 37 | // :3:27: note: pointer alignment '1' cannot cast into pointer alignment '4' | ||
| 38 | // :8:18: error: expected type '*u8', found '[*c]const u8' | ||
| 39 | // :8:18: note: cast discards const qualifier | ||
| 40 | // :13:19: error: expected type '*u32', found '[*c]u8' | ||
| 41 | // :13:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32' | ||
| 42 | // :18:22: error: expected type '[*c]u32', found '*align(1) u32' | ||
| 43 | // :18:22: note: pointer alignment '1' cannot cast into pointer alignment '4' | ||
| 44 | // :23:21: error: expected type '[*c]u8', found '*const u8' | ||
| 45 | // :23:21: note: cast discards const qualifier | ||
| 46 | // :28:22: error: expected type '[*c]u32', found '*u8' | ||
| 47 | // :28:22: note: pointer type child 'u8' cannot cast into pointer type child 'u32' | ||
test/cases/compile_errors/implicit_cast_const_array_to_mutable_slice.zig created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | const buffer: [1]u8 = [_]u8{8}; | ||
| 3 | const sliceA: []u8 = &buffer; | ||
| 4 | _ = sliceA; | ||
| 5 | } | ||
| 6 | export fn entry1() void { | ||
| 7 | const str: *const [0:0]u8 = ""; | ||
| 8 | const slice: [:0]u8 = str; | ||
| 9 | _ = slice; | ||
| 10 | } | ||
| 11 | export fn entry2() void { | ||
| 12 | const str: *const [0:0]u8 = ""; | ||
| 13 | const many: [*]u8 = str; | ||
| 14 | _ = many; | ||
| 15 | } | ||
| 16 | |||
| 17 | // error | ||
| 18 | // backend=stage2 | ||
| 19 | // target=native | ||
| 20 | // | ||
| 21 | // :3:26: error: expected type '[]u8', found '*const [1]u8' | ||
| 22 | // :3:26: note: cast discards const qualifier | ||
| 23 | // :8:27: error: expected type '[:0]u8', found '*const [0:0]u8' | ||
| 24 | // :8:27: note: cast discards const qualifier | ||
| 25 | // :13:25: error: expected type '[*]u8', found '*const [0:0]u8' | ||
| 26 | // :13:25: note: cast discards const qualifier | ||
test/cases/compile_errors/implicitly_increasing_slice_alignment.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | const Foo = packed struct { | ||
| 2 | a: u8, | ||
| 3 | b: u32, | ||
| 4 | }; | ||
| 5 | |||
| 6 | export fn entry() void { | ||
| 7 | var foo = Foo { .a = 1, .b = 10 }; | ||
| 8 | foo.b += 1; | ||
| 9 | bar(@as(*[1]u32, &foo.b)[0..]); | ||
| 10 | } | ||
| 11 | |||
| 12 | fn bar(x: []u32) void { | ||
| 13 | x[0] += 1; | ||
| 14 | } | ||
| 15 | |||
| 16 | // error | ||
| 17 | // backend=stage2 | ||
| 18 | // target=native | ||
| 19 | // | ||
| 20 | // :9:22: error: expected type '*[1]u32', found '*align(1) u32' | ||
| 21 | // :9:22: note: pointer alignment '1' cannot cast into pointer alignment '4' | ||
test/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | export fn entry() u32 { | ||
| 2 | var bytes: [4]u8 = [_]u8{0x01, 0x02, 0x03, 0x04}; | ||
| 3 | const ptr = @ptrCast(*u32, &bytes[0]); | ||
| 4 | return ptr.*; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage2 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // :3:17: error: cast increases pointer alignment | ||
| 12 | // :3:32: note: '*u8' has alignment '1' | ||
| 13 | // :3:26: note: '*u32' has alignment '4' | ||
test/cases/compile_errors/issue_5221_invalid_struct_init_type_referenced_by_typeInfo_and_passed_into_function.zig created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | fn ignore(comptime param: anytype) void {_ = param;} | ||
| 2 | |||
| 3 | export fn foo() void { | ||
| 4 | const MyStruct = struct { | ||
| 5 | wrong_type: []u8 = "foo", | ||
| 6 | }; | ||
| 7 | |||
| 8 | comptime ignore(@typeInfo(MyStruct).Struct.fields[0]); | ||
| 9 | } | ||
| 10 | |||
| 11 | // error | ||
| 12 | // backend=stage2 | ||
| 13 | // target=native | ||
| 14 | // | ||
| 15 | // :4:22: error: expected type '[]u8', found '*const [3:0]u8' | ||
| 16 | // :4:22: note: cast discards const qualifier | ||
test/cases/compile_errors/load_too_many_bytes_from_comptime_reinterpreted_pointer.zig+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | export fn entry() void { | 1 | export fn entry() void { |
| 2 | const float: f32 = 5.99999999999994648725e-01; | 2 | const float: f32 align(@alignOf(i64)) = 5.99999999999994648725e-01; |
| 3 | const float_ptr = &float; | 3 | const float_ptr = &float; |
| 4 | const int_ptr = @ptrCast(*const i64, float_ptr); | 4 | const int_ptr = @ptrCast(*const i64, float_ptr); |
| 5 | const int_val = int_ptr.*; | 5 | const int_val = int_ptr.*; |
test/cases/compile_errors/peer_cast_then_implicit_cast_const_pointer_to_mutable_C_pointer.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | export fn func() void { | ||
| 2 | var strValue: [*c]u8 = undefined; | ||
| 3 | strValue = strValue orelse ""; | ||
| 4 | } | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=stage2 | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // :3:32: error: expected type '[*c]u8', found '*const [0:0]u8' | ||
| 11 | // :3:32: note: cast discards const qualifier | ||
test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig created+24| ... | @@ -0,0 +1,24 @@ | ||
| 1 | comptime { | ||
| 2 | const c: [][]const u8 = &.{ "hello", "world" }; | ||
| 3 | _ = c; | ||
| 4 | } | ||
| 5 | comptime { | ||
| 6 | const c: *[2][]const u8 = &.{ "hello", "world" }; | ||
| 7 | _ = c; | ||
| 8 | } | ||
| 9 | const S = struct { a: u8 = 1, b: u32 = 2 }; | ||
| 10 | comptime { | ||
| 11 | const c: *S = &.{ .a = 2 }; | ||
| 12 | _ = c; | ||
| 13 | } | ||
| 14 | |||
| 15 | // error | ||
| 16 | // backend=stage2 | ||
| 17 | // target=native | ||
| 18 | // | ||
| 19 | // :2:29: error: expected type '[][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}' | ||
| 20 | // :2:29: note: cast discards const qualifier | ||
| 21 | // :6:31: error: expected type '*[2][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}' | ||
| 22 | // :6:31: note: cast discards const qualifier | ||
| 23 | // :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}' | ||
| 24 | // :11:19: note: cast discards const qualifier | ||
test/cases/compile_errors/ptrCast_discards_const_qualifier.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | const x: i32 = 1234; | ||
| 3 | const y = @ptrCast(*i32, &x); | ||
| 4 | _ = y; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage2 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // :3:15: error: cast discards const qualifier | ||
test/cases/compile_errors/reading_past_end_of_pointer_casted_array.zig+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | comptime { | 1 | comptime { |
| 2 | const array: [4]u8 = "aoeu".*; | 2 | const array: [4]u8 = "aoeu".*; |
| 3 | const sub_array = array[1..]; | 3 | const sub_array = array[1..]; |
| 4 | const int_ptr = @ptrCast(*const u24, sub_array); | 4 | const int_ptr = @ptrCast(*const u24, @alignCast(@alignOf(u24), sub_array)); |
| 5 | const deref = int_ptr.*; | 5 | const deref = int_ptr.*; |
| 6 | _ = deref; | 6 | _ = deref; |
| 7 | } | 7 | } |
test/cases/compile_errors/slice_cannot_have_its_bytes_reinterpreted.zig+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | export fn foo() void { | 1 | export fn foo() void { |
| 2 | const bytes = [1]u8{ 0xfa } ** 16; | 2 | const bytes align(@alignOf([]const u8)) = [1]u8{0xfa} ** 16; |
| 3 | var value = @ptrCast(*const []const u8, &bytes).*; | 3 | var value = @ptrCast(*const []const u8, &bytes).*; |
| 4 | _ = value; | 4 | _ = value; |
| 5 | } | 5 | } |
test/cases/compile_errors/stage1/obj/implicit_cast_between_C_pointer_and_Zig_pointer-bad_const-align-child.zig deleted-42| ... | @@ -1,42 +0,0 @@ | ||
| 1 | export fn a() void { | ||
| 2 | var x: [*c]u8 = undefined; | ||
| 3 | var y: *align(4) u8 = x; | ||
| 4 | _ = y; | ||
| 5 | } | ||
| 6 | export fn b() void { | ||
| 7 | var x: [*c]const u8 = undefined; | ||
| 8 | var y: *u8 = x; | ||
| 9 | _ = y; | ||
| 10 | } | ||
| 11 | export fn c() void { | ||
| 12 | var x: [*c]u8 = undefined; | ||
| 13 | var y: *u32 = x; | ||
| 14 | _ = y; | ||
| 15 | } | ||
| 16 | export fn d() void { | ||
| 17 | var y: *align(1) u32 = undefined; | ||
| 18 | var x: [*c]u32 = y; | ||
| 19 | _ = x; | ||
| 20 | } | ||
| 21 | export fn e() void { | ||
| 22 | var y: *const u8 = undefined; | ||
| 23 | var x: [*c]u8 = y; | ||
| 24 | _ = x; | ||
| 25 | } | ||
| 26 | export fn f() void { | ||
| 27 | var y: *u8 = undefined; | ||
| 28 | var x: [*c]u32 = y; | ||
| 29 | _ = x; | ||
| 30 | } | ||
| 31 | |||
| 32 | // error | ||
| 33 | // backend=stage1 | ||
| 34 | // target=native | ||
| 35 | // | ||
| 36 | // tmp.zig:3:27: error: cast increases pointer alignment | ||
| 37 | // tmp.zig:8:18: error: cast discards const qualifier | ||
| 38 | // tmp.zig:13:19: error: expected type '*u32', found '[*c]u8' | ||
| 39 | // tmp.zig:13:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32' | ||
| 40 | // tmp.zig:18:22: error: cast increases pointer alignment | ||
| 41 | // tmp.zig:23:21: error: cast discards const qualifier | ||
| 42 | // tmp.zig:28:22: error: expected type '[*c]u32', found '*u8' | ||
test/cases/compile_errors/stage1/obj/implicit_cast_const_array_to_mutable_slice.zig deleted-12| ... | @@ -1,12 +0,0 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | const buffer: [1]u8 = [_]u8{8}; | ||
| 3 | const sliceA: []u8 = &buffer; | ||
| 4 | _ = sliceA; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage1 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // tmp.zig:3:27: error: cannot cast pointer to array literal to slice type '[]u8' | ||
| 12 | // tmp.zig:3:27: note: cast discards const qualifier | ||
test/cases/compile_errors/stage1/obj/implicitly_increasing_slice_alignment.zig deleted-22| ... | @@ -1,22 +0,0 @@ | ||
| 1 | const Foo = packed struct { | ||
| 2 | a: u8, | ||
| 3 | b: u32, | ||
| 4 | }; | ||
| 5 | |||
| 6 | export fn entry() void { | ||
| 7 | var foo = Foo { .a = 1, .b = 10 }; | ||
| 8 | foo.b += 1; | ||
| 9 | bar(@as(*[1]u32, &foo.b)[0..]); | ||
| 10 | } | ||
| 11 | |||
| 12 | fn bar(x: []u32) void { | ||
| 13 | x[0] += 1; | ||
| 14 | } | ||
| 15 | |||
| 16 | // error | ||
| 17 | // backend=stage1 | ||
| 18 | // target=native | ||
| 19 | // | ||
| 20 | // tmp.zig:9:26: error: cast increases pointer alignment | ||
| 21 | // tmp.zig:9:26: note: '*align(1) u32' has alignment 1 | ||
| 22 | // tmp.zig:9:26: note: '*[1]u32' has alignment 4 | ||
test/cases/compile_errors/stage1/obj/increase_pointer_alignment_in_ptrCast.zig deleted-13| ... | @@ -1,13 +0,0 @@ | ||
| 1 | export fn entry() u32 { | ||
| 2 | var bytes: [4]u8 = [_]u8{0x01, 0x02, 0x03, 0x04}; | ||
| 3 | const ptr = @ptrCast(*u32, &bytes[0]); | ||
| 4 | return ptr.*; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage1 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // tmp.zig:3:17: error: cast increases pointer alignment | ||
| 12 | // tmp.zig:3:38: note: '*u8' has alignment 1 | ||
| 13 | // tmp.zig:3:26: note: '*u32' has alignment 4 | ||
test/cases/compile_errors/stage1/obj/issue_5221_invalid_struct_init_type_referenced_by_typeInfo_and_passed_into_function.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | fn ignore(comptime param: anytype) void {_ = param;} | ||
| 2 | |||
| 3 | export fn foo() void { | ||
| 4 | const MyStruct = struct { | ||
| 5 | wrong_type: []u8 = "foo", | ||
| 6 | }; | ||
| 7 | |||
| 8 | comptime ignore(@typeInfo(MyStruct).Struct.fields[0]); | ||
| 9 | } | ||
| 10 | |||
| 11 | // error | ||
| 12 | // backend=stage1 | ||
| 13 | // target=native | ||
| 14 | // | ||
| 15 | // :5:28: error: cannot cast pointer to array literal to slice type '[]u8' | ||
| 16 | // :5:28: note: cast discards const qualifier | ||
test/cases/compile_errors/stage1/obj/peer_cast_then_implicit_cast_const_pointer_to_mutable_C_pointer.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | export fn func() void { | ||
| 2 | var strValue: [*c]u8 = undefined; | ||
| 3 | strValue = strValue orelse ""; | ||
| 4 | } | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=stage1 | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0:0]u8' | ||
| 11 | // tmp.zig:3:32: note: cast discards const qualifier | ||
test/cases/compile_errors/stage1/obj/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig deleted-24| ... | @@ -1,24 +0,0 @@ | ||
| 1 | comptime { | ||
| 2 | const c: [][]const u8 = &.{"hello", "world" }; | ||
| 3 | _ = c; | ||
| 4 | } | ||
| 5 | comptime { | ||
| 6 | const c: *[2][]const u8 = &.{"hello", "world" }; | ||
| 7 | _ = c; | ||
| 8 | } | ||
| 9 | const S = struct {a: u8 = 1, b: u32 = 2}; | ||
| 10 | comptime { | ||
| 11 | const c: *S = &.{}; | ||
| 12 | _ = c; | ||
| 13 | } | ||
| 14 | |||
| 15 | // error | ||
| 16 | // backend=stage1 | ||
| 17 | // target=native | ||
| 18 | // | ||
| 19 | // tmp.zig:2:31: error: cannot cast pointer to array literal to slice type '[][]const u8' | ||
| 20 | // tmp.zig:2:31: note: cast discards const qualifier | ||
| 21 | // tmp.zig:6:33: error: cannot cast pointer to array literal to '*[2][]const u8' | ||
| 22 | // tmp.zig:6:33: note: cast discards const qualifier | ||
| 23 | // tmp.zig:11:21: error: expected type '*S', found '*const struct:11:21' | ||
| 24 | // tmp.zig:11:21: note: cast discards const qualifier | ||
test/cases/compile_errors/stage1/obj/ptrCast_discards_const_qualifier.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | const x: i32 = 1234; | ||
| 3 | const y = @ptrCast(*i32, &x); | ||
| 4 | _ = y; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage1 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // tmp.zig:3:15: error: cast discards const qualifier | ||