authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-07-08 17:29:32-07:00
committergravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-07-08 19:51:35-07:00
log51a8f52e6cdd53321572830efe3ac75cb09b5a09
tree0b263b2bc46765c0c17aa4d06e30e1c7007c6176
parent2fff25fd220632cc6943680d3d6bbb1f21fa141f

stage2: Support `@offsetOf` for tuples and anon structs


3 files changed, 23 insertions(+), 39 deletions(-)

src/Sema.zig+22-32
......@@ -15872,50 +15872,40 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
1587215872 const target = sema.mod.getTarget();
1587315873
1587415874 try sema.resolveTypeLayout(block, lhs_src, ty);
15875 if (ty.tag() != .@"struct") {
15876 const msg = msg: {
15877 const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)});
15878 errdefer msg.destroy(sema.gpa);
15879 try sema.addDeclaredHereNote(msg, ty);
15880 break :msg msg;
15881 };
15882 return sema.failWithOwnedErrorMsg(block, msg);
15875 switch (ty.tag()) {
15876 .@"struct", .tuple, .anon_struct => {},
15877 else => {
15878 const msg = msg: {
15879 const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)});
15880 errdefer msg.destroy(sema.gpa);
15881 try sema.addDeclaredHereNote(msg, ty);
15882 break :msg msg;
15883 };
15884 return sema.failWithOwnedErrorMsg(block, msg);
15885 },
1588315886 }
1588415887
15885 const fields = ty.structFields();
15886 const index = fields.getIndex(field_name) orelse {
15887 const msg = msg: {
15888 const msg = try sema.errMsg(
15889 block,
15890 rhs_src,
15891 "struct '{}' has no field '{s}'",
15892 .{ ty.fmt(sema.mod), field_name },
15893 );
15894 errdefer msg.destroy(sema.gpa);
15895 try sema.addDeclaredHereNote(msg, ty);
15896 break :msg msg;
15897 };
15898 return sema.failWithOwnedErrorMsg(block, msg);
15899 };
15888 const field_index = if (ty.isTuple()) b: {
15889 if (std.fmt.parseUnsigned(u32, field_name, 10)) |idx| {
15890 if (idx < ty.structFieldCount()) break :b idx;
15891 } else |_| {}
15892 return sema.fail(block, rhs_src, "tuple '{}' has no such field '{s}'", .{
15893 ty.fmt(sema.mod), field_name,
15894 });
15895 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
1590015896
1590115897 switch (ty.containerLayout()) {
1590215898 .Packed => {
1590315899 var bit_sum: u64 = 0;
15900 const fields = ty.structFields();
1590415901 for (fields.values()) |field, i| {
15905 if (i == index) {
15902 if (i == field_index) {
1590615903 return bit_sum;
1590715904 }
1590815905 bit_sum += field.ty.bitSize(target);
1590915906 } else unreachable;
1591015907 },
15911 else => {
15912 var it = ty.iterateStructOffsets(target);
15913 while (it.next()) |field_offset| {
15914 if (field_offset.field == index) {
15915 return field_offset.offset * 8;
15916 }
15917 } else unreachable;
15918 },
15908 else => return ty.structFieldOffset(field_index, target) * 8,
1591915909 }
1592015910}
1592115911
test/behavior/tuple.zig-6
......@@ -221,20 +221,14 @@ test "fieldParentPtr of anon struct" {
221221}
222222
223223test "offsetOf tuple" {
224 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
225
226224 var x: u32 = 0;
227225 const T = @TypeOf(.{ x, x });
228
229226 _ = @offsetOf(T, "1");
230227}
231228
232229test "offsetOf anon struct" {
233 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
234
235230 var x: u32 = 0;
236231 const T = @TypeOf(.{ .foo = x, .bar = x });
237
238232 _ = @offsetOf(T, "bar");
239233}
240234
test/cases/compile_errors/offsetOf-bad_field_name.zig+1-1
......@@ -9,5 +9,5 @@ export fn foo() usize {
99// backend=stage2
1010// target=native
1111//
12// :5:27: error: struct 'tmp.Foo' has no field 'a'
12// :5:27: error: no field named 'a' in struct 'tmp.Foo'
1313// :1:13: note: struct declared here