| 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 | 34258 | |
| 34259 | 34259 | fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value) CompileError!DerefResult { |
| 34260 | 34260 | const pt = sema.pt; |
| 34261 | const ip = &pt.zcu.intern_pool; | |
| 34261 | const zcu = pt.zcu; | |
| 34262 | const ip = &zcu.intern_pool; | |
| 34262 | 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 | 34270 | .runtime_load => return .runtime_load, |
| 34265 | 34271 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 34266 | 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 | 377 | src, |
| 378 | 378 | null, |
| 379 | 379 | )) { |
| 380 | // We already have a value which is IMC to the desired type. | |
| 381 | return .{ .success = base_val }; | |
| 380 | // We already have a value which is IMC to the desired type. If the type matches | |
| 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 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 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 | 6 | const ptr_size = @sizeOf(usize); |
| 6 | 7 | |
| 7 | 8 | test "type pun signed and unsigned as single pointer" { |
| ... | ... | @@ -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 | } |