authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-24 17:31:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-25 11:23:41-07:00
log1ba72bcf9a86060fc39117f89536a971ace620c4
tree0c4b819a94bdc1692a17d4a0e542505d1f9c0b6e
parent747f58366a25593431a0e8ff85d76095e0e39e74

update test cases for new memcpy/memset semantics


11 files changed, 137 insertions(+), 28 deletions(-)

lib/std/zig/c_builtins.zig+4-4
......@@ -171,10 +171,10 @@ pub inline fn __builtin_memcpy(
171171 noalias src: ?*const anyopaque,
172172 len: usize,
173173) ?*anyopaque {
174 const dst_cast = @ptrCast([*c]u8, dst);
175 const src_cast = @ptrCast([*c]const u8, src);
176
177 @memcpy(dst_cast[0..len], src_cast);
174 if (len > 0) @memcpy(
175 @ptrCast([*]u8, dst.?)[0..len],
176 @ptrCast([*]const u8, src.?),
177 );
178178 return dst;
179179}
180180
src/Sema.zig+1-17
......@@ -20424,22 +20424,6 @@ fn checkPtrType(
2042420424 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)});
2042520425}
2042620426
20427fn checkSliceOrArrayType(
20428 sema: *Sema,
20429 block: *Block,
20430 ty_src: LazySrcLoc,
20431 ty: Type,
20432) CompileError!void {
20433 if (ty.zigTypeTag() == .Pointer) {
20434 switch (ty.ptrSize()) {
20435 .Slice => return,
20436 .One => if (ty.childType().zigTypeTag() == .Array) return,
20437 else => {},
20438 }
20439 }
20440 return sema.fail(block, ty_src, "expected slice or array pointer; found '{}'", .{ty.fmt(sema.mod)});
20441}
20442
2044320427fn checkVectorElemType(
2044420428 sema: *Sema,
2044520429 block: *Block,
......@@ -21993,7 +21977,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2199321977 const dest_ptr = try sema.resolveInst(extra.lhs);
2199421978 const uncoerced_elem = try sema.resolveInst(extra.rhs);
2199521979 const dest_ptr_ty = sema.typeOf(dest_ptr);
21996 try checkSliceOrArrayType(sema, block, dest_src, dest_ptr_ty);
21980 try checkIndexable(sema, block, dest_src, dest_ptr_ty);
2199721981
2199821982 const dest_elem_ty = dest_ptr_ty.elemType2();
2199921983 const target = sema.mod.getTarget();
test/behavior/builtin_functions_returning_void_or_noreturn.zig+2-2
......@@ -17,8 +17,8 @@ test {
1717 try testing.expectEqual(void, @TypeOf(@breakpoint()));
1818 try testing.expectEqual({}, @export(x, .{ .name = "x" }));
1919 try testing.expectEqual({}, @fence(.Acquire));
20 try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1), @intToPtr([*]u8, 1), 0));
21 try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1), undefined, 0));
20 try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1)[0..0], @intToPtr([*]u8, 1)[0..0]));
21 try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1)[0..0], undefined));
2222 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));
2323 try testing.expectEqual({}, @prefetch(&val, .{}));
2424 try testing.expectEqual({}, @setAlignStack(16));
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig+21-4
......@@ -2,18 +2,35 @@ pub export fn entry() void {
22 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
33 var slice: []u8 = &buf;
44 const a: u32 = 1234;
5 @memcpy(slice, @ptrCast([*]const u8, &a));
5 @memcpy(slice.ptr, @ptrCast([*]const u8, &a));
66}
77pub export fn entry1() void {
88 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
99 var ptr: *u8 = &buf[0];
1010 @memcpy(ptr, 0);
1111}
12pub export fn entry2() void {
13 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
14 var ptr: *u8 = &buf[0];
15 @memset(ptr, 0);
16}
17pub export fn non_matching_lengths() void {
18 var buf1: [5]u8 = .{ 1, 2, 3, 4, 5 };
19 var buf2: [6]u8 = .{ 1, 2, 3, 4, 5, 6 };
20 @memcpy(&buf2, &buf1);
21}
1222
1323// error
1424// backend=stage2
1525// target=native
1626//
17// :5:13: error: expected type '[*]u8', found '[]u8'
18// :10:13: error: expected type '[*]u8', found '*u8'
19// :10:13: note: a single pointer cannot cast into a many pointer
27// :5:5: error: unknown @memcpy length
28// :5:18: note: destination type [*]u8 provides no length
29// :5:24: note: source type [*]align(4) const u8 provides no length
30// :10:13: error: type 'u8' does not support indexing
31// :10:13: note: for loop operand must be an array, slice, tuple, or vector
32// :15:13: error: type '*u8' does not support indexing
33// :15:13: note: for loop operand must be an array, slice, tuple, or vector
34// :20:5: error: non-matching @memcpy lengths
35// :20:13: note: length 6 here
36// :20:20: note: length 5 here
test/cases/safety/memcpy_alias.zig created+17
......@@ -0,0 +1,17 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "@memcpy arguments alias")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [2]u8{ 1, 2 } ** 5;
12 var len: usize = 5;
13 @memcpy(buffer[0..len], buffer[4 .. 4 + len]);
14}
15// run
16// backend=llvm
17// target=native
test/cases/safety/memcpy_len_mismatch.zig created+17
......@@ -0,0 +1,17 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "@memcpy arguments have non-equal lengths")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [2]u8{ 1, 2 } ** 5;
12 var len: usize = 5;
13 @memcpy(buffer[0..len], buffer[len .. len + 4]);
14}
15// run
16// backend=llvm
17// target=native
test/cases/safety/memset_array_undefined_bytes.zig created+18
......@@ -0,0 +1,18 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 };
12 @memset(&buffer, undefined);
13 var x: u8 = buffer[1];
14 x += buffer[2];
15}
16// run
17// backend=llvm
18// target=native
test/cases/safety/memset_array_undefined_large.zig created+18
......@@ -0,0 +1,18 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 };
12 @memset(&buffer, undefined);
13 var x: i32 = buffer[1];
14 x += buffer[2];
15}
16// run
17// backend=llvm
18// target=native
test/cases/safety/memset_slice_undefined_bytes.zig created+19
......@@ -0,0 +1,19 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 };
12 var len = buffer.len;
13 @memset(buffer[0..len], undefined);
14 var x: u8 = buffer[1];
15 x += buffer[2];
16}
17// run
18// backend=llvm
19// target=native
test/cases/safety/memset_slice_undefined_large.zig created+19
......@@ -0,0 +1,19 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 };
12 var len = buffer.len;
13 @memset(buffer[0..len], undefined);
14 var x: i32 = buffer[1];
15 x += buffer[2];
16}
17// run
18// backend=llvm
19// target=native
test/cases/safety/switch on corrupted union value.zig +1-1
......@@ -15,7 +15,7 @@ const U = union(enum(u32)) {
1515
1616pub fn main() !void {
1717 var u: U = undefined;
18 @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
18 @memset(@ptrCast([*]u8, &u)[0..@sizeOf(U)], 0x55);
1919 switch (u) {
2020 .X, .Y => @breakpoint(),
2121 }