diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 67de0cd63d..9daea60e62 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -302,7 +302,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { .Array = .{ .len = array_info.len, .child = array_info.child, - .sentinel = &sentinel_val, + .sentinel = @ptrCast(?*const anyopaque, &sentinel_val), }, }), .is_allowzero = info.is_allowzero, @@ -320,7 +320,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { .address_space = info.address_space, .child = info.child, .is_allowzero = info.is_allowzero, - .sentinel = &sentinel_val, + .sentinel = @ptrCast(?*const anyopaque, &sentinel_val), }, }), else => {}, @@ -338,7 +338,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { .address_space = ptr_info.address_space, .child = ptr_info.child, .is_allowzero = ptr_info.is_allowzero, - .sentinel = &sentinel_val, + .sentinel = @ptrCast(?*const anyopaque, &sentinel_val), }, }), }, diff --git a/lib/std/start_windows_tls.zig b/lib/std/start_windows_tls.zig index 7c9930fe6b..df25a903a2 100644 --- a/lib/std/start_windows_tls.zig +++ b/lib/std/start_windows_tls.zig @@ -42,7 +42,7 @@ export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{ .StartAddressOfRawData = &_tls_start, .EndAddressOfRawData = &_tls_end, .AddressOfIndex = &_tls_index, - .AddressOfCallBacks = &__xl_a, + .AddressOfCallBacks = @ptrCast(*anyopaque, &__xl_a), .SizeOfZeroFill = 0, .Characteristics = 0, }; diff --git a/src/Sema.zig b/src/Sema.zig index 954eaddab9..dd0f0ab50a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -23928,9 +23928,20 @@ fn coerceExtra( // cast from ?*T and ?[*]T to ?*anyopaque // but don't do it if the source type is a double pointer if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and - inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer) - { + inst_ty.isPtrAtRuntime()) + anyopaque_check: { if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional; + const elem_ty = inst_ty.elemType2(); + if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) { + in_memory_result = .{ .double_ptr_to_anyopaque = .{ + .actual = inst_ty, + .wanted = dest_ty, + } }; + break :optional; + } + // Let the logic below handle wrapping the optional now that + // it has been checked to correctly coerce. + if (!inst_ty.isPtrLikeOptional()) break: anyopaque_check; return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); } @@ -24053,9 +24064,16 @@ fn coerceExtra( // cast from *T and [*]T to *anyopaque // but don't do it if the source type is a double pointer - if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer and - inst_ty.childType().zigTypeTag() != .Pointer and sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) - { + if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) { + if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; + const elem_ty = inst_ty.elemType2(); + if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) { + in_memory_result = .{ .double_ptr_to_anyopaque = .{ + .actual = inst_ty, + .wanted = dest_ty, + } }; + break :pointer; + } return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); } @@ -24537,6 +24555,7 @@ const InMemoryCoercionResult = union(enum) { ptr_allowzero: Pair, ptr_bit_range: BitRange, ptr_alignment: IntPair, + double_ptr_to_anyopaque: Pair, const Pair = struct { actual: Type, @@ -24829,6 +24848,12 @@ const InMemoryCoercionResult = union(enum) { }); break; }, + .double_ptr_to_anyopaque => |pair| { + try sema.errNote(block, src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{ + pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod), + }); + break; + }, }; } }; diff --git a/src/type.zig b/src/type.zig index b4015427c8..0fc580000a 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3941,10 +3941,7 @@ pub const Type = extern union { .optional => { var buf: Payload.ElemType = undefined; const child_type = self.optionalChild(&buf); - // optionals of zero sized pointers behave like bools - if (!child_type.hasRuntimeBits()) return false; if (child_type.zigTypeTag() != .Pointer) return false; - const info = child_type.ptrInfo().data; switch (info.size) { .Slice, .C => return false, diff --git a/test/cases/compile_errors/dont_implicit_cast_double_pointer_to_anyopaque.zig b/test/cases/compile_errors/dont_implicit_cast_double_pointer_to_anyopaque.zig deleted file mode 100644 index 44ae18ae8a..0000000000 --- a/test/cases/compile_errors/dont_implicit_cast_double_pointer_to_anyopaque.zig +++ /dev/null @@ -1,14 +0,0 @@ -export fn entry() void { - var a: u32 = 1; - var ptr: *align(@alignOf(u32)) anyopaque = &a; - var b: *u32 = @ptrCast(*u32, ptr); - var ptr2: *anyopaque = &b; - _ = ptr2; -} - -// error -// backend=stage2 -// target=native -// -// :5:28: error: expected type '*anyopaque', found '**u32' -// :5:28: note: pointer type child '*u32' cannot cast into pointer type child 'anyopaque' diff --git a/test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig b/test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig new file mode 100644 index 0000000000..6aa9618dbd --- /dev/null +++ b/test/cases/compile_errors/double_pointer_to_anyopaque_pointer.zig @@ -0,0 +1,28 @@ +pub export fn entry1() void { + const x: usize = 5; + + const ptr: *const anyopaque = &(&x); + _ = ptr; +} +pub export fn entry2() void { + var val: [*:0]u8 = undefined; + func(&val); +} +fn func(_: ?*anyopaque) void {} +pub export fn entry3() void { + var x: *?*usize = undefined; + + const ptr: *const anyopaque = x; + _ = ptr; +} + +// error +// backend=stage2 +// target=native +// +// :4:35: error: expected type '*const anyopaque', found '*const *const usize' +// :4:35: note: cannot implicitly cast double pointer '*const *const usize' to anyopaque pointer '*const anyopaque' +// :9:10: error: expected type '?*anyopaque', found '*[*:0]u8' +// :9:10: note: cannot implicitly cast double pointer '*[*:0]u8' to anyopaque pointer '?*anyopaque' +// :15:35: error: expected type '*const anyopaque', found '*?*usize' +// :15:35: note: cannot implicitly cast double pointer '*?*usize' to anyopaque pointer '*const anyopaque'