authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-06-17 12:11:35+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-06-24 10:20:56+01:00
log2fcac141e75598dc0edd357b55c35d468b506672
treebdda10f0253587ba97ef9e8673f59fae7fd53e70
parent2e0524954405e05d8b2bfa4a15c293f26a4a080d
signaturelock-open Commit is signed but in an unrecognized format.

tests: update for new `@bitCast` semantics


16 files changed, 253 insertions(+), 285 deletions(-)

doc/langref/test_packed_structs.zig+2-10
...@@ -26,16 +26,8 @@ fn doTheTest() !void {...@@ -26,16 +26,8 @@ fn doTheTest() !void {
26 try expectEqual(0x1, divided.quarter4);26 try expectEqual(0x1, divided.quarter4);
2727
28 const ordered: [2]u8 = @bitCast(full);28 const ordered: [2]u8 = @bitCast(full);
29 switch (native_endian) {29 try expectEqual(0x34, ordered[0]);
30 .big => {30 try expectEqual(0x12, ordered[1]);
31 try expectEqual(0x12, ordered[0]);
32 try expectEqual(0x34, ordered[1]);
33 },
34 .little => {
35 try expectEqual(0x34, ordered[0]);
36 try expectEqual(0x12, ordered[1]);
37 },
38 }
39}31}
4032
41// test33// test
doc/langref/test_pointer_casting.zig+12-8
...@@ -1,18 +1,22 @@...@@ -1,18 +1,22 @@
1const std = @import("std");1const std = @import("std");
2const native_endian = @import("builtin").target.cpu.arch.endian();
2const expectEqual = std.testing.expectEqual;3const expectEqual = std.testing.expectEqual;
34
4test "pointer casting" {5test "pointer casting" {
5 const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 };6 const bytes: [4]u8 align(@alignOf(u32)) = .{ 0x10, 0x20, 0x30, 0x40 };
6 const u32_ptr: *const u32 = @ptrCast(&bytes);7 const u32_ptr: *const u32 = @ptrCast(&bytes);
7 try expectEqual(0x12121212, u32_ptr.*);
88
9 // Even this example is contrived - there are better ways to do the above than9 // Because we directly reinterpreted bytes of memory, the `u32` value we
10 // pointer casting. For example, using a slice narrowing cast:10 // load from `u32_ptr` depends on the target endian:
11 const u32_value = std.mem.bytesAsSlice(u32, bytes[0..])[0];11 switch (native_endian) {
12 try expectEqual(0x12121212, u32_value);12 .little => try expectEqual(0x40302010, u32_ptr.*),
13 .big => try expectEqual(0x10203040, u32_ptr.*),
14 }
1315
14 // And even another way, the most straightforward way to do it:16 // To instead reinterpret the logical bit representation of `bytes` with no
15 try expectEqual(0x12121212, @as(u32, @bitCast(bytes)));17 // dependency on the target endian, use `@bitCast`, which always places
18 // earlier array elements into less-significant bits:
19 try expectEqual(0x40302010, @as(u32, @bitCast(bytes)));
16}20}
1721
18test "pointer child type" {22test "pointer child type" {
test/behavior/asm.zig-36
...@@ -209,42 +209,6 @@ test "packed output types (x86_64)" {...@@ -209,42 +209,6 @@ test "packed output types (x86_64)" {
209 }209 }
210}210}
211211
212test "extern output types (x86_64)" {
213 if (builtin.target.cpu.arch != .x86_64) return error.SkipZigTest;
214 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
215 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31531
216
217 const S = extern struct { x: u32 };
218 {
219 const s: S = asm volatile ("mov $123, %[ret]"
220 : [ret] "=r" (-> S),
221 );
222 try expect(s.x == 123);
223 }
224 {
225 var s: S = undefined;
226 asm volatile ("mov $123, %[ret]"
227 : [ret] "=r" (s),
228 );
229 try expect(s.x == 123);
230 }
231
232 const U = extern union { x: u32 };
233 {
234 const u: U = asm volatile ("mov $123, %[ret]"
235 : [ret] "=r" (-> U),
236 );
237 try expect(u.x == 123);
238 }
239 {
240 var u: U = undefined;
241 asm volatile ("mov $123, %[ret]"
242 : [ret] "=r" (u),
243 );
244 try expect(u.x == 123);
245 }
246}
247
248test "abi register aliases as clobbers (RISC-V)" {212test "abi register aliases as clobbers (RISC-V)" {
249 if (!builtin.target.cpu.arch.isRISCV()) return error.SkipZigTest;213 if (!builtin.target.cpu.arch.isRISCV()) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;214 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/atomics.zig-1
...@@ -358,7 +358,6 @@ test "atomics with different types" {...@@ -358,7 +358,6 @@ test "atomics with different types" {
358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
359 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;359 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
360 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;360 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
361 if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // #24282
362361
363 try testAtomicsWithType(bool, true, false);362 try testAtomicsWithType(bool, true, false);
364363
test/behavior/bitcast.zig+141-167
...@@ -74,55 +74,6 @@ fn conv_uN(comptime N: usize, x: @Int(.unsigned, N)) @Int(.signed, N) {...@@ -74,55 +74,6 @@ fn conv_uN(comptime N: usize, x: @Int(.unsigned, N)) @Int(.signed, N) {
74 return @as(@Int(.signed, N), @bitCast(x));74 return @as(@Int(.signed, N), @bitCast(x));
75}75}
7676
77test "bitcast uX to bytes" {
78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
82 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
83
84 const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };
85 inline for (bit_values) |bits| {
86 try testBitCast(bits);
87 try comptime testBitCast(bits);
88 }
89}
90
91fn testBitCastuXToBytes(comptime N: usize) !void {
92
93 // The location of padding bits in these layouts are technically not defined
94 // by LLVM, but we currently allow exotic integers to be cast (at comptime)
95 // to types that expose their padding bits anyway.
96 //
97 // This test at least makes sure those bits are matched by the runtime behavior
98 // on the platforms we target. If the above behavior is restricted after all,
99 // this test should be deleted.
100
101 const T = @Int(.unsigned, N);
102 for ([_]T{ 0, ~@as(T, 0) }) |init_value| {
103 var x: T = init_value;
104 const bytes = std.mem.asBytes(&x);
105
106 const byte_count = (N + 7) / 8;
107 switch (native_endian) {
108 .little => {
109 var byte_i = 0;
110 while (byte_i < (byte_count - 1)) : (byte_i += 1) {
111 try expect(bytes[byte_i] == 0xff);
112 }
113 try expect(((bytes[byte_i] ^ 0xff) << -%@as(u3, @truncate(N))) == 0);
114 },
115 .big => {
116 var byte_i = byte_count - 1;
117 while (byte_i > 0) : (byte_i -= 1) {
118 try expect(bytes[byte_i] == 0xff);
119 }
120 try expect(((bytes[byte_i] ^ 0xff) << -%@as(u3, @truncate(N))) == 0);
121 },
122 }
123 }
124}
125
126test "nested bitcast" {77test "nested bitcast" {
127 const S = struct {78 const S = struct {
128 fn moo(x: isize) !void {79 fn moo(x: isize) !void {
...@@ -183,39 +134,6 @@ test "@bitCast packed structs at runtime and comptime" {...@@ -183,39 +134,6 @@ test "@bitCast packed structs at runtime and comptime" {
183 try comptime S.doTheTest();134 try comptime S.doTheTest();
184}135}
185136
186test "@bitCast extern structs at runtime and comptime" {
187 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
188 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
189 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
190
191 const Full = extern struct {
192 number: u16,
193 };
194 const TwoHalves = extern struct {
195 half1: u8,
196 half2: u8,
197 };
198 const S = struct {
199 fn doTheTest() !void {
200 var full = Full{ .number = 0x1234 };
201 _ = &full;
202 const two_halves: TwoHalves = @bitCast(full);
203 switch (native_endian) {
204 .big => {
205 try expect(two_halves.half1 == 0x12);
206 try expect(two_halves.half2 == 0x34);
207 },
208 .little => {
209 try expect(two_halves.half1 == 0x34);
210 try expect(two_halves.half2 == 0x12);
211 },
212 }
213 }
214 };
215 try S.doTheTest();
216 try comptime S.doTheTest();
217}
218
219test "bitcast packed struct to integer and back" {137test "bitcast packed struct to integer and back" {
220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;139 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -363,32 +281,12 @@ test "comptime @bitCast packed struct to int and back" {...@@ -363,32 +281,12 @@ test "comptime @bitCast packed struct to int and back" {
363 }281 }
364}282}
365283
366test "comptime bitcast with fields following f80" {
367 if (true) {
368 // https://github.com/ziglang/zig/issues/19387
369 return error.SkipZigTest;
370 }
371
372 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
375
376 const FloatT = extern struct { f: f80, x: u128 align(16) };
377 const x: FloatT = .{ .f = 0.5, .x = 123 };
378 var x_as_uint: u256 = comptime @as(u256, @bitCast(x));
379 _ = &x_as_uint;
380
381 try expect(x.f == @as(FloatT, @bitCast(x_as_uint)).f);
382 try expect(x.x == @as(FloatT, @bitCast(x_as_uint)).x);
383}
384
385test "bitcast vector to integer and back" {284test "bitcast vector to integer and back" {
386 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;285 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
387 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO286 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
388 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO287 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
389 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;288 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
390 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;289 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
391 if (builtin.cpu.arch.endian() == .big and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
392290
393 var vec: @Vector(16, bool) = @splat(true);291 var vec: @Vector(16, bool) = @splat(true);
394 vec[1] = false;292 vec[1] = false;
...@@ -524,87 +422,163 @@ test "@bitCast of packed struct of bools all false" {...@@ -524,87 +422,163 @@ test "@bitCast of packed struct of bools all false" {
524 try expect(@as(u8, @as(u4, @bitCast(p))) == 0);422 try expect(@as(u8, @as(u4, @bitCast(p))) == 0);
525}423}
526424
527test "@bitCast of extern struct containing pointer" {425test "@bitCast of packed struct with void field to integer" {
528 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;426 const S = packed struct(u8) {
529 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO427 v: void,
530 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO428 x: u8,
531 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
532
533 const S = struct {
534 const A = extern struct {
535 ptr: *const u32,
536 };
537
538 const B = extern struct {
539 ptr: *const i32,
540 };
541429
542 fn doTheTest() !void {430 fn doTheTest(x: u8) !void {
543 const x: u32 = 123;431 // Intentionally using `@as` to avoid RLS which masks the bug
544 var a: A = undefined;432 const foo = @as(@This(), .{ .v = {}, .x = x });
545 a = .{ .ptr = &x };433 const as_int: u8 = @bitCast(foo);
546 const b: B = @bitCast(a);434 try expect(as_int == x);
547 try expect(b.ptr.* == 123);
548 }435 }
549 };436 };
550437 try S.doTheTest(123);
551 try S.doTheTest();438 try comptime S.doTheTest(123);
552 try comptime S.doTheTest();
553}439}
554440
555test "@bitCast of extern struct to float" {441test "@bitCast vector to array with different element size" {
556 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;442 const static = struct {
557 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;443 fn doTheTest(v: @Vector(4, u5)) !void {
558444 const result: [5]u4 = @bitCast(v);
559 const S = struct {445 // See the definition of `v` in the test proper for these values.
560 const S = extern struct {446 try expect(result[0] == 0b0010);
561 x: u16,447 try expect(result[1] == 0b1110);
562 y: u16,448 try expect(result[2] == 0b0101);
563 };449 try expect(result[3] == 0b0110);
564 fn doTheTest() !void {450 try expect(result[4] == 0b0000);
565 var s: S = .{ .x = 0, .y = 0 };451 }
566 _ = &s;452 };
567 const a: f32 = @bitCast(s);453 // The strange digit groupings here are to indicate how this maps to `expected` above.
568 try expect(a == 0);454 const v: @Vector(4, u5) = .{
455 0b0_0010,
456 0b01_111,
457 0b110_01,
458 0b0000_0,
459 };
460 try static.doTheTest(v);
461 try comptime static.doTheTest(v);
462}
463
464test "@bitCast packed struct to array of bits" {
465 const S = packed struct(u16) {
466 foo: u5,
467 bar: i7,
468 baz: u3,
469 qux: bool,
470 fn doTheTest(val: @This(), comptime Bits: type) !void {
471 const bits: Bits = @bitCast(val);
472
473 // foo
474 try expect(bits[0] == 1);
475 try expect(bits[1] == 0);
476 try expect(bits[2] == 0);
477 try expect(bits[3] == 1);
478 try expect(bits[4] == 0);
479 // bar
480 try expect(bits[5] == 0);
481 try expect(bits[6] == 1);
482 try expect(bits[7] == 1);
483 try expect(bits[8] == 1);
484 try expect(bits[9] == 1);
485 try expect(bits[10] == 1);
486 try expect(bits[11] == 1);
487 // baz
488 try expect(bits[12] == 0);
489 try expect(bits[13] == 1);
490 try expect(bits[14] == 0);
491 // qux
492 try expect(bits[15] == 1);
569 }493 }
570 };494 };
571495
572 try S.doTheTest();496 const val: S = .{
573 try comptime S.doTheTest();497 .foo = 0b01001,
498 .bar = -2,
499 .baz = 0b010,
500 .qux = true,
501 };
502
503 try val.doTheTest(@Vector(16, u1));
504 try val.doTheTest([16]u1);
505
506 try comptime val.doTheTest(@Vector(16, u1));
507 try comptime val.doTheTest([16]u1);
574}508}
575509
576test "@bitCast of float to extern struct" {510test "@bitCast nested arrays of vectors" {
577 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;511 const Src = [2][2]@Vector(4, u5);
578 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;512 const Dest = [5]@Vector(2, u8);
579513
580 const S = struct {514 // The strange digit groupings here are to indicate how this maps to the output.
581 const S = extern struct {515 const src: Src = .{ .{
582 x: u32,516 .{ 0b00011, 0b00_100, 0b11100, 0b0010_1 },
583 };517 .{ 0b1_0110, 0b11011, 0b101_10, 0b10101 },
584 fn doTheTest() !void {518 }, .{
585 var a: f32 = -0.0;519 .{ 0b10101, 0b00_001, 0b01011, 0b0001_0 },
586 _ = &a;520 .{ 0b0_0001, 0b01111, 0b111_10, 0b00001 },
587 const s: S = @bitCast(a);521 } };
588 try expect(s.x == 0x80000000);522
523 const expected: Dest = .{
524 .{ 0b10000011, 0b11110000 },
525 .{ 0b01100010, 0b10110111 },
526 .{ 0b10101101, 0b00110101 },
527 .{ 0b00101100, 0b00010001 },
528 .{ 0b10011110, 0b00001111 },
529 };
530
531 const static = struct {
532 fn doTheTest(src_arg: Src) !void {
533 const actual: Dest = @bitCast(src_arg);
534 for (actual, expected) |actual_vec, expected_vec| {
535 try expect(actual_vec[0] == expected_vec[0]);
536 try expect(actual_vec[1] == expected_vec[1]);
537 }
589 }538 }
590 };539 };
591540
592 try S.doTheTest();541 try static.doTheTest(src);
593 try comptime S.doTheTest();542 try comptime static.doTheTest(src);
594}543}
595544
596test "@bitCast of packed struct with void field to integer" {545test "@bitCast nested arrays of bool to scalar" {
597 const S = packed struct(u8) {546 const static = struct {
598 v: void,547 fn doTheTest(src: [4][4]bool) !void {
599 x: u8,548 const result: u16 = @bitCast(src);
600549 try expect(result == 0b1100_0101_1010_0011);
601 fn doTheTest(x: u8) !void {
602 // Intentionally using `@as` to avoid RLS which masks the bug
603 const foo = @as(@This(), .{ .v = {}, .x = x });
604 const as_int: u8 = @bitCast(foo);
605 try expect(as_int == x);
606 }550 }
607 };551 };
608 try S.doTheTest(123);552 const src: [4][4]bool = .{
609 try comptime S.doTheTest(123);553 .{ true, true, false, false }, // 0b0011
554 .{ false, true, false, true }, // 0b1010
555 .{ true, false, true, false }, // 0b0101
556 .{ false, false, true, true }, // 0b1100
557 };
558 try static.doTheTest(src);
559 try comptime static.doTheTest(src);
560}
561
562test "@bitCast deeply nested arrays to scalar" {
563 const static = struct {
564 fn doTheTest(src: [2][1][3][5]u4) !void {
565 const signed: i120 = @bitCast(src);
566 try expect(signed < 0); // top nibble is 0x8 so sign bit is 1
567 const unsigned: u120 = @bitCast(src);
568 try expect(unsigned == 0x8873B_5BF6F_F4020_0E7AC_1EFED_40F51);
569 try expect(@as(i120, @bitCast(unsigned)) == signed);
570 try expect(@as(u120, @bitCast(signed)) == unsigned);
571 }
572 };
573 const src: [2][1][3][5]u4 = .{ .{.{
574 .{ 0x1, 0x5, 0xF, 0x0, 0x4 },
575 .{ 0xD, 0xE, 0xF, 0xE, 0x1 },
576 .{ 0xC, 0xA, 0x7, 0xE, 0x0 },
577 }}, .{.{
578 .{ 0x0, 0x2, 0x0, 0x4, 0xF },
579 .{ 0xF, 0x6, 0xF, 0xB, 0x5 },
580 .{ 0xB, 0x3, 0x7, 0x8, 0x8 },
581 }} };
582 try static.doTheTest(src);
583 try comptime static.doTheTest(src);
610}584}
test/behavior/comptime_memory.zig+16
...@@ -583,3 +583,19 @@ test "comptime store to extern struct reinterpreted as byte array" {...@@ -583,3 +583,19 @@ test "comptime store to extern struct reinterpreted as byte array" {
583583
584 comptime std.debug.assert(val.x == 0);584 comptime std.debug.assert(val.x == 0);
585}585}
586
587test "reinterpret sentinel-terminated array as packed struct" {
588 const S = packed struct(u16) { lo: u8, hi: u8 };
589 const data: [2:0]u8 = .{ 0x12, 0x34 };
590 const ptr: *align(1) const S = @ptrCast(&data);
591 switch (endian) {
592 .little => {
593 try testing.expect(ptr.lo == 0x12);
594 try testing.expect(ptr.hi == 0x34);
595 },
596 .big => {
597 try testing.expect(ptr.lo == 0x34);
598 try testing.expect(ptr.hi == 0x12);
599 },
600 }
601}
test/behavior/sizeof_and_typeof.zig-11
...@@ -151,9 +151,6 @@ test "branching logic inside @TypeOf" {...@@ -151,9 +151,6 @@ test "branching logic inside @TypeOf" {
151test "@bitSizeOf" {151test "@bitSizeOf" {
152 try expect(@bitSizeOf(u2) == 2);152 try expect(@bitSizeOf(u2) == 2);
153 try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);153 try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
154 try expect(@bitSizeOf(struct {
155 a: u2,
156 }) == 8);
157 try expect(@bitSizeOf(packed struct {154 try expect(@bitSizeOf(packed struct {
158 a: u2,155 a: u2,
159 }) == 2);156 }) == 2);
...@@ -281,14 +278,6 @@ test "@offsetOf zero-bit field" {...@@ -281,14 +278,6 @@ test "@offsetOf zero-bit field" {
281 try expect(@offsetOf(S, "b") == @offsetOf(S, "c"));278 try expect(@offsetOf(S, "b") == @offsetOf(S, "c"));
282}279}
283280
284test "@bitSizeOf on array of structs" {
285 const S = struct {
286 foo: u64,
287 };
288
289 try expectEqual(128, @bitSizeOf([2]S));
290}
291
292test "lazy abi size used in comparison" {281test "lazy abi size used in comparison" {
293 const S = struct { a: usize };282 const S = struct { a: usize };
294 var rhs: i32 = 100;283 var rhs: i32 = 100;
test/behavior/vector.zig+2-2
...@@ -1536,12 +1536,12 @@ test "vector pointer is indexable" {...@@ -1536,12 +1536,12 @@ test "vector pointer is indexable" {
1536 const V = @Vector(2, u32);1536 const V = @Vector(2, u32);
15371537
1538 const x: V = .{ 123, 456 };1538 const x: V = .{ 123, 456 };
1539 comptime assert(@TypeOf(&(&x)[0]) == *const u32); // validate constness1539 comptime assert(@typeInfo(@TypeOf(&(&x)[0])).pointer.attrs.@"const");
1540 try expectEqual(@as(u32, 123), (&x)[0]);1540 try expectEqual(@as(u32, 123), (&x)[0]);
1541 try expectEqual(@as(u32, 456), (&x)[1]);1541 try expectEqual(@as(u32, 456), (&x)[1]);
15421542
1543 var y: V = .{ 123, 456 };1543 var y: V = .{ 123, 456 };
1544 comptime assert(@TypeOf(&(&y)[0]) == *u32); // validate constness1544 comptime assert(!@typeInfo(@TypeOf(&(&y)[0])).pointer.attrs.@"const");
1545 try expectEqual(@as(u32, 123), (&y)[0]);1545 try expectEqual(@as(u32, 123), (&y)[0]);
1546 try expectEqual(@as(u32, 456), (&y)[1]);1546 try expectEqual(@as(u32, 456), (&y)[1]);
15471547
test/c_abi/main.zig+2-1
...@@ -17109,7 +17109,8 @@ const byval_tail_callsite_attr = struct {...@@ -17109,7 +17109,8 @@ const byval_tail_callsite_attr = struct {
17109 }17109 }
1711017110
17111 fn cast(self: MyRect) struct_Rect {17111 fn cast(self: MyRect) struct_Rect {
17112 return @bitCast(self);17112 const ptr: *const struct_Rect = @ptrCast(&self);
17113 return ptr.*;
17113 }17114 }
1711417115
17115 extern fn c_byval_tail_callsite_attr(struct_Rect) f64;17116 extern fn c_byval_tail_callsite_attr(struct_Rect) f64;
test/cases/compile_errors/asm_output_type_no_guaranteed_in_memory_layout.zig+28-4
...@@ -25,14 +25,38 @@ export fn entry4() void {...@@ -25,14 +25,38 @@ export fn entry4() void {
25 : [_] "=r" (u),25 : [_] "=r" (u),
26 );26 );
27}27}
28const ES = extern struct { x: u32 };
29export fn entry5() void {
30 var es: ES = undefined;
31 asm volatile (""
32 : [_] "=r" (es),
33 );
34}
35const EU = extern union { x: u32 };
36export fn entry6() void {
37 var eu: EU = undefined;
38 asm volatile (""
39 : [_] "=r" (eu),
40 );
41}
2842
29// error43// error
30//44//
31// :4:24: error: invalid inline assembly output type; 'tmp.S' does not have a guaranteed in-memory layout45// :4:24: error: invalid inline assembly output type 'tmp.S'
46// :4:24: note: struct types cannot be passed to inline assembly
32// :1:11: note: struct declared here47// :1:11: note: struct declared here
33// :11:21: error: invalid inline assembly output type; 'tmp.S' does not have a guaranteed in-memory layout48// :11:21: error: invalid inline assembly output type 'tmp.S'
49// :11:21: note: struct types cannot be passed to inline assembly
34// :1:11: note: struct declared here50// :1:11: note: struct declared here
35// :18:24: error: invalid inline assembly output type; 'tmp.U' does not have a guaranteed in-memory layout51// :18:24: error: invalid inline assembly output type 'tmp.U'
52// :18:24: note: union types cannot be passed to inline assembly
36// :15:11: note: union declared here53// :15:11: note: union declared here
37// :25:21: error: invalid inline assembly output type; 'tmp.U' does not have a guaranteed in-memory layout54// :25:21: error: invalid inline assembly output type 'tmp.U'
55// :25:21: note: union types cannot be passed to inline assembly
38// :15:11: note: union declared here56// :15:11: note: union declared here
57// :32:21: error: invalid inline assembly output type 'tmp.ES'
58// :32:21: note: struct types cannot be passed to inline assembly
59// :28:19: note: struct declared here
60// :39:21: error: invalid inline assembly output type 'tmp.EU'
61// :39:21: note: union types cannot be passed to inline assembly
62// :35:19: note: union declared here
test/cases/compile_errors/bitCast_extern_struct.zig created+10
...@@ -0,0 +1,10 @@
1const S = extern struct { x: u32 };
2export fn foo(s: S) void {
3 const as_int: u32 = @bitCast(s);
4 _ = as_int;
5}
6
7// error
8//
9// :3:34: error: cannot @bitCast from 'tmp.S'
10// :1:18: note: struct declared here
test/cases/compile_errors/bitCast_to_enum_type.zig deleted-10
...@@ -1,10 +0,0 @@
1export fn entry() void {
2 const E = enum(u32) { a, b };
3 const y: E = @bitCast(@as(u32, 3));
4 _ = y;
5}
6
7// error
8//
9// :3:18: error: cannot @bitCast to 'tmp.entry.E'
10// :3:18: note: use @enumFromInt to cast from 'u32'
test/cases/compile_errors/bitCast_vector_of_pointer.zig created+9
...@@ -0,0 +1,9 @@
1export fn foo(p: *u32) void {
2 const vec: @Vector(2, *u32) = .{ p, p };
3 const raw: [2]usize = @bitCast(vec);
4 _ = raw;
5}
6
7// error
8//
9// :3:36: error: cannot @bitCast from '@Vector(2, *u32)'
test/cases/compile_errors/bitCast_with_invalid_array_element_type.zig+2-5
...@@ -18,9 +18,6 @@ export fn baz() void {...@@ -18,9 +18,6 @@ export fn baz() void {
1818
19// error19// error
20//20//
21// :5:29: error: cannot @bitCast from '[1]tmp.foo.S'21// :5:42: error: cannot @bitCast from '[1]tmp.foo.S'
22// :5:29: note: array element type 'tmp.foo.S' does not have a guaranteed in-memory layout
23// :12:19: error: cannot @bitCast to '[1]tmp.bar.S'22// :12:19: error: cannot @bitCast to '[1]tmp.bar.S'
24// :12:19: note: array element type 'tmp.bar.S' does not have a guaranteed in-memory layout23// :16:45: error: cannot @bitCast from '[1]comptime_int'
25// :16:21: error: cannot @bitCast from '[1]comptime_int'
26// :16:21: note: array element type 'comptime_int' does not have a guaranteed in-memory layout
test/cases/compile_errors/error_in_nested_declaration.zig created+29
...@@ -0,0 +1,29 @@
1const S = struct {
2 b: u32,
3 c: i32,
4 a: struct {
5 pub fn str(_: @This(), extra: []u32) []i32 {
6 return @bitCast(extra);
7 }
8 },
9};
10
11pub export fn entry() void {
12 var s: S = undefined;
13 _ = s.a.str(undefined);
14}
15
16const S2 = struct {
17 a: [*c]anyopaque,
18};
19
20pub export fn entry2() void {
21 var s: S2 = undefined;
22 _ = &s;
23}
24
25// error
26//
27// :6:20: error: cannot @bitCast to '[]i32'
28// :6:20: note: use @ptrCast to cast from '[]u32'
29// :17:12: error: indexable pointer to opaque type 'anyopaque' not allowed
test/cases/error_in_nested_declaration.zig deleted-30
...@@ -1,30 +0,0 @@
1const S = struct {
2 b: u32,
3 c: i32,
4 a: struct {
5 pub fn str(_: @This(), extra: []u32) []i32 {
6 return @bitCast(extra);
7 }
8 },
9};
10
11pub export fn entry() void {
12 var s: S = undefined;
13 _ = s.a.str(undefined);
14}
15
16const S2 = struct {
17 a: [*c]anyopaque,
18};
19
20pub export fn entry2() void {
21 var s: S2 = undefined;
22 _ = &s;
23}
24
25// error
26// backend=selfhosted,llvm
27//
28// :6:20: error: cannot @bitCast to '[]i32'
29// :6:20: note: use @ptrCast to cast from '[]u32'
30// :17:12: error: indexable pointer to opaque type 'anyopaque' not allowed