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 {
302302 .Array = .{
303303 .len = array_info.len,
304304 .child = array_info.child,
305 .sentinel = &sentinel_val,
305 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
306306 },
307307 }),
308308 .is_allowzero = info.is_allowzero,
......@@ -320,7 +320,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
320320 .address_space = info.address_space,
321321 .child = info.child,
322322 .is_allowzero = info.is_allowzero,
323 .sentinel = &sentinel_val,
323 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
324324 },
325325 }),
326326 else => {},
......@@ -338,7 +338,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
338338 .address_space = ptr_info.address_space,
339339 .child = ptr_info.child,
340340 .is_allowzero = ptr_info.is_allowzero,
341 .sentinel = &sentinel_val,
341 .sentinel = @ptrCast(?*const anyopaque, &sentinel_val),
342342 },
343343 }),
344344 },
lib/std/start_windows_tls.zig+1-1
......@@ -42,7 +42,7 @@ export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{
4242 .StartAddressOfRawData = &_tls_start,
4343 .EndAddressOfRawData = &_tls_end,
4444 .AddressOfIndex = &_tls_index,
45 .AddressOfCallBacks = &__xl_a,
45 .AddressOfCallBacks = @ptrCast(*anyopaque, &__xl_a),
4646 .SizeOfZeroFill = 0,
4747 .Characteristics = 0,
4848};
src/Sema.zig+30-5
......@@ -23928,9 +23928,20 @@ fn coerceExtra(
2392823928 // cast from ?*T and ?[*]T to ?*anyopaque
2392923929 // but don't do it if the source type is a double pointer
2393023930 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and
23931 inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer)
23932 {
23931 inst_ty.isPtrAtRuntime())
23932 anyopaque_check: {
2393323933 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;
2393423945 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2393523946 }
2393623947
......@@ -24053,9 +24064,16 @@ fn coerceExtra(
2405324064
2405424065 // cast from *T and [*]T to *anyopaque
2405524066 // 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 and
24057 inst_ty.childType().zigTypeTag() != .Pointer and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
24058 {
24067 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) {
24068 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
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 }
2405924077 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2406024078 }
2406124079
......@@ -24537,6 +24555,7 @@ const InMemoryCoercionResult = union(enum) {
2453724555 ptr_allowzero: Pair,
2453824556 ptr_bit_range: BitRange,
2453924557 ptr_alignment: IntPair,
24558 double_ptr_to_anyopaque: Pair,
2454024559
2454124560 const Pair = struct {
2454224561 actual: Type,
......@@ -24829,6 +24848,12 @@ const InMemoryCoercionResult = union(enum) {
2482924848 });
2483024849 break;
2483124850 },
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 },
2483224857 };
2483324858 }
2483424859};
src/type.zig-3
......@@ -3941,10 +3941,7 @@ pub const Type = extern union {
39413941 .optional => {
39423942 var buf: Payload.ElemType = undefined;
39433943 const child_type = self.optionalChild(&buf);
3944 // optionals of zero sized pointers behave like bools
3945 if (!child_type.hasRuntimeBits()) return false;
39463944 if (child_type.zigTypeTag() != .Pointer) return false;
3947
39483945 const info = child_type.ptrInfo().data;
39493946 switch (info.size) {
39503947 .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'