authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2025-01-22 18:44:27+11:00
committergravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2025-04-26 13:34:17+10:00
log4e78836d29260e915e767bc907ff7ba6c652ef5f
tree5006310b522813a4729d4883b6f1557a3ce81719
parent898ca824585e78306bb0137dbae1fbf859b762b6

test: add tests for @memmove


8 files changed, 478 insertions(+), 1 deletions(-)

test/behavior.zig+1
...@@ -55,6 +55,7 @@ test {...@@ -55,6 +55,7 @@ test {
55 _ = @import("behavior/member_func.zig");55 _ = @import("behavior/member_func.zig");
56 _ = @import("behavior/memcpy.zig");56 _ = @import("behavior/memcpy.zig");
57 _ = @import("behavior/memset.zig");57 _ = @import("behavior/memset.zig");
58 _ = @import("behavior/memmove.zig");
58 _ = @import("behavior/merge_error_sets.zig");59 _ = @import("behavior/merge_error_sets.zig");
59 _ = @import("behavior/muladd.zig");60 _ = @import("behavior/muladd.zig");
60 _ = @import("behavior/multiple_externs_with_conflicting_types.zig");61 _ = @import("behavior/multiple_externs_with_conflicting_types.zig");
test/behavior/builtin_functions_returning_void_or_noreturn.zig+2
...@@ -6,6 +6,7 @@ var x: u8 = 1;...@@ -6,6 +6,7 @@ var x: u8 = 1;
66
7// This excludes builtin functions that return void or noreturn that cannot be tested.7// This excludes builtin functions that return void or noreturn that cannot be tested.
8test {8test {
9 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -17,6 +18,7 @@ test {...@@ -17,6 +18,7 @@ test {
17 try testing.expectEqual(void, @TypeOf(@breakpoint()));18 try testing.expectEqual(void, @TypeOf(@breakpoint()));
18 try testing.expectEqual({}, @export(&x, .{ .name = "x" }));19 try testing.expectEqual({}, @export(&x, .{ .name = "x" }));
19 try testing.expectEqual({}, @memcpy(@as([*]u8, @ptrFromInt(1))[0..0], @as([*]u8, @ptrFromInt(1))[0..0]));20 try testing.expectEqual({}, @memcpy(@as([*]u8, @ptrFromInt(1))[0..0], @as([*]u8, @ptrFromInt(1))[0..0]));
21 try testing.expectEqual({}, @memmove(@as([*]u8, @ptrFromInt(1))[0..0], @as([*]u8, @ptrFromInt(1))[0..0]));
20 try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined));22 try testing.expectEqual({}, @memset(@as([*]u8, @ptrFromInt(1))[0..0], undefined));
21 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));23 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));
22 try testing.expectEqual({}, @prefetch(&val, .{}));24 try testing.expectEqual({}, @prefetch(&val, .{}));
test/behavior/memmove.zig created+183
...@@ -0,0 +1,183 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5test "memmove and memset intrinsics" {
6 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13
14 try testMemmoveMemset();
15 try comptime testMemmoveMemset();
16}
17
18fn testMemmoveMemset() !void {
19 var foo: [20]u8 = undefined;
20
21 @memset(foo[0..10], 'A');
22 @memset(foo[10..20], 'B');
23
24 try expect(foo[0] == 'A');
25 try expect(foo[11] == 'B');
26 try expect(foo[19] == 'B');
27
28 @memmove(foo[10..20], foo[0..10]);
29
30 try expect(foo[0] == 'A');
31 try expect(foo[11] == 'A');
32 try expect(foo[19] == 'A');
33}
34
35test "@memmove with both operands single-ptr-to-array, one is null-terminated" {
36 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
40 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
41 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
42 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
43
44 try testMemmoveBothSinglePtrArrayOneIsNullTerminated();
45 try comptime testMemmoveBothSinglePtrArrayOneIsNullTerminated();
46}
47
48fn testMemmoveBothSinglePtrArrayOneIsNullTerminated() !void {
49 var buf: [100]u8 = undefined;
50 const suffix = "hello";
51 @memmove(buf[buf.len - suffix.len ..], suffix);
52 try expect(buf[95] == 'h');
53 try expect(buf[96] == 'e');
54 try expect(buf[97] == 'l');
55 try expect(buf[98] == 'l');
56 try expect(buf[99] == 'o');
57
58 const start = buf.len - suffix.len - 3;
59 const end = start + suffix.len;
60 @memmove(buf[start..end], buf[buf.len - suffix.len ..]);
61 try expect(buf[92] == 'h');
62 try expect(buf[93] == 'e');
63 try expect(buf[94] == 'l');
64 try expect(buf[95] == 'l');
65 try expect(buf[96] == 'o');
66 try expect(buf[97] == 'l');
67 try expect(buf[98] == 'l');
68 try expect(buf[99] == 'o');
69
70 @memmove(buf[start + 2 .. end + 2], buf[start..end]);
71 try expect(buf[92] == 'h');
72 try expect(buf[93] == 'e');
73 try expect(buf[94] == 'h');
74 try expect(buf[95] == 'e');
75 try expect(buf[96] == 'l');
76 try expect(buf[97] == 'l');
77 try expect(buf[98] == 'o');
78 try expect(buf[99] == 'o');
79}
80
81test "@memmove dest many pointer" {
82 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
88 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
89
90 try testMemmoveDestManyPtr();
91 try comptime testMemmoveDestManyPtr();
92}
93
94fn testMemmoveDestManyPtr() !void {
95 var str = "hello".*;
96 var buf: [8]u8 = undefined;
97 var len: usize = 5;
98 _ = &len;
99 @memmove(@as([*]u8, @ptrCast(&buf)), @as([*]const u8, @ptrCast(&str))[0..len]);
100 try expect(buf[0] == 'h');
101 try expect(buf[1] == 'e');
102 try expect(buf[2] == 'l');
103 try expect(buf[3] == 'l');
104 try expect(buf[4] == 'o');
105 @memmove(buf[3..].ptr, buf[0..len]);
106 try expect(buf[0] == 'h');
107 try expect(buf[1] == 'e');
108 try expect(buf[2] == 'l');
109 try expect(buf[3] == 'h');
110 try expect(buf[4] == 'e');
111 try expect(buf[5] == 'l');
112 try expect(buf[6] == 'l');
113 try expect(buf[7] == 'o');
114 @memmove(buf[2..7].ptr, buf[3 .. len + 3]);
115 try expect(buf[0] == 'h');
116 try expect(buf[1] == 'e');
117 try expect(buf[2] == 'h');
118 try expect(buf[3] == 'e');
119 try expect(buf[4] == 'l');
120 try expect(buf[5] == 'l');
121 try expect(buf[6] == 'o');
122 try expect(buf[7] == 'o');
123}
124
125test "@memmove slice" {
126 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
128 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
129 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
130 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
131 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
132 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
133
134 try testMemmoveSlice();
135 try comptime testMemmoveSlice();
136}
137
138fn testMemmoveSlice() !void {
139 var buf: [8]u8 = undefined;
140 const dst1: []u8 = buf[0..5];
141 const dst2: []u8 = buf[3..8];
142 const dst3: []u8 = buf[2..7];
143 const src: []const u8 = "hello";
144 @memmove(dst1, src);
145 try expect(buf[0] == 'h');
146 try expect(buf[1] == 'e');
147 try expect(buf[2] == 'l');
148 try expect(buf[3] == 'l');
149 try expect(buf[4] == 'o');
150 @memmove(dst2, dst1);
151 try expect(buf[0] == 'h');
152 try expect(buf[1] == 'e');
153 try expect(buf[2] == 'l');
154 try expect(buf[3] == 'h');
155 try expect(buf[4] == 'e');
156 try expect(buf[5] == 'l');
157 try expect(buf[6] == 'l');
158 try expect(buf[7] == 'o');
159 @memmove(dst3, dst2);
160 try expect(buf[0] == 'h');
161 try expect(buf[1] == 'e');
162 try expect(buf[2] == 'h');
163 try expect(buf[3] == 'e');
164 try expect(buf[4] == 'l');
165 try expect(buf[5] == 'l');
166 try expect(buf[6] == 'o');
167 try expect(buf[7] == 'o');
168}
169
170comptime {
171 const S = struct {
172 buffer: [8]u8 = undefined,
173 fn set(self: *@This(), items: []const u8) void {
174 @memmove(self.buffer[0..items.len], items);
175 @memmove(self.buffer[3..], self.buffer[0..items.len]);
176 @memmove(self.buffer[2 .. 2 + items.len], self.buffer[3..]);
177 }
178 };
179
180 var s = S{};
181 s.set("hello");
182 if (!std.mem.eql(u8, s.buffer[0..8], "hehelloo")) @compileError("bad");
183}
test/cases/compile_errors/@memmove_type_mismatch.zig created+218
...@@ -0,0 +1,218 @@
1export fn foo() void {
2 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
3 const dest: []u8 = &buf;
4 const src: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
5
6 @memmove(dest, src);
7}
8
9export fn bar() void {
10 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
11 const dest: []u8 = &buf;
12 const src: *align(1) [8]u16 = @ptrCast(&buf);
13
14 @memmove(dest, src);
15}
16
17export fn baz() void {
18 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
19 const dest: []u8 = &buf;
20 const src: [*]align(1) u16 = @ptrCast(&buf);
21
22 @memmove(dest, src);
23}
24
25export fn qux() void {
26 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
27 const dest: *[8]u8 = &buf;
28 const src: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
29
30 @memmove(dest, src);
31}
32
33export fn quux() void {
34 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
35 const dest: *[8]u8 = &buf;
36 const src: *align(1) [8]u16 = @ptrCast(&buf);
37
38 @memmove(dest, src);
39}
40
41export fn quuux() void {
42 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
43 const dest: *[8]u8 = &buf;
44 const src: [*]align(1) u16 = @ptrCast(&buf);
45
46 @memmove(dest, src);
47}
48
49export fn foo2() void {
50 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
51 const dest: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
52 const src: []u8 = &buf;
53
54 @memmove(dest, src);
55}
56
57export fn bar2() void {
58 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
59 const dest: *align(1) [8]u16 = @ptrCast(&buf);
60 const src: []u8 = &buf;
61
62 @memmove(dest, src);
63}
64
65export fn baz2() void {
66 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
67 const dest: [*]align(1) u16 = @ptrCast(&buf);
68 const src: []u8 = &buf;
69
70 @memmove(dest, src);
71}
72
73export fn qux2() void {
74 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
75 const dest: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
76 const src: *[8]u8 = &buf;
77
78 @memmove(dest, src);
79}
80
81export fn quux2() void {
82 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
83 const dest: *align(1) [8]u16 = @ptrCast(&buf);
84 const src: *[8]u8 = &buf;
85
86 @memmove(dest, src);
87}
88
89export fn quuux2() void {
90 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
91 const dest: [*]align(1) u16 = @ptrCast(&buf);
92 const src: *[8]u8 = &buf;
93
94 @memmove(dest, src);
95}
96
97comptime {
98 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
99 const dest: []u8 = &buf;
100 const src: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
101 @memmove(dest, src);
102}
103
104comptime {
105 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
106 const dest: []u8 = &buf;
107 const src: *align(1) [8]u16 = @ptrCast(&buf);
108 @memmove(dest, src);
109}
110
111comptime {
112 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
113 const dest: []u8 = &buf;
114 const src: [*]align(1) u16 = @ptrCast(&buf);
115 @memmove(dest, src);
116}
117
118comptime {
119 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
120 const dest: *[8]u8 = &buf;
121 const src: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
122 @memmove(dest, src);
123}
124
125comptime {
126 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
127 const dest: *[8]u8 = &buf;
128 const src: *align(1) [8]u16 = @ptrCast(&buf);
129 @memmove(dest, src);
130}
131
132comptime {
133 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
134 const dest: *[8]u8 = &buf;
135 const src: [*]align(1) u16 = @ptrCast(&buf);
136 @memmove(dest, src);
137}
138
139comptime {
140 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
141 const dest: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
142 const src: []u8 = &buf;
143 @memmove(dest, src);
144}
145
146comptime {
147 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
148 const dest: *align(1) [8]u16 = @ptrCast(&buf);
149 const src: []u8 = &buf;
150 @memmove(dest, src);
151}
152
153comptime {
154 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
155 const dest: [*]align(1) u16 = @ptrCast(&buf);
156 const src: []u8 = &buf;
157 @memmove(dest, src);
158}
159
160comptime {
161 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
162 const dest: []align(1) u16 = @as([*]align(1) u16, @ptrCast(&buf))[0..4];
163 const src: *[8]u8 = &buf;
164 @memmove(dest, src);
165}
166
167comptime {
168 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
169 const dest: *align(1) [8]u16 = @ptrCast(&buf);
170 const src: *[8]u8 = &buf;
171 @memmove(dest, src);
172}
173
174comptime {
175 var buf: [8]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7 };
176 const dest: [*]align(1) u16 = @ptrCast(&buf);
177 const src: *[8]u8 = &buf;
178 @memmove(dest, src);
179}
180
181// error
182//
183// :6:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
184// :6:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
185// :14:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
186// :14:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
187// :22:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
188// :22:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
189// :30:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
190// :30:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
191// :38:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
192// :38:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
193// :46:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
194// :46:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
195// :54:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
196// :62:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
197// :70:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
198// :78:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
199// :86:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
200// :94:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
201// :101:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
202// :101:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
203// :108:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
204// :108:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
205// :115:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
206// :115:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
207// :122:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
208// :122:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
209// :129:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
210// :129:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
211// :136:5: error: pointer element type 'u16' cannot coerce into element type 'u8'
212// :136:5: note: unsigned 8-bit int cannot represent all possible unsigned 16-bit values
213// :143:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
214// :150:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
215// :157:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
216// :164:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
217// :171:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
218// :178:5: error: pointer element type 'u8' cannot coerce into element type 'u16'
test/cases/compile_errors/comptime_var_referenced_at_runtime.zig+11
...@@ -63,6 +63,14 @@ export fn far() void {...@@ -63,6 +63,14 @@ export fn far() void {
63 @memset(&rt, elem);63 @memset(&rt, elem);
64}64}
6565
66export fn bax() void {
67 comptime var x: [2]u32 = undefined;
68 x = .{ 1, 2 };
69
70 var rt: [2]u32 = undefined;
71 @memmove(&rt, &x);
72}
73
66// error74// error
67//75//
68// :5:19: error: runtime value contains reference to comptime var76// :5:19: error: runtime value contains reference to comptime var
...@@ -92,3 +100,6 @@ export fn far() void {...@@ -92,3 +100,6 @@ export fn far() void {
92// :63:18: error: runtime value contains reference to comptime var100// :63:18: error: runtime value contains reference to comptime var
93// :63:18: note: comptime var pointers are not available at runtime101// :63:18: note: comptime var pointers are not available at runtime
94// :59:27: note: 'runtime_value' points to comptime var declared here102// :59:27: note: 'runtime_value' points to comptime var declared here
103// :71:19: error: runtime value contains reference to comptime var
104// :71:19: note: comptime var pointers are not available at runtime
105// :67:30: note: 'runtime_value' points to comptime var declared here
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig+43-1
...@@ -28,10 +28,39 @@ pub export fn memcpy_const_dest_ptr() void {...@@ -28,10 +28,39 @@ pub export fn memcpy_const_dest_ptr() void {
28 var buf2: [5]u8 = .{ 1, 2, 3, 4, 5 };28 var buf2: [5]u8 = .{ 1, 2, 3, 4, 5 };
29 @memcpy(&buf1, &buf2);29 @memcpy(&buf1, &buf2);
30}30}
31pub export fn memset_array() void {31pub export fn memcpy_array() void {
32 const buf: [5]u8 = .{ 1, 2, 3, 4, 5 };32 const buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
33 @memcpy(buf, 1);33 @memcpy(buf, 1);
34}34}
35pub export fn entry_memmove() void {
36 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
37 const slice: []u8 = &buf;
38 const a: u32 = 1234;
39 @memmove(slice.ptr, @as([*]const u8, @ptrCast(&a)));
40}
41pub export fn entry1_memmove() void {
42 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
43 const ptr: *u8 = &buf[0];
44 @memmove(ptr, 0);
45}
46pub export fn non_matching_lengths_memmove() void {
47 var buf1: [5]u8 = .{ 1, 2, 3, 4, 5 };
48 var buf2: [6]u8 = .{ 1, 2, 3, 4, 5, 6 };
49 @memmove(&buf2, &buf1);
50}
51pub export fn memcpy_const_dest_ptr_memmove() void {
52 const buf1: [5]u8 = .{ 1, 2, 3, 4, 5 };
53 var buf2: [5]u8 = .{ 1, 2, 3, 4, 5 };
54 @memmove(&buf1, &buf2);
55}
56pub export fn memmove_array() void {
57 const buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
58 @memmove(buf, 1);
59}
60pub export fn memset_array() void {
61 const buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
62 @memset(buf, 1);
63}
3564
36// error65// error
37// backend=stage266// backend=stage2
...@@ -51,3 +80,16 @@ pub export fn memset_array() void {...@@ -51,3 +80,16 @@ pub export fn memset_array() void {
51// :29:13: error: cannot memcpy to constant pointer80// :29:13: error: cannot memcpy to constant pointer
52// :33:13: error: type '[5]u8' is not an indexable pointer81// :33:13: error: type '[5]u8' is not an indexable pointer
53// :33:13: note: operand must be a slice, a many pointer or a pointer to an array82// :33:13: note: operand must be a slice, a many pointer or a pointer to an array
83// :39:5: error: unknown @memmove length
84// :39:19: note: destination type '[*]u8' provides no length
85// :39:25: note: source type '[*]const u8' provides no length
86// :44:14: error: type '*u8' is not an indexable pointer
87// :44:14: note: operand must be a slice, a many pointer or a pointer to an array
88// :49:5: error: non-matching @memmove lengths
89// :49:14: note: length 6 here
90// :49:21: note: length 5 here
91// :54:14: error: cannot memmove to constant pointer
92// :58:14: error: type '[5]u8' is not an indexable pointer
93// :58:14: note: operand must be a slice, a many pointer or a pointer to an array
94// :62:13: error: type '[5]u8' is not an indexable pointer
95// :62:13: note: operand must be a slice, a many pointer or a pointer to an array
test/cases/safety/memmove_len_mismatch.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, "@memmove 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 _ = &len;
14 @memmove(buffer[0..len], buffer[len .. len + 4]);
15 return error.TestFailed;
16}
17// run
18// backend=llvm
19// target=native
test/standalone/zerolength_check/src/main.zig+1
...@@ -5,6 +5,7 @@ test {...@@ -5,6 +5,7 @@ test {
5 const source = foo();5 const source = foo();
66
7 @memcpy(dest, source);7 @memcpy(dest, source);
8 @memmove(dest, source);
8 @memset(dest, 4);9 @memset(dest, 4);
9 @memset(dest, undefined);10 @memset(dest, undefined);
1011