zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit ab5a72f6ca9446820f3f516873e1b5d1aeefb5a8 (tree)
parent 2ce9122a009efa0a5d2857a0d29ad3d77a81dff1
Author: Veikka Tuominen <git@vexu.eu>
Date:   Sun, 14 May 2023 12:48:11 +0300

Sema: ensure dest ptr of memcpy has length

Closes #15513

Diffstat:
Msrc/Sema.zig | 12++++++++++++
Mtest/behavior/memcpy.zig | 21+++++++++++++++++++++
2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -22130,6 +22130,14 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const ok = try block.addBinOp(.cmp_eq, dest_len, src_len); try sema.addSafetyCheck(block, ok, .memcpy_len_mismatch); } + } else if (dest_len != .none) { + if (try sema.resolveDefinedValue(block, dest_src, dest_len)) |dest_len_val| { + len_val = dest_len_val; + } + } else if (src_len != .none) { + if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| { + len_val = src_len_val; + } } const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { @@ -22213,6 +22221,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void if (new_src_ptr_ty.isSlice()) { new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); } + } else if (dest_len == .none and len_val == null) { + // Change the dest to a slice, since its type must have the length. + const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr); + new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false); } try sema.requireRuntimeBlock(block, src, runtime_src); diff --git a/test/behavior/memcpy.zig b/test/behavior/memcpy.zig @@ -44,3 +44,24 @@ fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void { try expect(buf[98] == 'l'); try expect(buf[99] == 'o'); } + +test "@memcpy dest many pointer" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + + try testMemcpyDestManyPtr(); + try comptime testMemcpyDestManyPtr(); +} + +fn testMemcpyDestManyPtr() !void { + var str = "hello".*; + var buf: [5]u8 = undefined; + @memcpy(@ptrCast([*]u8, &buf), @ptrCast([*]const u8, &str)[0..5]); + try expect(buf[0] == 'h'); + try expect(buf[1] == 'e'); + try expect(buf[2] == 'l'); + try expect(buf[3] == 'l'); + try expect(buf[4] == 'o'); +}