authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-28 16:37:02+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-29 14:55:43+03:00
logd7314555f2bc413494d58bbafa2d607b88922afb
treedab26956d951366fdd37024781392428decf6c80
parent9607bd90e6927eea0fc7d57e042d03657afbf70d

Sema: improve compile error for casting double pointer to anyopaque pointer

Closes #12042

6 files changed, 62 insertions(+), 26 deletions(-)

lib/std/meta.zig+3-3
...@@ -302,7 +302,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {...@@ -302,7 +302,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
302 .Array = .{302 .Array = .{
303 .len = array_info.len,303 .len = array_info.len,
304 .child = array_info.child,304 .child = array_info.child,
305 .sentinel = &sentinel_val,305 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
306 },306 },
307 }),307 }),
308 .is_allowzero = info.is_allowzero,308 .is_allowzero = info.is_allowzero,
...@@ -320,7 +320,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {...@@ -320,7 +320,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
320 .address_space = info.address_space,320 .address_space = info.address_space,
321 .child = info.child,321 .child = info.child,
322 .is_allowzero = info.is_allowzero,322 .is_allowzero = info.is_allowzero,
323 .sentinel = &sentinel_val,323 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
324 },324 },
325 }),325 }),
326 else => {},326 else => {},
...@@ -338,7 +338,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {...@@ -338,7 +338,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
338 .address_space = ptr_info.address_space,338 .address_space = ptr_info.address_space,
339 .child = ptr_info.child,339 .child = ptr_info.child,
340 .is_allowzero = ptr_info.is_allowzero,340 .is_allowzero = ptr_info.is_allowzero,
341 .sentinel = &sentinel_val,341 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
342 },342 },
343 }),343 }),
344 },344 },
lib/std/start_windows_tls.zig+1-1
...@@ -42,7 +42,7 @@ export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{...@@ -42,7 +42,7 @@ export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{
42 .StartAddressOfRawData = &_tls_start,42 .StartAddressOfRawData = &_tls_start,
43 .EndAddressOfRawData = &_tls_end,43 .EndAddressOfRawData = &_tls_end,
44 .AddressOfIndex = &_tls_index,44 .AddressOfIndex = &_tls_index,
45 .AddressOfCallBacks = &__xl_a,45 .AddressOfCallBacks = @ptrCast(*anyopaque, &__xl_a),
46 .SizeOfZeroFill = 0,46 .SizeOfZeroFill = 0,
47 .Characteristics = 0,47 .Characteristics = 0,
48};48};
src/Sema.zig+30-5
...@@ -23928,9 +23928,20 @@ fn coerceExtra(...@@ -23928,9 +23928,20 @@ fn coerceExtra(
23928 // cast from ?*T and ?[*]T to ?*anyopaque23928 // cast from ?*T and ?[*]T to ?*anyopaque
23929 // but don't do it if the source type is a double pointer23929 // but don't do it if the source type is a double pointer
23930 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and23930 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and
23931 inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer)23931 inst_ty.isPtrAtRuntime())
23932 {23932 anyopaque_check: {
23933 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;23933 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
23934 const elem_ty = inst_ty.elemType2();
23935 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
23936 in_memory_result = .{ .double_ptr_to_anyopaque = .{
23937 .actual = inst_ty,
23938 .wanted = dest_ty,
23939 } };
23940 break :optional;
23941 }
23942 // Let the logic below handle wrapping the optional now that
23943 // it has been checked to correctly coerce.
23944 if (!inst_ty.isPtrLikeOptional()) break: anyopaque_check;
23934 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);23945 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
23935 }23946 }
2393623947
...@@ -24053,9 +24064,16 @@ fn coerceExtra(...@@ -24053,9 +24064,16 @@ fn coerceExtra(
2405324064
24054 // cast from *T and [*]T to *anyopaque24065 // cast from *T and [*]T to *anyopaque
24055 // but don't do it if the source type is a double pointer24066 // but don't do it if the source type is a double pointer
24056 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and24067 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) {
24057 inst_ty.childType().zigTypeTag() != .Pointer and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))24068 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
24058 {24069 const elem_ty = inst_ty.elemType2();
24070 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
24071 in_memory_result = .{ .double_ptr_to_anyopaque = .{
24072 .actual = inst_ty,
24073 .wanted = dest_ty,
24074 } };
24075 break :pointer;
24076 }
24059 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);24077 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
24060 }24078 }
2406124079
...@@ -24537,6 +24555,7 @@ const InMemoryCoercionResult = union(enum) {...@@ -24537,6 +24555,7 @@ const InMemoryCoercionResult = union(enum) {
24537 ptr_allowzero: Pair,24555 ptr_allowzero: Pair,
24538 ptr_bit_range: BitRange,24556 ptr_bit_range: BitRange,
24539 ptr_alignment: IntPair,24557 ptr_alignment: IntPair,
24558 double_ptr_to_anyopaque: Pair,
2454024559
24541 const Pair = struct {24560 const Pair = struct {
24542 actual: Type,24561 actual: Type,
...@@ -24829,6 +24848,12 @@ const InMemoryCoercionResult = union(enum) {...@@ -24829,6 +24848,12 @@ const InMemoryCoercionResult = union(enum) {
24829 });24848 });
24830 break;24849 break;
24831 },24850 },
24851 .double_ptr_to_anyopaque => |pair| {
24852 try sema.errNote(block, src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{
24853 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
24854 });
24855 break;
24856 },
24832 };24857 };
24833 }24858 }
24834};24859};
src/type.zig-3
...@@ -3941,10 +3941,7 @@ pub const Type = extern union {...@@ -3941,10 +3941,7 @@ pub const Type = extern union {
3941 .optional => {3941 .optional => {
3942 var buf: Payload.ElemType = undefined;3942 var buf: Payload.ElemType = undefined;
3943 const child_type = self.optionalChild(&buf);3943 const child_type = self.optionalChild(&buf);
3944 // optionals of zero sized pointers behave like bools
3945 if (!child_type.hasRuntimeBits()) return false;
3946 if (child_type.zigTypeTag() != .Pointer) return false;3944 if (child_type.zigTypeTag() != .Pointer) return false;
3947
3948 const info = child_type.ptrInfo().data;3945 const info = child_type.ptrInfo().data;
3949 switch (info.size) {3946 switch (info.size) {
3950 .Slice, .C => return false,3947 .Slice, .C => return false,
test/cases/compile_errors/dont_implicit_cast_double_pointer_to_anyopaque.zig deleted-14
...@@ -1,14 +0,0 @@
1export fn entry() void {
2 var a: u32 = 1;
3 var ptr: *align(@alignOf(u32)) anyopaque = &a;
4 var b: *u32 = @ptrCast(*u32, ptr);
5 var ptr2: *anyopaque = &b;
6 _ = ptr2;
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :5:28: error: expected type '*anyopaque', found '**u32'
14// :5:28: note: pointer type child '*u32' cannot cast into pointer type child 'anyopaque'
test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig created+28
...@@ -0,0 +1,28 @@
1pub export fn entry1() void {
2 const x: usize = 5;
3
4 const ptr: *const anyopaque = &(&x);
5 _ = ptr;
6}
7pub export fn entry2() void {
8 var val: [*:0]u8 = undefined;
9 func(&val);
10}
11fn func(_: ?*anyopaque) void {}
12pub export fn entry3() void {
13 var x: *?*usize = undefined;
14
15 const ptr: *const anyopaque = x;
16 _ = ptr;
17}
18
19// error
20// backend=stage2
21// target=native
22//
23// :4:35: error: expected type '*const anyopaque', found '*const *const usize'
24// :4:35: note: cannot implicitly cast double pointer '*const *const usize' to anyopaque pointer '*const anyopaque'
25// :9:10: error: expected type '?*anyopaque', found '*[*:0]u8'
26// :9:10: note: cannot implicitly cast double pointer '*[*:0]u8' to anyopaque pointer '?*anyopaque'
27// :15:35: error: expected type '*const anyopaque', found '*?*usize'
28// :15:35: note: cannot implicitly cast double pointer '*?*usize' to anyopaque pointer '*const anyopaque'