1const builtin = @import("builtin");
2const std = @import("std");
3const testing = std.testing;
4const assert = std.debug.assert;
5const expect = testing.expect;
6const expectError = testing.expectError;
7
8test "dereference pointer" {
9 try comptime testDerefPtr();
10 try testDerefPtr();
11}
12
13fn testDerefPtr() !void {
14 var x: i32 = 1234;
15 const y = &x;
16 y.* += 1;
17 try expect(x == 1235);
18}
19
20test "pointer-integer arithmetic" {
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
24
25 var ptr: [*]const u8 = "abcd";
26
27 try expect(ptr[0] == 'a');
28 ptr += 1;
29 try expect(ptr[0] == 'b');
30 ptr += 1;
31 try expect(ptr[0] == 'c');
32 ptr += 1;
33 try expect(ptr[0] == 'd');
34 ptr += 1;
35 try expect(ptr[0] == 0);
36 ptr -= 1;
37 try expect(ptr[0] == 'd');
38 ptr -= 1;
39 try expect(ptr[0] == 'c');
40 ptr -= 1;
41 try expect(ptr[0] == 'b');
42 ptr -= 1;
43 try expect(ptr[0] == 'a');
44}
45
46test "pointer subtraction" {
47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
49
50 {
51 const a: *u8 = @ptrFromInt(100);
52 const b: *u8 = @ptrFromInt(50);
53 try expect(a - b == 50);
54 }
55 {
56 var ptr: [*]const u8 = "abc";
57 try expect(&ptr[1] - &ptr[0] == 1);
58 try expect(&ptr[2] - &ptr[0] == 2);
59 }
60 {
61 const a: *[100]u16 = @ptrFromInt(100);
62 const b: *[100]u16 = @ptrFromInt(50);
63 try expect(a - b == 25);
64 }
65 {
66 var x: struct { a: u32, b: u32 } = undefined;
67 const a = &x.a;
68 const b = &x.b;
69 try expect(a - a == 0);
70 try expect(b - b == 0);
71 try expect(b - a == 1);
72 }
73 comptime {
74 var x: packed struct { a: u1, b: u1 } = undefined;
75 const a = &x.a;
76 const b = &x.b;
77 try expect(a - a == 0);
78 try expect(b - b == 0);
79 try expect(b - a == 0);
80 }
81 comptime {
82 var x: extern struct { a: u32, b: u32 } = undefined;
83 const a = &x.a;
84 const b = &x.b;
85 try expect(a - a == 0);
86 try expect(b - b == 0);
87 try expect(b - a == 1);
88 }
89 comptime {
90 const a: *const [3]u8 = "abc";
91 const b: [*]const u8 = @ptrCast(a);
92 try expect(&a[1] - &b[0] == 1);
93 }
94 comptime {
95 var x: [64][64]u8 = undefined;
96 const a = &x[0][12];
97 const b = &x[15][3];
98 try expect(b - a == 951);
99 }
100}
101
102test "pointer arithmetic with non-trivial RHS" {
103 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
104
105 var t: bool = undefined;
106 t = true;
107
108 var ptr: [*]const u8 = "Hello, World!";
109 ptr += if (t) 5 else 2;
110 try expect(ptr[0] == ',');
111 ptr += if (!t) 4 else 2;
112 try expect(ptr[0] == 'W');
113 ptr -= if (t) @as(usize, 6) else 3;
114 try expect(ptr[0] == 'e');
115 ptr -= if (!t) @as(usize, 0) else 1;
116 try expect(ptr[0] == 'H');
117}
118
119test "double pointer parsing" {
120 comptime assert(PtrOf(PtrOf(i32)) == **i32);
121}
122
123fn PtrOf(comptime T: type) type {
124 return *T;
125}
126
127test "implicit cast single item pointer to C pointer and back" {
128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
129 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
130
131 var y: u8 = 11;
132 const x: [*c]u8 = &y;
133 const z: *u8 = x;
134 z.* += 1;
135 try expect(y == 12);
136}
137
138test "initialize const optional C pointer to null" {
139 const a: ?[*c]i32 = null;
140 try expect(a == null);
141 comptime assert(a == null);
142}
143
144test "assigning integer to C pointer" {
145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
147 var x: i32 = 0;
148 var y: i32 = 1;
149 var ptr: [*c]u8 = 0;
150 var ptr2: [*c]u8 = x;
151 var ptr3: [*c]u8 = 1;
152 var ptr4: [*c]u8 = y;
153 _ = .{ &x, &y, &ptr, &ptr2, &ptr3, &ptr4 };
154
155 try expect(ptr == ptr2);
156 try expect(ptr3 == ptr4);
157 try expect(ptr3 > ptr and ptr4 > ptr2 and y > x);
158 try expect(1 > ptr and y > ptr2 and 0 < ptr3 and x < ptr4);
159}
160
161test "C pointer comparison and arithmetic" {
162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
164
165 const S = struct {
166 fn doTheTest() !void {
167 var ptr1: [*c]u32 = 0;
168 var ptr2 = ptr1 + 10;
169 _ = &ptr1;
170 try expect(ptr1 == 0);
171 try expect(ptr1 >= 0);
172 try expect(ptr1 <= 0);
173 // expect(ptr1 < 1);
174 // expect(ptr1 < one);
175 // expect(1 > ptr1);
176 // expect(one > ptr1);
177 try expect(ptr1 < ptr2);
178 try expect(ptr2 > ptr1);
179 try expect(ptr2 >= 40);
180 try expect(ptr2 == 40);
181 try expect(ptr2 <= 40);
182 ptr2 -= 10;
183 try expect(ptr1 == ptr2);
184 }
185 };
186 try S.doTheTest();
187 try comptime S.doTheTest();
188}
189
190test "dereference pointer again" {
191 try testDerefPtrOneVal();
192 try comptime testDerefPtrOneVal();
193}
194
195const Foo1 = struct {
196 x: void,
197};
198
199fn testDerefPtrOneVal() !void {
200 // Foo1 satisfies the OnePossibleValueYes criteria
201 const x = &Foo1{ .x = {} };
202 const y = x.*;
203 try expect(@TypeOf(y.x) == void);
204}
205
206test "peer type resolution with C pointers" {
207 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
208
209 const ptr_one: *u8 = undefined;
210 const ptr_many: [*]u8 = undefined;
211 const ptr_c: [*c]u8 = undefined;
212 var t = true;
213 _ = &t;
214 const x1 = if (t) ptr_one else ptr_c;
215 const x2 = if (t) ptr_many else ptr_c;
216 const x3 = if (t) ptr_c else ptr_one;
217 const x4 = if (t) ptr_c else ptr_many;
218 try expect(@TypeOf(x1) == [*c]u8);
219 try expect(@TypeOf(x2) == [*c]u8);
220 try expect(@TypeOf(x3) == [*c]u8);
221 try expect(@TypeOf(x4) == [*c]u8);
222}
223
224test "peer type resolution with C pointer and const pointer" {
225 var ptr_c: [*c]u8 = undefined;
226 var ptr_const: *const u8 = &undefined;
227 _ = .{ &ptr_c, &ptr_const };
228 try expect(@TypeOf(ptr_c, ptr_const) == [*c]const u8);
229}
230
231test "implicit casting between C pointer and optional non-C pointer" {
232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
235 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
236
237 var slice: []const u8 = "aoeu";
238 _ = &slice;
239 const opt_many_ptr: ?[*]const u8 = slice.ptr;
240 var ptr_opt_many_ptr = &opt_many_ptr;
241 const c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
242 try expect(c_ptr.*.* == 'a');
243 ptr_opt_many_ptr = c_ptr;
244 try expect(ptr_opt_many_ptr.*.?[1] == 'o');
245}
246
247test "implicit cast error unions with non-optional to optional pointer" {
248 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
249 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
250 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
252
253 const S = struct {
254 fn doTheTest() !void {
255 try expectError(error.Fail, foo());
256 }
257 fn foo() anyerror!?*u8 {
258 return bar() orelse error.Fail;
259 }
260 fn bar() ?*u8 {
261 return null;
262 }
263 };
264 try S.doTheTest();
265 try comptime S.doTheTest();
266}
267
268test "compare equality of optional and non-optional pointer" {
269 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
270
271 const a = @as(*const usize, @ptrFromInt(0x12345678));
272 const b = @as(?*usize, @ptrFromInt(0x12345678));
273 try expect(a == b);
274 try expect(b == a);
275}
276
277test "allowzero pointer and slice" {
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
280 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
281 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
282
283 var ptr: [*]allowzero i32 = @ptrFromInt(0);
284 const opt_ptr: ?[*]allowzero i32 = ptr;
285 try expect(opt_ptr != null);
286 try expect(@intFromPtr(ptr) == 0);
287 var runtime_zero: usize = 0;
288 _ = &runtime_zero;
289 var slice = ptr[runtime_zero..10];
290 comptime assert(@TypeOf(slice) == []allowzero i32);
291 try expect(@intFromPtr(&slice[5]) == 20);
292
293 comptime assert(@typeInfo(@TypeOf(ptr)).pointer.attrs.@"allowzero");
294 comptime assert(@typeInfo(@TypeOf(slice)).pointer.attrs.@"allowzero");
295}
296
297test "assign null directly to C pointer and test null equality" {
298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
299 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
300 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
301
302 var x: [*c]i32 = null;
303 _ = &x;
304 try expect(x == null);
305 try expect(null == x);
306 try expect(!(x != null));
307 try expect(!(null != x));
308 if (x) |same_x| {
309 _ = same_x;
310 @panic("fail");
311 }
312 var otherx: i32 = undefined;
313 try expect((x orelse &otherx) == &otherx);
314
315 const y: [*c]i32 = null;
316 comptime assert(y == null);
317 comptime assert(null == y);
318 comptime assert(!(y != null));
319 comptime assert(!(null != y));
320 if (y) |same_y| {
321 _ = same_y;
322 @panic("fail");
323 }
324 const othery: i32 = undefined;
325 const ptr_othery = &othery;
326 comptime assert((y orelse ptr_othery) == ptr_othery);
327
328 var n: i32 = 1234;
329 const x1: [*c]i32 = &n;
330 try expect(!(x1 == null));
331 try expect(!(null == x1));
332 try expect(x1 != null);
333 try expect(null != x1);
334 try expect(x1.?.* == 1234);
335 if (x1) |same_x1| {
336 try expect(same_x1.* == 1234);
337 } else {
338 @panic("fail");
339 }
340 try expect((x1 orelse &otherx) == x1);
341
342 const nc: i32 = 1234;
343 const y1: [*c]const i32 = &nc;
344 comptime assert(!(y1 == null));
345 comptime assert(!(null == y1));
346 comptime assert(y1 != null);
347 comptime assert(null != y1);
348 comptime assert(y1.?.* == 1234);
349 if (y1) |same_y1| {
350 try expect(same_y1.* == 1234);
351 } else {
352 @compileError("fail");
353 }
354 comptime assert((y1 orelse &othery) == y1);
355}
356
357test "array initialization types" {
358 const E = enum { A, B, C };
359 try expect(@TypeOf([_]u8{}) == [0]u8);
360 try expect(@TypeOf([_:0]u8{}) == [0:0]u8);
361 try expect(@TypeOf([_:.A]E{}) == [0:.A]E);
362 try expect(@TypeOf([_:0]u8{ 1, 2, 3 }) == [3:0]u8);
363}
364
365test "null terminated pointer" {
366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
367 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
368
369 const S = struct {
370 fn doTheTest() !void {
371 var array_with_zero = [_:0]u8{ 'h', 'e', 'l', 'l', 'o' };
372 const zero_ptr: [*:0]const u8 = @ptrCast(&array_with_zero);
373 const no_zero_ptr: [*]const u8 = zero_ptr;
374 const zero_ptr_again: [*:0]const u8 = @ptrCast(no_zero_ptr);
375 try expect(std.mem.eql(u8, std.mem.sliceTo(zero_ptr_again, 0), "hello"));
376 }
377 };
378 try S.doTheTest();
379 try comptime S.doTheTest();
380}
381
382test "allow any sentinel" {
383 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
384 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
385 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
386
387 const S = struct {
388 fn doTheTest() !void {
389 var array = [_:std.math.minInt(i32)]i32{ 1, 2, 3, 4 };
390 const ptr: [*:std.math.minInt(i32)]i32 = &array;
391 try expect(ptr[4] == std.math.minInt(i32));
392 }
393 };
394 try S.doTheTest();
395 try comptime S.doTheTest();
396}
397
398test "pointer sentinel with enums" {
399 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
400 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
401 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
402
403 const S = struct {
404 const Number = enum {
405 one,
406 two,
407 sentinel,
408 };
409
410 fn doTheTest() !void {
411 var ptr: [*:.sentinel]const Number = &[_:.sentinel]Number{ .one, .two, .two, .one };
412 _ = &ptr;
413 try expect(ptr[4] == .sentinel); // TODO this should be comptime assert, see #3731
414 }
415 };
416 try S.doTheTest();
417 try comptime S.doTheTest();
418}
419
420test "pointer sentinel with optional element" {
421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
422 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
423 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
424 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
425
426 const S = struct {
427 fn doTheTest() !void {
428 var ptr: [*:null]const ?i32 = &[_:null]?i32{ 1, 2, 3, 4 };
429 _ = &ptr;
430 try expect(ptr[4] == null); // TODO this should be comptime assert, see #3731
431 }
432 };
433 try S.doTheTest();
434 try comptime S.doTheTest();
435}
436
437test "pointer sentinel with +inf" {
438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
439 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
440 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
441 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
442
443 const S = struct {
444 fn doTheTest() !void {
445 const inf_f32 = comptime std.math.inf(f32);
446 var ptr: [*:inf_f32]const f32 = &[_:inf_f32]f32{ 1.1, 2.2, 3.3, 4.4 };
447 _ = &ptr;
448 try expect(ptr[4] == inf_f32); // TODO this should be comptime assert, see #3731
449 }
450 };
451 try S.doTheTest();
452 try comptime S.doTheTest();
453}
454
455test "pointer to array at fixed address" {
456 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
457
458 const array = @as(*volatile [2]u32, @ptrFromInt(0x10));
459 // Silly check just to reference `array`
460 try expect(@intFromPtr(&array[0]) == 0x10);
461 try expect(@intFromPtr(&array[1]) == 0x14);
462}
463
464test "pointer-integer arithmetic affects the alignment" {
465 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
466
467 {
468 var ptr: [*]align(8) u32 = undefined;
469 var x: usize = 1;
470 _ = .{ &ptr, &x };
471
472 try expect(@typeInfo(@TypeOf(ptr)).pointer.attrs.@"align" == 8);
473 const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4
474 try expect(@typeInfo(@TypeOf(ptr1)).pointer.attrs.@"align" == 4);
475 const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8
476 try expect(@typeInfo(@TypeOf(ptr2)).pointer.attrs.@"align" == 8);
477 const ptr3 = ptr + 0; // no-op
478 try expect(@typeInfo(@TypeOf(ptr3)).pointer.attrs.@"align" == 8);
479 const ptr4 = ptr + x; // runtime-known addend
480 try expect(@typeInfo(@TypeOf(ptr4)).pointer.attrs.@"align" == 4);
481 }
482 {
483 var ptr: [*]align(8) [3]u8 = undefined;
484 var x: usize = 1;
485 _ = .{ &ptr, &x };
486
487 const ptr1 = ptr + 17; // 3 * 17 = 51
488 try expect(@typeInfo(@TypeOf(ptr1)).pointer.attrs.@"align" == 1);
489 const ptr2 = ptr + x; // runtime-known addend
490 try expect(@typeInfo(@TypeOf(ptr2)).pointer.attrs.@"align" == 1);
491 const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8
492 try expect(@typeInfo(@TypeOf(ptr3)).pointer.attrs.@"align" == 8);
493 const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4
494 try expect(@typeInfo(@TypeOf(ptr4)).pointer.attrs.@"align" == 4);
495 }
496}
497
498test "@intFromPtr on null optional at comptime" {
499 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
500
501 {
502 const pointer = @as(?*u8, @ptrFromInt(0x000));
503 const x = @intFromPtr(pointer);
504 _ = x;
505 comptime assert(0 == @intFromPtr(pointer));
506 }
507 {
508 const pointer = @as(?*u8, @ptrFromInt(0xf00));
509 comptime assert(0xf00 == @intFromPtr(pointer));
510 }
511}
512
513test "indexing array with sentinel returns correct type" {
514 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
517
518 var s: [:0]const u8 = "abc";
519 try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
520}
521
522test "element pointer to slice" {
523 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
525
526 const S = struct {
527 fn doTheTest() !void {
528 var cases: [2][2]i32 = [_][2]i32{
529 [_]i32{ 0, 1 },
530 [_]i32{ 2, 3 },
531 };
532
533 const items: []i32 = &cases[0]; // *[2]i32
534 try testing.expect(items.len == 2);
535 try testing.expect(items[1] == 1);
536 try testing.expect(items[0] == 0);
537 }
538 };
539
540 try S.doTheTest();
541 try comptime S.doTheTest();
542}
543
544test "element pointer arithmetic to slice" {
545 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
546 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
547
548 const S = struct {
549 fn doTheTest() !void {
550 var cases: [2][2]i32 = [_][2]i32{
551 [_]i32{ 0, 1 },
552 [_]i32{ 2, 3 },
553 };
554
555 const elem_ptr = &cases[0]; // *[2]i32
556 const many = @as([*][2]i32, @ptrCast(elem_ptr));
557 const many_elem = @as(*[2]i32, @ptrCast(&many[1]));
558 const items: []i32 = many_elem;
559 try testing.expect(items.len == 2);
560 try testing.expect(items[1] == 3);
561 try testing.expect(items[0] == 2);
562 }
563 };
564
565 try S.doTheTest();
566 try comptime S.doTheTest();
567}
568
569test "array slicing to slice" {
570 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
571 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
572
573 const S = struct {
574 fn doTheTest() !void {
575 var str: [5]i32 = [_]i32{ 1, 2, 3, 4, 5 };
576 const sub: *[2]i32 = str[1..3];
577 const slice: []i32 = sub; // used to cause failures
578 try testing.expect(slice.len == 2);
579 try testing.expect(slice[0] == 2);
580 }
581 };
582
583 try S.doTheTest();
584 try comptime S.doTheTest();
585}
586
587test "pointer to constant decl preserves alignment" {
588 const S = struct {
589 a: u8,
590 b: u8,
591 const aligned align(8) = @This(){ .a = 3, .b = 4 };
592 };
593
594 const alignment = @typeInfo(@TypeOf(&S.aligned)).pointer.attrs.@"align";
595 try std.testing.expect(alignment == 8);
596}
597
598test "ptrCast comptime known slice to C pointer" {
599 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
600 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
601 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
602
603 const s: [:0]const u8 = "foo";
604 var p: [*c]const u8 = @ptrCast(s);
605 _ = &p;
606 try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0));
607}
608
609test "pointer alignment and element type include call expression" {
610 const S = struct {
611 fn T() type {
612 return struct { _: i32 };
613 }
614 const P = *align(@alignOf(T())) [@sizeOf(T())]u8;
615 };
616 try expect(@alignOf(S.P) > 0);
617}
618
619test "pointer to array has explicit alignment" {
620 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
621
622 const S = struct {
623 const Base = extern struct { a: u8 };
624 const Base2 = extern struct { a: u8 };
625 fn func(ptr: *[4]Base) *align(1) [4]Base2 {
626 return @alignCast(@as(*[4]Base2, @ptrCast(ptr)));
627 }
628 };
629 var bases: [4]S.Base = @splat(.{ .a = 2 });
630 const casted = S.func(&bases);
631 try expect(casted[0].a == 2);
632}
633
634test "result type preserved through multiple references" {
635 const S = struct { x: u32 };
636 var my_u64: u64 = 12345;
637 _ = &my_u64;
638 const foo: *const *const *const S = &&&.{
639 .x = @intCast(my_u64),
640 };
641 try expect(foo.*.*.*.x == 12345);
642}
643
644test "result type found through optional pointer" {
645 const ptr1: ?*const u32 = &@intCast(123);
646 const ptr2: ?[]const u8 = &.{ @intCast(123), @truncate(0xABCD) };
647 try expect(ptr1.?.* == 123);
648 try expect(ptr2.?.len == 2);
649 try expect(ptr2.?[0] == 123);
650 try expect(ptr2.?[1] == 0xCD);
651}
652
653const Box0 = struct {
654 items: [4]Item,
655
656 const Item = struct {
657 num: u32,
658 };
659};
660const Box1 = struct {
661 items: [4]Item,
662
663 const Item = struct {};
664};
665const Box2 = struct {
666 items: [4]Item,
667
668 const Item = struct {
669 nothing: void,
670 };
671};
672
673fn mutable() !void {
674 var box0: Box0 = .{ .items = undefined };
675 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).pointer.attrs.@"const" == false);
676
677 var box1: Box1 = .{ .items = undefined };
678 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).pointer.attrs.@"const" == false);
679
680 var box2: Box2 = .{ .items = undefined };
681 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).pointer.attrs.@"const" == false);
682}
683
684fn constant() !void {
685 const box0: Box0 = .{ .items = undefined };
686 try std.testing.expect(@typeInfo(@TypeOf(box0.items[0..])).pointer.attrs.@"const" == true);
687
688 const box1: Box1 = .{ .items = undefined };
689 try std.testing.expect(@typeInfo(@TypeOf(box1.items[0..])).pointer.attrs.@"const" == true);
690
691 const box2: Box2 = .{ .items = undefined };
692 try std.testing.expect(@typeInfo(@TypeOf(box2.items[0..])).pointer.attrs.@"const" == true);
693}
694
695test "pointer-to-array constness for zero-size elements, var" {
696 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
697 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
698 try mutable();
699 try comptime mutable();
700}
701
702test "pointer-to-array constness for zero-size elements, const" {
703 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
704 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
705
706 try constant();
707 try comptime constant();
708}
709
710test "cast pointers with zero sized elements" {
711 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
712
713 const a: *void = undefined;
714 const b: *[1]void = a;
715 _ = b;
716 const c: *[0]u8 = undefined;
717 const d: []u8 = c;
718 _ = d;
719}
720
721test "comptime pointer equality through distinct fields with well-defined layout" {
722 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
723
724 const A = extern struct {
725 x: u32,
726 z: u16,
727 };
728 const B = extern struct {
729 x: u16,
730 y: u16,
731 z: u16,
732 };
733
734 const a: A = .{
735 .x = undefined,
736 .z = 123,
737 };
738
739 const ap: *const A = &a;
740 const bp: *const B = @ptrCast(ap);
741
742 comptime assert(&ap.z == &bp.z);
743 comptime assert(ap.z == 123);
744 comptime assert(bp.z == 123);
745}
746
747test "comptime pointer equality through distinct elements with well-defined layout" {
748 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
749
750 const buf: [2]u32 = .{ 123, 456 };
751
752 const ptr: *const [2]u32 = &buf;
753 const byte_ptr: *align(4) const [8]u8 = @ptrCast(ptr);
754 const second_elem: *const u32 = @ptrCast(byte_ptr[4..8]);
755
756 comptime assert(&buf[1] == second_elem);
757 comptime assert(buf[1] == 456);
758 comptime assert(second_elem.* == 456);
759}
760
761test "pointers to elements of slice of zero-bit type" {
762 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
763
764 var slice: []const u0 = undefined;
765 slice = &.{ 0, 0 };
766
767 const a = &slice[0];
768 const b = &slice[1];
769
770 try expect(a == b);
771}
772
773test "pointers to elements of many-ptr to zero-bit type" {
774 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
775
776 var many_ptr: [*]const u0 = undefined;
777 many_ptr = &.{ 0, 0 };
778
779 const a = &many_ptr[0];
780 const b = &many_ptr[1];
781
782 try expect(a == b);
783}
784
785test "comptime C pointer to optional pointer" {
786 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
787
788 const opt: ?*u8 = @ptrFromInt(0x1000);
789 const outer_ptr: [*c]const ?*u8 = &opt;
790 const inner_ptr = &outer_ptr.*.?;
791 comptime assert(@TypeOf(inner_ptr) == *const *u8);
792 comptime assert(@intFromPtr(inner_ptr.*) == 0x1000);
793}