authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-27 20:25:48+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-30 18:55:57+02:00
logf16c10a86b7183e99e54a70344f4681211cd52bb
treeaa6c1f3510696eb5ee63dd4ddb17c96cc6dce45b
parentfe4ea31f7e9e1c8caea6a1df107b91e8ea1a7b8a

implement `@qualCast`


13 files changed, 113 insertions(+), 18 deletions(-)

doc/langref.html.in+11-4
...@@ -8803,10 +8803,10 @@ pub const PrefetchOptions = struct {...@@ -8803,10 +8803,10 @@ pub const PrefetchOptions = struct {
8803 {#syntax#}@ptrCast{#endsyntax#} cannot be used for:8803 {#syntax#}@ptrCast{#endsyntax#} cannot be used for:
8804 </p>8804 </p>
8805 <ul>8805 <ul>
8806 <li>Removing {#syntax#}const{#endsyntax#} or {#syntax#}volatile{#endsyntax#} qualifier. TODO add a {#syntax#}@qualCast{#endsyntax#} builtin.</li>8806 <li>Removing {#syntax#}const{#endsyntax#} or {#syntax#}volatile{#endsyntax#} qualifier, use {#link|@qualCast#}.</li>
8807 <li>Changing pointer address space, use {#link|@addrSpaceCast#}</li>8807 <li>Changing pointer address space, use {#link|@addrSpaceCast#}.</li>
8808 <li>Increasing pointer alignment, use {#link|@alignCast#}</li>8808 <li>Increasing pointer alignment, use {#link|@alignCast#}.</li>
8809 <li>Casting a non-slice pointer to a slice, use slicing syntax {#syntax#}ptr[start..end]{#endsyntax#}</li>8809 <li>Casting a non-slice pointer to a slice, use slicing syntax {#syntax#}ptr[start..end]{#endsyntax#}.</li>
8810 </ul>8810 </ul>
8811 {#header_close#}8811 {#header_close#}
88128812
...@@ -8820,6 +8820,13 @@ pub const PrefetchOptions = struct {...@@ -8820,6 +8820,13 @@ pub const PrefetchOptions = struct {
88208820
8821 {#header_close#}8821 {#header_close#}
88228822
8823 {#header_open|@qualCast#}
8824 <pre>{#syntax#}@qualCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}</pre>
8825 <p>
8826 Remove {#syntax#}const{#endsyntax#} or {#syntax#}volatile{#endsyntax#} qualifier from a pointer.
8827 </p>
8828 {#header_close#}
8829
8823 {#header_open|@rem#}8830 {#header_open|@rem#}
8824 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>8831 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
8825 <p>8832 <p>
lib/std/child_process.zig+2-2
...@@ -1164,7 +1164,7 @@ fn windowsCreateProcessPathExt(...@@ -1164,7 +1164,7 @@ fn windowsCreateProcessPathExt(
1164 var app_name_unicode_string = windows.UNICODE_STRING{1164 var app_name_unicode_string = windows.UNICODE_STRING{
1165 .Length = app_name_len_bytes,1165 .Length = app_name_len_bytes,
1166 .MaximumLength = app_name_len_bytes,1166 .MaximumLength = app_name_len_bytes,
1167 .Buffer = @intToPtr([*]u16, @ptrToInt(app_name_wildcard.ptr)),1167 .Buffer = @qualCast([*:0]u16, app_name_wildcard.ptr),
1168 };1168 };
1169 const rc = windows.ntdll.NtQueryDirectoryFile(1169 const rc = windows.ntdll.NtQueryDirectoryFile(
1170 dir.fd,1170 dir.fd,
...@@ -1261,7 +1261,7 @@ fn windowsCreateProcessPathExt(...@@ -1261,7 +1261,7 @@ fn windowsCreateProcessPathExt(
1261 var app_name_unicode_string = windows.UNICODE_STRING{1261 var app_name_unicode_string = windows.UNICODE_STRING{
1262 .Length = app_name_len_bytes,1262 .Length = app_name_len_bytes,
1263 .MaximumLength = app_name_len_bytes,1263 .MaximumLength = app_name_len_bytes,
1264 .Buffer = @intToPtr([*]u16, @ptrToInt(app_name_appended.ptr)),1264 .Buffer = @qualCast([*:0]u16, app_name_appended.ptr),
1265 };1265 };
12661266
1267 // Re-use the directory handle but this time we call with the appended app name1267 // Re-use the directory handle but this time we call with the appended app name
lib/std/fs.zig+1-1
...@@ -1763,7 +1763,7 @@ pub const Dir = struct {...@@ -1763,7 +1763,7 @@ pub const Dir = struct {
1763 var nt_name = w.UNICODE_STRING{1763 var nt_name = w.UNICODE_STRING{
1764 .Length = path_len_bytes,1764 .Length = path_len_bytes,
1765 .MaximumLength = path_len_bytes,1765 .MaximumLength = path_len_bytes,
1766 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),1766 .Buffer = @qualCast([*:0]u16, sub_path_w),
1767 };1767 };
1768 var attr = w.OBJECT_ATTRIBUTES{1768 var attr = w.OBJECT_ATTRIBUTES{
1769 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),1769 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
lib/std/os.zig+1-1
...@@ -4513,7 +4513,7 @@ pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32...@@ -4513,7 +4513,7 @@ pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32
4513 var nt_name = windows.UNICODE_STRING{4513 var nt_name = windows.UNICODE_STRING{
4514 .Length = path_len_bytes,4514 .Length = path_len_bytes,
4515 .MaximumLength = path_len_bytes,4515 .MaximumLength = path_len_bytes,
4516 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),4516 .Buffer = @qualCast([*:0]u16, sub_path_w),
4517 };4517 };
4518 var attr = windows.OBJECT_ATTRIBUTES{4518 var attr = windows.OBJECT_ATTRIBUTES{
4519 .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),4519 .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
lib/std/os/windows.zig+7-7
...@@ -85,7 +85,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -85,7 +85,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
85 var nt_name = UNICODE_STRING{85 var nt_name = UNICODE_STRING{
86 .Length = path_len_bytes,86 .Length = path_len_bytes,
87 .MaximumLength = path_len_bytes,87 .MaximumLength = path_len_bytes,
88 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w.ptr)),88 .Buffer = @qualCast([*]u16, sub_path_w.ptr),
89 };89 };
90 var attr = OBJECT_ATTRIBUTES{90 var attr = OBJECT_ATTRIBUTES{
91 .Length = @sizeOf(OBJECT_ATTRIBUTES),91 .Length = @sizeOf(OBJECT_ATTRIBUTES),
...@@ -634,7 +634,7 @@ pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void...@@ -634,7 +634,7 @@ pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void
634 var nt_name = UNICODE_STRING{634 var nt_name = UNICODE_STRING{
635 .Length = path_len_bytes,635 .Length = path_len_bytes,
636 .MaximumLength = path_len_bytes,636 .MaximumLength = path_len_bytes,
637 .Buffer = @intToPtr([*]u16, @ptrToInt(path_name.ptr)),637 .Buffer = @qualCast([*]u16, path_name.ptr),
638 };638 };
639639
640 const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);640 const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
...@@ -766,7 +766,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin...@@ -766,7 +766,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin
766 var nt_name = UNICODE_STRING{766 var nt_name = UNICODE_STRING{
767 .Length = path_len_bytes,767 .Length = path_len_bytes,
768 .MaximumLength = path_len_bytes,768 .MaximumLength = path_len_bytes,
769 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w.ptr)),769 .Buffer = @qualCast([*]u16, sub_path_w.ptr),
770 };770 };
771 var attr = OBJECT_ATTRIBUTES{771 var attr = OBJECT_ATTRIBUTES{
772 .Length = @sizeOf(OBJECT_ATTRIBUTES),772 .Length = @sizeOf(OBJECT_ATTRIBUTES),
...@@ -876,7 +876,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil...@@ -876,7 +876,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
876 .Length = path_len_bytes,876 .Length = path_len_bytes,
877 .MaximumLength = path_len_bytes,877 .MaximumLength = path_len_bytes,
878 // The Windows API makes this mutable, but it will not mutate here.878 // The Windows API makes this mutable, but it will not mutate here.
879 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w.ptr)),879 .Buffer = @qualCast([*]u16, sub_path_w.ptr),
880 };880 };
881881
882 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {882 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
...@@ -1414,7 +1414,7 @@ pub fn sendmsg(...@@ -1414,7 +1414,7 @@ pub fn sendmsg(
1414}1414}
14151415
1416pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {1416pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 {
1417 var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @intToPtr([*]u8, @ptrToInt(buf)) };1417 var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @qualCast([*]u8, buf) };
1418 var bytes_send: DWORD = undefined;1418 var bytes_send: DWORD = undefined;
1419 if (ws2_32.WSASendTo(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_send, flags, to, @intCast(i32, to_len), null, null) == ws2_32.SOCKET_ERROR) {1419 if (ws2_32.WSASendTo(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_send, flags, to, @intCast(i32, to_len), null, null) == ws2_32.SOCKET_ERROR) {
1420 return ws2_32.SOCKET_ERROR;1420 return ws2_32.SOCKET_ERROR;
...@@ -1876,13 +1876,13 @@ pub fn eqlIgnoreCaseWTF16(a: []const u16, b: []const u16) bool {...@@ -1876,13 +1876,13 @@ pub fn eqlIgnoreCaseWTF16(a: []const u16, b: []const u16) bool {
1876 const a_string = UNICODE_STRING{1876 const a_string = UNICODE_STRING{
1877 .Length = a_bytes,1877 .Length = a_bytes,
1878 .MaximumLength = a_bytes,1878 .MaximumLength = a_bytes,
1879 .Buffer = @intToPtr([*]u16, @ptrToInt(a.ptr)),1879 .Buffer = @qualCast([*]u16, a.ptr),
1880 };1880 };
1881 const b_bytes = @intCast(u16, b.len * 2);1881 const b_bytes = @intCast(u16, b.len * 2);
1882 const b_string = UNICODE_STRING{1882 const b_string = UNICODE_STRING{
1883 .Length = b_bytes,1883 .Length = b_bytes,
1884 .MaximumLength = b_bytes,1884 .MaximumLength = b_bytes,
1885 .Buffer = @intToPtr([*]u16, @ptrToInt(b.ptr)),1885 .Buffer = @qualCast([*]u16, b.ptr),
1886 };1886 };
1887 return ntdll.RtlEqualUnicodeString(&a_string, &b_string, TRUE) == TRUE;1887 return ntdll.RtlEqualUnicodeString(&a_string, &b_string, TRUE) == TRUE;
1888}1888}
lib/std/zig/c_translation.zig+1-1
...@@ -75,7 +75,7 @@ fn castPtr(comptime DestType: type, target: anytype) DestType {...@@ -75,7 +75,7 @@ fn castPtr(comptime DestType: type, target: anytype) DestType {
75 const source = ptrInfo(@TypeOf(target));75 const source = ptrInfo(@TypeOf(target));
7676
77 if (source.is_const and !dest.is_const or source.is_volatile and !dest.is_volatile)77 if (source.is_const and !dest.is_const or source.is_volatile and !dest.is_volatile)
78 return @intToPtr(DestType, @ptrToInt(target))78 return @qualCast(DestType, target)
79 else if (@typeInfo(dest.child) == .Opaque)79 else if (@typeInfo(dest.child) == .Opaque)
80 // dest.alignment would error out80 // dest.alignment would error out
81 return @ptrCast(DestType, target)81 return @ptrCast(DestType, target)
src/AstGen.zig+2
...@@ -2530,6 +2530,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2530,6 +2530,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2530 .bit_size_of,2530 .bit_size_of,
2531 .typeof_log2_int_type,2531 .typeof_log2_int_type,
2532 .ptr_to_int,2532 .ptr_to_int,
2533 .qual_cast,
2533 .align_of,2534 .align_of,
2534 .bool_to_int,2535 .bool_to_int,
2535 .embed_file,2536 .embed_file,
...@@ -8037,6 +8038,7 @@ fn builtinCall(...@@ -8037,6 +8038,7 @@ fn builtinCall(
8037 .float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast),8038 .float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast),
8038 .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast),8039 .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast),
8039 .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast),8040 .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast),
8041 .qual_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .qual_cast),
8040 .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate),8042 .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate),
8041 // zig fmt: on8043 // zig fmt: on
80428044
src/BuiltinFn.zig+8
...@@ -75,6 +75,7 @@ pub const Tag = enum {...@@ -75,6 +75,7 @@ pub const Tag = enum {
75 prefetch,75 prefetch,
76 ptr_cast,76 ptr_cast,
77 ptr_to_int,77 ptr_to_int,
78 qual_cast,
78 rem,79 rem,
79 return_address,80 return_address,
80 select,81 select,
...@@ -674,6 +675,13 @@ pub const list = list: {...@@ -674,6 +675,13 @@ pub const list = list: {
674 .param_count = 1,675 .param_count = 1,
675 },676 },
676 },677 },
678 .{
679 "@qualCast",
680 .{
681 .tag = .qual_cast,
682 .param_count = 2,
683 },
684 },
677 .{685 .{
678 "@rem",686 "@rem",
679 .{687 .{
src/Sema.zig+60-2
...@@ -1015,6 +1015,7 @@ fn analyzeBodyInner(...@@ -1015,6 +1015,7 @@ fn analyzeBodyInner(
1015 .float_cast => try sema.zirFloatCast(block, inst),1015 .float_cast => try sema.zirFloatCast(block, inst),
1016 .int_cast => try sema.zirIntCast(block, inst),1016 .int_cast => try sema.zirIntCast(block, inst),
1017 .ptr_cast => try sema.zirPtrCast(block, inst),1017 .ptr_cast => try sema.zirPtrCast(block, inst),
1018 .qual_cast => try sema.zirQualCast(block, inst),
1018 .truncate => try sema.zirTruncate(block, inst),1019 .truncate => try sema.zirTruncate(block, inst),
1019 .align_cast => try sema.zirAlignCast(block, inst),1020 .align_cast => try sema.zirAlignCast(block, inst),
1020 .has_decl => try sema.zirHasDecl(block, inst),1021 .has_decl => try sema.zirHasDecl(block, inst),
...@@ -19529,10 +19530,24 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19529,10 +19530,24 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19529 const operand_info = operand_ty.ptrInfo().data;19530 const operand_info = operand_ty.ptrInfo().data;
19530 const dest_info = dest_ty.ptrInfo().data;19531 const dest_info = dest_ty.ptrInfo().data;
19531 if (!operand_info.mutable and dest_info.mutable) {19532 if (!operand_info.mutable and dest_info.mutable) {
19532 return sema.fail(block, src, "cast discards const qualifier", .{});19533 const msg = msg: {
19534 const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{});
19535 errdefer msg.destroy(sema.gpa);
19536
19537 try sema.errNote(block, src, msg, "consider using '@qualCast'", .{});
19538 break :msg msg;
19539 };
19540 return sema.failWithOwnedErrorMsg(msg);
19533 }19541 }
19534 if (operand_info.@"volatile" and !dest_info.@"volatile") {19542 if (operand_info.@"volatile" and !dest_info.@"volatile") {
19535 return sema.fail(block, src, "cast discards volatile qualifier", .{});19543 const msg = msg: {
19544 const msg = try sema.errMsg(block, src, "cast discards volatile qualifier", .{});
19545 errdefer msg.destroy(sema.gpa);
19546
19547 try sema.errNote(block, src, msg, "consider using '@qualCast'", .{});
19548 break :msg msg;
19549 };
19550 return sema.failWithOwnedErrorMsg(msg);
19536 }19551 }
19537 if (operand_info.@"addrspace" != dest_info.@"addrspace") {19552 if (operand_info.@"addrspace" != dest_info.@"addrspace") {
19538 const msg = msg: {19553 const msg = msg: {
...@@ -19634,6 +19649,49 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19634,6 +19649,49 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19634 return block.addBitCast(aligned_dest_ty, ptr);19649 return block.addBitCast(aligned_dest_ty, ptr);
19635}19650}
1963619651
19652fn zirQualCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
19653 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19654 const src = inst_data.src();
19655 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
19656 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
19657 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
19658 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
19659 const operand = try sema.resolveInst(extra.rhs);
19660 const operand_ty = sema.typeOf(operand);
19661
19662 try sema.checkPtrType(block, dest_ty_src, dest_ty);
19663 try sema.checkPtrOperand(block, operand_src, operand_ty);
19664
19665 var operand_payload = operand_ty.ptrInfo();
19666 var dest_info = dest_ty.ptrInfo();
19667
19668 operand_payload.data.mutable = dest_info.data.mutable;
19669 operand_payload.data.@"volatile" = dest_info.data.@"volatile";
19670
19671 const altered_operand_ty = Type.initPayload(&operand_payload.base);
19672 if (!altered_operand_ty.eql(dest_ty, sema.mod)) {
19673 const msg = msg: {
19674 const msg = try sema.errMsg(block, src, "'@qualCast' can only modify 'const' and 'volatile' qualifiers", .{});
19675 errdefer msg.destroy(sema.gpa);
19676
19677 dest_info.data.mutable = !operand_ty.isConstPtr();
19678 dest_info.data.@"volatile" = operand_ty.isVolatilePtr();
19679 const altered_dest_ty = Type.initPayload(&dest_info.base);
19680 try sema.errNote(block, src, msg, "expected type '{}'", .{altered_dest_ty.fmt(sema.mod)});
19681 try sema.errNote(block, src, msg, "got type '{}'", .{operand_ty.fmt(sema.mod)});
19682 break :msg msg;
19683 };
19684 return sema.failWithOwnedErrorMsg(msg);
19685 }
19686
19687 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
19688 return sema.addConstant(dest_ty, operand_val);
19689 }
19690
19691 try sema.requireRuntimeBlock(block, src, null);
19692 return block.addBitCast(dest_ty, operand);
19693}
19694
19637fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {19695fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
19638 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;19696 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
19639 const src = inst_data.src();19697 const src = inst_data.src();
src/Zir.zig+6
...@@ -857,6 +857,9 @@ pub const Inst = struct {...@@ -857,6 +857,9 @@ pub const Inst = struct {
857 /// Implements the `@ptrCast` builtin.857 /// Implements the `@ptrCast` builtin.
858 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.858 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
859 ptr_cast,859 ptr_cast,
860 /// Implements the `@qualCast` builtin.
861 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
862 qual_cast,
860 /// Implements the `@truncate` builtin.863 /// Implements the `@truncate` builtin.
861 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.864 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
862 truncate,865 truncate,
...@@ -1195,6 +1198,7 @@ pub const Inst = struct {...@@ -1195,6 +1198,7 @@ pub const Inst = struct {
1195 .float_cast,1198 .float_cast,
1196 .int_cast,1199 .int_cast,
1197 .ptr_cast,1200 .ptr_cast,
1201 .qual_cast,
1198 .truncate,1202 .truncate,
1199 .align_cast,1203 .align_cast,
1200 .has_field,1204 .has_field,
...@@ -1484,6 +1488,7 @@ pub const Inst = struct {...@@ -1484,6 +1488,7 @@ pub const Inst = struct {
1484 .float_cast,1488 .float_cast,
1485 .int_cast,1489 .int_cast,
1486 .ptr_cast,1490 .ptr_cast,
1491 .qual_cast,
1487 .truncate,1492 .truncate,
1488 .align_cast,1493 .align_cast,
1489 .has_field,1494 .has_field,
...@@ -1755,6 +1760,7 @@ pub const Inst = struct {...@@ -1755,6 +1760,7 @@ pub const Inst = struct {
1755 .float_cast = .pl_node,1760 .float_cast = .pl_node,
1756 .int_cast = .pl_node,1761 .int_cast = .pl_node,
1757 .ptr_cast = .pl_node,1762 .ptr_cast = .pl_node,
1763 .qual_cast = .pl_node,
1758 .truncate = .pl_node,1764 .truncate = .pl_node,
1759 .align_cast = .pl_node,1765 .align_cast = .pl_node,
1760 .typeof_builtin = .pl_node,1766 .typeof_builtin = .pl_node,
src/print_zir.zig+1
...@@ -332,6 +332,7 @@ const Writer = struct {...@@ -332,6 +332,7 @@ const Writer = struct {
332 .float_cast,332 .float_cast,
333 .int_cast,333 .int_cast,
334 .ptr_cast,334 .ptr_cast,
335 .qual_cast,
335 .truncate,336 .truncate,
336 .align_cast,337 .align_cast,
337 .div_exact,338 .div_exact,
test/cases/compile_errors/invalid_qualcast.zig created+12
...@@ -0,0 +1,12 @@
1pub export fn entry() void {
2 var a: [*:0]const volatile u16 = undefined;
3 _ = @qualCast([*]u16, a);
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :3:9: error: '@qualCast' can only modify 'const' and 'volatile' qualifiers
11// :3:9: note: expected type '[*]const volatile u16'
12// :3:9: note: got type '[*:0]const volatile u16'
test/cases/compile_errors/ptrCast_discards_const_qualifier.zig+1
...@@ -9,3 +9,4 @@ export fn entry() void {...@@ -9,3 +9,4 @@ export fn entry() void {
9// target=native9// target=native
10//10//
11// :3:15: error: cast discards const qualifier11// :3:15: error: cast discards const qualifier
12// :3:15: note: consider using '@qualCast'