| author | |
| committer | |
| log | 9a810ff16e1969b7be4a3e0799741fda0077b2f7 |
| tree | a871143f49499767c366849f9715914fb5281d02 |
| parent | 1b7a78122ecf9d5f6d36b46c26bd5e3fb8211eea |
And add an assertion to `Sema.pointerDerefExtra` to hopefully catch this
kind of bug a little more easily next time: this bug actually snuck past
our existing assertions in many cases!
Resolves: https://codeberg.org/ziglang/zig/issues/364523 files changed, 29 insertions(+), 5 deletions(-)
src/Sema.zig+8-2| ... | @@ -34258,9 +34258,15 @@ const DerefResult = union(enum) { | ... | @@ -34258,9 +34258,15 @@ const DerefResult = union(enum) { |
| 34258 | 34258 | ||
| 34259 | fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value) CompileError!DerefResult { | 34259 | fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value) CompileError!DerefResult { |
| 34260 | const pt = sema.pt; | 34260 | const pt = sema.pt; |
| 34261 | const ip = &pt.zcu.intern_pool; | 34261 | const zcu = pt.zcu; |
| 34262 | const ip = &zcu.intern_pool; | ||
| 34262 | switch (try sema.loadComptimePtr(block, src, ptr_val)) { | 34263 | switch (try sema.loadComptimePtr(block, src, ptr_val)) { |
| 34263 | .success => |mv| return .{ .val = try mv.intern(pt, sema.arena) }, | 34264 | .success => |mv| { |
| 34265 | const loaded_val = try mv.intern(pt, sema.arena); | ||
| 34266 | const elem_ty_ip = ptr_val.typeOf(zcu).ptrInfo(zcu).child; | ||
| 34267 | assert(loaded_val.typeOf(zcu).toIntern() == elem_ty_ip); | ||
| 34268 | return .{ .val = loaded_val }; | ||
| 34269 | }, | ||
| 34264 | .runtime_load => return .runtime_load, | 34270 | .runtime_load => return .runtime_load, |
| 34265 | .undef => return sema.failWithUseOfUndef(block, src, null), | 34271 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 34266 | .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {f}", .{err_name.fmt(ip)}), | 34272 | .err_payload => |err_name| return sema.fail(block, src, "attempt to unwrap error: {f}", .{err_name.fmt(ip)}), |
src/Sema/comptime_ptr_access.zig+9-2| ... | @@ -377,8 +377,15 @@ fn loadComptimePtrInner( | ... | @@ -377,8 +377,15 @@ fn loadComptimePtrInner( |
| 377 | src, | 377 | src, |
| 378 | null, | 378 | null, |
| 379 | )) { | 379 | )) { |
| 380 | // We already have a value which is IMC to the desired type. | 380 | // We already have a value which is IMC to the desired type. If the type matches |
| 381 | return .{ .success = base_val }; | 381 | // exactly we can just return `base_val`, otherwise we need to do the coercion. |
| 382 | if (base_val.typeOf(zcu).toIntern() == load_ty.toIntern()) { | ||
| 383 | return .{ .success = base_val }; | ||
| 384 | } else { | ||
| 385 | const interned_val = try base_val.intern(pt, sema.arena); | ||
| 386 | const coerced_val = try pt.getCoerced(interned_val, load_ty); | ||
| 387 | return .{ .success = .{ .interned = coerced_val.toIntern() } }; | ||
| 388 | } | ||
| 382 | } | 389 | } |
| 383 | } | 390 | } |
| 384 | } | 391 | } |
test/behavior/comptime_memory.zig+12-1| ... | @@ -1,7 +1,8 @@ | ... | @@ -1,7 +1,8 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const endian = builtin.cpu.arch.endian(); | 3 | const endian = builtin.cpu.arch.endian(); |
| 4 | const testing = @import("std").testing; | 4 | const testing = std.testing; |
| 5 | const assert = std.debug.assert; | ||
| 5 | const ptr_size = @sizeOf(usize); | 6 | const ptr_size = @sizeOf(usize); |
| 6 | 7 | ||
| 7 | test "type pun signed and unsigned as single pointer" { | 8 | test "type pun signed and unsigned as single pointer" { |
| ... | @@ -605,3 +606,13 @@ test "reinterpret sentinel-terminated array as packed struct" { | ... | @@ -605,3 +606,13 @@ test "reinterpret sentinel-terminated array as packed struct" { |
| 605 | }, | 606 | }, |
| 606 | } | 607 | } |
| 607 | } | 608 | } |
| 609 | |||
| 610 | test "reinterpret pointer as optional pointer via double-pointer coercion" { | ||
| 611 | const p0: *const *anyopaque = &@ptrFromInt(0x1000); | ||
| 612 | const p1: *const ?*anyopaque = p0; | ||
| 613 | |||
| 614 | const loaded = p1.*; | ||
| 615 | |||
| 616 | comptime assert(@TypeOf(loaded) == ?*anyopaque); | ||
| 617 | comptime assert(@intFromPtr(loaded) == 0x1000); | ||
| 618 | } |