master
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4const assert = std.debug.assert;
5
6test "memcpy and memset intrinsics" {
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10
11 try testMemcpyMemset();
12 try comptime testMemcpyMemset();
13}
14
15fn testMemcpyMemset() !void {
16 var foo: [20]u8 = undefined;
17 var bar: [20]u8 = undefined;
18
19 @memset(&foo, 'A');
20 @memcpy(&bar, &foo);
21
22 try expect(bar[0] == 'A');
23 try expect(bar[11] == 'A');
24 try expect(bar[19] == 'A');
25}
26
27test "@memcpy with both operands single-ptr-to-array, one is null-terminated" {
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
31
32 try testMemcpyBothSinglePtrArrayOneIsNullTerminated();
33 try comptime testMemcpyBothSinglePtrArrayOneIsNullTerminated();
34}
35
36fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void {
37 var buf: [100]u8 = undefined;
38 const suffix = "hello";
39 @memcpy(buf[buf.len - suffix.len ..], suffix);
40 try expect(buf[95] == 'h');
41 try expect(buf[96] == 'e');
42 try expect(buf[97] == 'l');
43 try expect(buf[98] == 'l');
44 try expect(buf[99] == 'o');
45}
46
47test "@memcpy dest many pointer" {
48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
50 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
51
52 try testMemcpyDestManyPtr();
53 try comptime testMemcpyDestManyPtr();
54}
55
56fn testMemcpyDestManyPtr() !void {
57 var str = "hello".*;
58 var buf: [5]u8 = undefined;
59 var len: usize = 5;
60 _ = &len;
61 @memcpy(@as([*]u8, @ptrCast(&buf)), @as([*]const u8, @ptrCast(&str))[0..len]);
62 try expect(buf[0] == 'h');
63 try expect(buf[1] == 'e');
64 try expect(buf[2] == 'l');
65 try expect(buf[3] == 'l');
66 try expect(buf[4] == 'o');
67}
68
69test "@memcpy C pointer" {
70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
72 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
73
74 try testMemcpyCPointer();
75 try comptime testMemcpyCPointer();
76}
77
78fn testMemcpyCPointer() !void {
79 const src = "hello";
80 var buf: [5]u8 = undefined;
81 @memcpy(@as([*c]u8, &buf), src);
82 try expect(buf[0] == 'h');
83 try expect(buf[1] == 'e');
84 try expect(buf[2] == 'l');
85 try expect(buf[3] == 'l');
86 try expect(buf[4] == 'o');
87}
88
89test "@memcpy slice" {
90 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
91 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
92 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
93 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
94
95 try testMemcpySlice();
96 try comptime testMemcpySlice();
97}
98
99fn testMemcpySlice() !void {
100 var buf: [5]u8 = undefined;
101 const dst: []u8 = &buf;
102 const src: []const u8 = "hello";
103 @memcpy(dst, src);
104 try expect(buf[0] == 'h');
105 try expect(buf[1] == 'e');
106 try expect(buf[2] == 'l');
107 try expect(buf[3] == 'l');
108 try expect(buf[4] == 'o');
109}
110
111comptime {
112 const S = struct {
113 buffer: [8]u8 = undefined,
114 fn set(self: *@This(), items: []const u8) void {
115 @memcpy(self.buffer[0..items.len], items);
116 }
117 };
118
119 var s = S{};
120 s.set("hello");
121 if (!std.mem.eql(u8, s.buffer[0..5], "hello")) @compileError("bad");
122}
123
124test "@memcpy comptime-only type" {
125 const in: [4]type = .{ u8, u16, u32, u64 };
126 comptime var out: [4]type = undefined;
127 @memcpy(&out, &in);
128
129 comptime assert(out[0] == u8);
130 comptime assert(out[1] == u16);
131 comptime assert(out[2] == u32);
132 comptime assert(out[3] == u64);
133}
134
135test "@memcpy zero-bit type with aliasing" {
136 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
137
138 const S = struct {
139 fn doTheTest() void {
140 var buf: [3]void = @splat({});
141 const slice: []void = &buf;
142 // These two pointers are the same, but it's still not considered aliasing because
143 // the input and output slices both correspond to zero bits of memory.
144 @memcpy(slice, slice);
145 comptime assert(buf[0] == {});
146 comptime assert(buf[1] == {});
147 comptime assert(buf[2] == {});
148 }
149 };
150 S.doTheTest();
151 comptime S.doTheTest();
152}
153
154test "@memcpy with sentinel" {
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
156 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157
158 const S = struct {
159 fn doTheTest() void {
160 const field = @typeInfo(struct { a: u32 }).@"struct".fields[0];
161 var buffer: [field.name.len]u8 = undefined;
162 @memcpy(&buffer, field.name);
163 }
164 };
165
166 S.doTheTest();
167 comptime S.doTheTest();
168}
169
170test "@memcpy no sentinel source into sentinel destination" {
171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
172
173 const S = struct {
174 fn doTheTest() void {
175 const src: []const u8 = &.{ 1, 2, 3 };
176 comptime var dest_buf: [3:0]u8 = @splat(0);
177 const dest: [:0]u8 = &dest_buf;
178 @memcpy(dest, src);
179 }
180 };
181
182 S.doTheTest();
183 comptime S.doTheTest();
184}