authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-03-18 15:00:27+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-03-30 20:50:48-04:00
log9b2345e182090e2f4c57e7684ec9739f195fdb1d
tree291857693683d092b886a59fb2fa37fefee981ec
parent5a41704f7ec2c472897f955ecfe1feafa697ff68

Sema: rework `@fieldParentPtr` to accept a pointer type

There is no way to know the expected parent pointer attributes (most notably alignment) from the type of the field pointer, so provide them in the first argument.

15 files changed, 2117 insertions(+), 243 deletions(-)

src/InternPool.zig+33-26
......@@ -5163,48 +5163,55 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
51635163 .ptr => |ptr| {
51645164 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
51655165 assert(ptr_type.flags.size != .Slice);
5166 switch (ptr.addr) {
5167 .decl => |decl| ip.items.appendAssumeCapacity(.{
5166 ip.items.appendAssumeCapacity(switch (ptr.addr) {
5167 .decl => |decl| .{
51685168 .tag = .ptr_decl,
51695169 .data = try ip.addExtra(gpa, PtrDecl{
51705170 .ty = ptr.ty,
51715171 .decl = decl,
51725172 }),
5173 }),
5174 .comptime_alloc => |alloc_index| ip.items.appendAssumeCapacity(.{
5173 },
5174 .comptime_alloc => |alloc_index| .{
51755175 .tag = .ptr_comptime_alloc,
51765176 .data = try ip.addExtra(gpa, PtrComptimeAlloc{
51775177 .ty = ptr.ty,
51785178 .index = alloc_index,
51795179 }),
5180 }),
5181 .anon_decl => |anon_decl| ip.items.appendAssumeCapacity(
5182 if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{
5180 },
5181 .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: {
5182 if (ptr.ty != anon_decl.orig_ty) {
5183 _ = ip.map.pop();
5184 var new_key = key;
5185 new_key.ptr.addr.anon_decl.orig_ty = ptr.ty;
5186 const new_gop = try ip.map.getOrPutAdapted(gpa, new_key, adapter);
5187 if (new_gop.found_existing) return @enumFromInt(new_gop.index);
5188 }
5189 break :item .{
51835190 .tag = .ptr_anon_decl,
51845191 .data = try ip.addExtra(gpa, PtrAnonDecl{
51855192 .ty = ptr.ty,
51865193 .val = anon_decl.val,
51875194 }),
5188 } else .{
5189 .tag = .ptr_anon_decl_aligned,
5190 .data = try ip.addExtra(gpa, PtrAnonDeclAligned{
5191 .ty = ptr.ty,
5192 .val = anon_decl.val,
5193 .orig_ty = anon_decl.orig_ty,
5194 }),
5195 },
5196 ),
5197 .comptime_field => |field_val| {
5195 };
5196 } else .{
5197 .tag = .ptr_anon_decl_aligned,
5198 .data = try ip.addExtra(gpa, PtrAnonDeclAligned{
5199 .ty = ptr.ty,
5200 .val = anon_decl.val,
5201 .orig_ty = anon_decl.orig_ty,
5202 }),
5203 },
5204 .comptime_field => |field_val| item: {
51985205 assert(field_val != .none);
5199 ip.items.appendAssumeCapacity(.{
5206 break :item .{
52005207 .tag = .ptr_comptime_field,
52015208 .data = try ip.addExtra(gpa, PtrComptimeField{
52025209 .ty = ptr.ty,
52035210 .field_val = field_val,
52045211 }),
5205 });
5212 };
52065213 },
5207 .int, .eu_payload, .opt_payload => |base| {
5214 .int, .eu_payload, .opt_payload => |base| item: {
52085215 switch (ptr.addr) {
52095216 .int => assert(ip.typeOf(base) == .usize_type),
52105217 .eu_payload => assert(ip.indexToKey(
......@@ -5215,7 +5222,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52155222 ) == .opt_type),
52165223 else => unreachable,
52175224 }
5218 ip.items.appendAssumeCapacity(.{
5225 break :item .{
52195226 .tag = switch (ptr.addr) {
52205227 .int => .ptr_int,
52215228 .eu_payload => .ptr_eu_payload,
......@@ -5226,9 +5233,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52265233 .ty = ptr.ty,
52275234 .base = base,
52285235 }),
5229 });
5236 };
52305237 },
5231 .elem, .field => |base_index| {
5238 .elem, .field => |base_index| item: {
52325239 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
52335240 switch (ptr.addr) {
52345241 .elem => assert(base_ptr_type.flags.size == .Many),
......@@ -5265,7 +5272,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52655272 } });
52665273 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
52675274 try ip.items.ensureUnusedCapacity(gpa, 1);
5268 ip.items.appendAssumeCapacity(.{
5275 break :item .{
52695276 .tag = switch (ptr.addr) {
52705277 .elem => .ptr_elem,
52715278 .field => .ptr_field,
......@@ -5276,9 +5283,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
52765283 .base = base_index.base,
52775284 .index = index_index,
52785285 }),
5279 });
5286 };
52805287 },
5281 }
5288 });
52825289 },
52835290
52845291 .opt => |opt| {
src/Sema.zig+143-86
......@@ -17699,19 +17699,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1769917699 .ty = new_decl_ty.toIntern(),
1770017700 .storage = .{ .elems = param_vals },
1770117701 } });
17702 const ptr_ty = (try sema.ptrType(.{
17702 const slice_ty = (try sema.ptrType(.{
1770317703 .child = param_info_ty.toIntern(),
1770417704 .flags = .{
1770517705 .size = .Slice,
1770617706 .is_const = true,
1770717707 },
1770817708 })).toIntern();
17709 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1770917710 break :v try mod.intern(.{ .slice = .{
17710 .ty = ptr_ty,
17711 .ty = slice_ty,
1771117712 .ptr = try mod.intern(.{ .ptr = .{
17712 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
17713 .ty = manyptr_ty,
1771317714 .addr = .{ .anon_decl = .{
17714 .orig_ty = ptr_ty,
17715 .orig_ty = manyptr_ty,
1771517716 .val = new_decl_val,
1771617717 } },
1771717718 } }),
......@@ -18031,12 +18032,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1803118032 .ty = array_errors_ty.toIntern(),
1803218033 .storage = .{ .elems = vals },
1803318034 } });
18035 const manyptr_errors_ty = slice_errors_ty.slicePtrFieldType(mod).toIntern();
1803418036 break :v try mod.intern(.{ .slice = .{
1803518037 .ty = slice_errors_ty.toIntern(),
1803618038 .ptr = try mod.intern(.{ .ptr = .{
18037 .ty = slice_errors_ty.slicePtrFieldType(mod).toIntern(),
18039 .ty = manyptr_errors_ty,
1803818040 .addr = .{ .anon_decl = .{
18039 .orig_ty = slice_errors_ty.toIntern(),
18041 .orig_ty = manyptr_errors_ty,
1804018042 .val = new_decl_val,
1804118043 } },
1804218044 } }),
......@@ -18155,20 +18157,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1815518157 .ty = fields_array_ty.toIntern(),
1815618158 .storage = .{ .elems = enum_field_vals },
1815718159 } });
18158 const ptr_ty = (try sema.ptrType(.{
18160 const slice_ty = (try sema.ptrType(.{
1815918161 .child = enum_field_ty.toIntern(),
1816018162 .flags = .{
1816118163 .size = .Slice,
1816218164 .is_const = true,
1816318165 },
1816418166 })).toIntern();
18167 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1816518168 break :v try mod.intern(.{ .slice = .{
18166 .ty = ptr_ty,
18169 .ty = slice_ty,
1816718170 .ptr = try mod.intern(.{ .ptr = .{
18168 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18171 .ty = manyptr_ty,
1816918172 .addr = .{ .anon_decl = .{
1817018173 .val = new_decl_val,
18171 .orig_ty = ptr_ty,
18174 .orig_ty = manyptr_ty,
1817218175 } },
1817318176 } }),
1817418177 .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(),
......@@ -18296,19 +18299,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1829618299 .ty = array_fields_ty.toIntern(),
1829718300 .storage = .{ .elems = union_field_vals },
1829818301 } });
18299 const ptr_ty = (try sema.ptrType(.{
18302 const slice_ty = (try sema.ptrType(.{
1830018303 .child = union_field_ty.toIntern(),
1830118304 .flags = .{
1830218305 .size = .Slice,
1830318306 .is_const = true,
1830418307 },
1830518308 })).toIntern();
18309 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1830618310 break :v try mod.intern(.{ .slice = .{
18307 .ty = ptr_ty,
18311 .ty = slice_ty,
1830818312 .ptr = try mod.intern(.{ .ptr = .{
18309 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18313 .ty = manyptr_ty,
1831018314 .addr = .{ .anon_decl = .{
18311 .orig_ty = ptr_ty,
18315 .orig_ty = manyptr_ty,
1831218316 .val = new_decl_val,
1831318317 } },
1831418318 } }),
......@@ -18523,19 +18527,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1852318527 .ty = array_fields_ty.toIntern(),
1852418528 .storage = .{ .elems = struct_field_vals },
1852518529 } });
18526 const ptr_ty = (try sema.ptrType(.{
18530 const slice_ty = (try sema.ptrType(.{
1852718531 .child = struct_field_ty.toIntern(),
1852818532 .flags = .{
1852918533 .size = .Slice,
1853018534 .is_const = true,
1853118535 },
1853218536 })).toIntern();
18537 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1853318538 break :v try mod.intern(.{ .slice = .{
18534 .ty = ptr_ty,
18539 .ty = slice_ty,
1853518540 .ptr = try mod.intern(.{ .ptr = .{
18536 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18541 .ty = manyptr_ty,
1853718542 .addr = .{ .anon_decl = .{
18538 .orig_ty = ptr_ty,
18543 .orig_ty = manyptr_ty,
1853918544 .val = new_decl_val,
1854018545 } },
1854118546 } }),
......@@ -18661,19 +18666,20 @@ fn typeInfoDecls(
1866118666 .ty = array_decl_ty.toIntern(),
1866218667 .storage = .{ .elems = decl_vals.items },
1866318668 } });
18664 const ptr_ty = (try sema.ptrType(.{
18669 const slice_ty = (try sema.ptrType(.{
1866518670 .child = declaration_ty.toIntern(),
1866618671 .flags = .{
1866718672 .size = .Slice,
1866818673 .is_const = true,
1866918674 },
1867018675 })).toIntern();
18676 const manyptr_ty = Type.fromInterned(slice_ty).slicePtrFieldType(mod).toIntern();
1867118677 return try mod.intern(.{ .slice = .{
18672 .ty = ptr_ty,
18678 .ty = slice_ty,
1867318679 .ptr = try mod.intern(.{ .ptr = .{
18674 .ty = Type.fromInterned(ptr_ty).slicePtrFieldType(mod).toIntern(),
18680 .ty = manyptr_ty,
1867518681 .addr = .{ .anon_decl = .{
18676 .orig_ty = ptr_ty,
18682 .orig_ty = manyptr_ty,
1867718683 .val = new_decl_val,
1867818684 } },
1867918685 } }),
......@@ -19803,8 +19809,18 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1980319809 break :blk @intCast(host_size);
1980419810 } else 0;
1980519811
19806 if (host_size != 0 and bit_offset >= host_size * 8) {
19807 return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});
19812 if (host_size != 0) {
19813 if (bit_offset >= host_size * 8) {
19814 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} starts {} bits after the end of a {} byte host integer", .{
19815 elem_ty.fmt(mod), bit_offset, bit_offset - host_size * 8, host_size,
19816 });
19817 }
19818 const elem_bit_size = try elem_ty.bitSizeAdvanced(mod, sema);
19819 if (elem_bit_size > host_size * 8 - bit_offset) {
19820 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{
19821 elem_ty.fmt(mod), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
19822 });
19823 }
1980819824 }
1980919825
1981019826 if (elem_ty.zigTypeTag(mod) == .Fn) {
......@@ -24844,106 +24860,147 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2484424860}
2484524861
2484624862fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
24847 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24848 const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data;
24849 const src = inst_data.src();
24850 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
24851 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
24852 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
24853
24854 const parent_ty = try sema.resolveType(block, ty_src, extra.parent_type);
24855 const field_name = try sema.resolveConstStringIntern(block, name_src, extra.field_name, .{
24856 .needed_comptime_reason = "field name must be comptime-known",
24857 });
24858 const field_ptr = try sema.resolveInst(extra.field_ptr);
24859 const field_ptr_ty = sema.typeOf(field_ptr);
2486024863 const mod = sema.mod;
2486124864 const ip = &mod.intern_pool;
2486224865
24866 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24867 const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data;
24868 const inst_src = inst_data.src();
24869 const parent_ptr_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
24870 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
24871 const field_ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
24872
24873 const parent_ptr_ty = try sema.resolveType(block, parent_ptr_ty_src, extra.parent_type);
24874 try sema.checkPtrType(block, parent_ptr_ty_src, parent_ptr_ty, false);
24875 if (!parent_ptr_ty.isSinglePointer(mod)) {
24876 return sema.fail(block, parent_ptr_ty_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)});
24877 }
24878 const parent_ty = parent_ptr_ty.childType(mod);
2486324879 if (parent_ty.zigTypeTag(mod) != .Struct and parent_ty.zigTypeTag(mod) != .Union) {
24864 return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)});
24880 return sema.fail(block, parent_ptr_ty_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)});
2486524881 }
2486624882 try sema.resolveTypeLayout(parent_ty);
2486724883
24884 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{
24885 .needed_comptime_reason = "field name must be comptime-known",
24886 });
2486824887 const field_index = switch (parent_ty.zigTypeTag(mod)) {
2486924888 .Struct => blk: {
2487024889 if (parent_ty.isTuple(mod)) {
2487124890 if (ip.stringEqlSlice(field_name, "len")) {
24872 return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
24891 return sema.fail(block, inst_src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
2487324892 }
24874 break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, name_src);
24893 break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, field_name_src);
2487524894 } else {
24876 break :blk try sema.structFieldIndex(block, parent_ty, field_name, name_src);
24895 break :blk try sema.structFieldIndex(block, parent_ty, field_name, field_name_src);
2487724896 }
2487824897 },
24879 .Union => try sema.unionFieldIndex(block, parent_ty, field_name, name_src),
24898 .Union => try sema.unionFieldIndex(block, parent_ty, field_name, field_name_src),
2488024899 else => unreachable,
2488124900 };
24882
2488324901 if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index, mod)) {
24884 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
24902 return sema.fail(block, field_name_src, "cannot get @fieldParentPtr of a comptime field", .{});
2488524903 }
2488624904
24887 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
24888 const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod);
24905 const field_ptr = try sema.resolveInst(extra.field_ptr);
24906 const field_ptr_ty = sema.typeOf(field_ptr);
24907 try sema.checkPtrOperand(block, field_ptr_src, field_ptr_ty);
24908 const field_ptr_info = field_ptr_ty.ptrInfo(mod);
2488924909
24890 var ptr_ty_data: InternPool.Key.PtrType = .{
24891 .child = parent_ty.structFieldType(field_index, mod).toIntern(),
24910 var actual_parent_ptr_info: InternPool.Key.PtrType = .{
24911 .child = parent_ty.toIntern(),
2489224912 .flags = .{
24893 .address_space = field_ptr_ty_info.flags.address_space,
24894 .is_const = field_ptr_ty_info.flags.is_const,
24913 .alignment = try parent_ptr_ty.ptrAlignmentAdvanced(mod, sema),
24914 .is_const = field_ptr_info.flags.is_const,
24915 .is_volatile = field_ptr_info.flags.is_volatile,
24916 .is_allowzero = field_ptr_info.flags.is_allowzero,
24917 .address_space = field_ptr_info.flags.address_space,
2489524918 },
24919 .packed_offset = parent_ptr_ty.ptrInfo(mod).packed_offset,
2489624920 };
24921 const field_ty = parent_ty.structFieldType(field_index, mod);
24922 var actual_field_ptr_info: InternPool.Key.PtrType = .{
24923 .child = field_ty.toIntern(),
24924 .flags = .{
24925 .alignment = try field_ptr_ty.ptrAlignmentAdvanced(mod, sema),
24926 .is_const = field_ptr_info.flags.is_const,
24927 .is_volatile = field_ptr_info.flags.is_volatile,
24928 .is_allowzero = field_ptr_info.flags.is_allowzero,
24929 .address_space = field_ptr_info.flags.address_space,
24930 },
24931 .packed_offset = field_ptr_info.packed_offset,
24932 };
24933 switch (parent_ty.containerLayout(mod)) {
24934 .auto => {
24935 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(
24936 if (mod.typeToStruct(parent_ty)) |struct_obj| try sema.structFieldAlignment(
24937 struct_obj.fieldAlign(ip, field_index),
24938 field_ty,
24939 struct_obj.layout,
24940 ) else if (mod.typeToUnion(parent_ty)) |union_obj|
24941 try sema.unionFieldAlignment(union_obj, field_index)
24942 else
24943 actual_field_ptr_info.flags.alignment,
24944 );
2489724945
24898 if (parent_ty.containerLayout(mod) == .@"packed") {
24899 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});
24900 } else {
24901 ptr_ty_data.flags.alignment = blk: {
24902 if (mod.typeToStruct(parent_ty)) |struct_type| {
24903 break :blk struct_type.fieldAlign(ip, field_index);
24904 } else if (mod.typeToUnion(parent_ty)) |union_obj| {
24905 break :blk union_obj.fieldAlign(ip, field_index);
24906 } else {
24907 break :blk .none;
24908 }
24909 };
24910 }
24911
24912 const actual_field_ptr_ty = try sema.ptrType(ptr_ty_data);
24913 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, ptr_src);
24946 actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
24947 actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
24948 },
24949 .@"extern" => {
24950 const field_offset = parent_ty.structFieldOffset(field_index, mod);
24951 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (field_offset > 0)
24952 Alignment.fromLog2Units(@ctz(field_offset))
24953 else
24954 actual_field_ptr_info.flags.alignment);
2491424955
24915 ptr_ty_data.child = parent_ty.toIntern();
24916 const result_ptr = try sema.ptrType(ptr_ty_data);
24956 actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
24957 actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
24958 },
24959 .@"packed" => {
24960 const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) +
24961 (if (mod.typeToStruct(parent_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, field_index) else 0) -
24962 actual_field_ptr_info.packed_offset.bit_offset), 8) catch
24963 return sema.fail(block, inst_src, "pointer bit-offset mismatch", .{});
24964 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (byte_offset > 0)
24965 Alignment.fromLog2Units(@ctz(byte_offset))
24966 else
24967 actual_field_ptr_info.flags.alignment);
24968 },
24969 }
2491724970
24918 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
24971 const actual_field_ptr_ty = try sema.ptrType(actual_field_ptr_info);
24972 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src);
24973 const actual_parent_ptr_ty = try sema.ptrType(actual_parent_ptr_info);
24974 const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: {
2491924975 const field = switch (ip.indexToKey(field_ptr_val.toIntern())) {
2492024976 .ptr => |ptr| switch (ptr.addr) {
2492124977 .field => |field| field,
2492224978 else => null,
2492324979 },
2492424980 else => null,
24925 } orelse return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
24981 } orelse return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{});
2492624982
2492724983 if (field.index != field_index) {
24928 return sema.fail(block, src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{
24984 return sema.fail(block, inst_src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{
2492924985 field_name.fmt(ip), field_index, field.index, parent_ty.fmt(sema.mod),
2493024986 });
2493124987 }
24932 return Air.internedToRef(field.base);
24933 }
24934
24935 try sema.requireRuntimeBlock(block, src, ptr_src);
24936 try sema.queueFullTypeResolution(result_ptr);
24937 return block.addInst(.{
24938 .tag = .field_parent_ptr,
24939 .data = .{ .ty_pl = .{
24940 .ty = Air.internedToRef(result_ptr.toIntern()),
24941 .payload = try block.sema.addExtra(Air.FieldParentPtr{
24942 .field_ptr = casted_field_ptr,
24943 .field_index = @intCast(field_index),
24944 }),
24945 } },
24946 });
24988 break :result try sema.coerce(block, actual_parent_ptr_ty, Air.internedToRef(field.base), inst_src);
24989 } else result: {
24990 try sema.requireRuntimeBlock(block, inst_src, field_ptr_src);
24991 try sema.queueFullTypeResolution(parent_ty);
24992 break :result try block.addInst(.{
24993 .tag = .field_parent_ptr,
24994 .data = .{ .ty_pl = .{
24995 .ty = Air.internedToRef(actual_parent_ptr_ty.toIntern()),
24996 .payload = try block.sema.addExtra(Air.FieldParentPtr{
24997 .field_ptr = casted_field_ptr,
24998 .field_index = @intCast(field_index),
24999 }),
25000 } },
25001 });
25002 };
25003 return sema.coerce(block, parent_ptr_ty, result, inst_src);
2494725004}
2494825005
2494925006fn zirMinMax(
src/arch/x86_64/CodeGen.zig+18-19
......@@ -7920,17 +7920,14 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
79207920 const mod = self.bin_file.comp.module.?;
79217921 const ptr_field_ty = self.typeOfIndex(inst);
79227922 const ptr_container_ty = self.typeOf(operand);
7923 const ptr_container_ty_info = ptr_container_ty.ptrInfo(mod);
79247923 const container_ty = ptr_container_ty.childType(mod);
79257924
7926 const field_offset: i32 = if (mod.typeToPackedStruct(container_ty)) |struct_obj|
7927 if (ptr_field_ty.ptrInfo(mod).packed_offset.host_size == 0)
7928 @divExact(mod.structPackedFieldBitOffset(struct_obj, index) +
7929 ptr_container_ty_info.packed_offset.bit_offset, 8)
7930 else
7931 0
7932 else
7933 @intCast(container_ty.structFieldOffset(index, mod));
7925 const field_off: i32 = switch (container_ty.containerLayout(mod)) {
7926 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, mod)),
7927 .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(mod).packed_offset.bit_offset) +
7928 (if (mod.typeToStruct(container_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, index) else 0) -
7929 ptr_field_ty.ptrInfo(mod).packed_offset.bit_offset, 8),
7930 };
79347931
79357932 const src_mcv = try self.resolveInst(operand);
79367933 const dst_mcv = if (switch (src_mcv) {
......@@ -7938,7 +7935,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
79387935 .register, .register_offset => self.reuseOperand(inst, operand, 0, src_mcv),
79397936 else => false,
79407937 }) src_mcv else try self.copyToRegisterWithInstTracking(inst, ptr_field_ty, src_mcv);
7941 return dst_mcv.offset(field_offset);
7938 return dst_mcv.offset(field_off);
79427939}
79437940
79447941fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
......@@ -7958,11 +7955,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
79587955
79597956 const src_mcv = try self.resolveInst(operand);
79607957 const field_off: u32 = switch (container_ty.containerLayout(mod)) {
7961 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, mod) * 8),
7962 .@"packed" => if (mod.typeToStruct(container_ty)) |struct_type|
7963 mod.structPackedFieldBitOffset(struct_type, index)
7964 else
7965 0,
7958 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(extra.field_index, mod) * 8),
7959 .@"packed" => if (mod.typeToStruct(container_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0,
79667960 };
79677961
79687962 switch (src_mcv) {
......@@ -8239,7 +8233,12 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
82398233
82408234 const inst_ty = self.typeOfIndex(inst);
82418235 const parent_ty = inst_ty.childType(mod);
8242 const field_offset: i32 = @intCast(parent_ty.structFieldOffset(extra.field_index, mod));
8236 const field_off: i32 = switch (parent_ty.containerLayout(mod)) {
8237 .auto, .@"extern" => @intCast(parent_ty.structFieldOffset(extra.field_index, mod)),
8238 .@"packed" => @divExact(@as(i32, inst_ty.ptrInfo(mod).packed_offset.bit_offset) +
8239 (if (mod.typeToStruct(parent_ty)) |struct_obj| mod.structPackedFieldBitOffset(struct_obj, extra.field_index) else 0) -
8240 self.typeOf(extra.field_ptr).ptrInfo(mod).packed_offset.bit_offset, 8),
8241 };
82438242
82448243 const src_mcv = try self.resolveInst(extra.field_ptr);
82458244 const dst_mcv = if (src_mcv.isRegisterOffset() and
......@@ -8247,7 +8246,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
82478246 src_mcv
82488247 else
82498248 try self.copyToRegisterWithInstTracking(inst, inst_ty, src_mcv);
8250 const result = dst_mcv.offset(-field_offset);
8249 const result = dst_mcv.offset(-field_off);
82518250 return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none });
82528251}
82538252
......@@ -17950,7 +17949,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1795017949 .Struct => {
1795117950 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
1795217951 if (result_ty.containerLayout(mod) == .@"packed") {
17953 const struct_type = mod.typeToStruct(result_ty).?;
17952 const struct_obj = mod.typeToStruct(result_ty).?;
1795417953 try self.genInlineMemset(
1795517954 .{ .lea_frame = .{ .index = frame_index } },
1795617955 .{ .immediate = 0 },
......@@ -17971,7 +17970,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1797117970 }
1797217971 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod));
1797317972 const elem_abi_bits = elem_abi_size * 8;
17974 const elem_off = mod.structPackedFieldBitOffset(struct_type, elem_i);
17973 const elem_off = mod.structPackedFieldBitOffset(struct_obj, elem_i);
1797517974 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
1797617975 const elem_bit_off = elem_off % elem_abi_bits;
1797717976 const elem_mcv = try self.resolveInst(elem);
test/behavior/align.zig+1-1
......@@ -693,5 +693,5 @@ test "zero-bit fields in extern struct pad fields appropriately" {
693693 try expect(@intFromPtr(&s) % 2 == 0);
694694 try expect(@intFromPtr(&s.y) - @intFromPtr(&s.x) == 2);
695695 try expect(@intFromPtr(&s.y) == @intFromPtr(&s.a));
696 try expect(@fieldParentPtr(S, "a", &s.a) == &s);
696 try expect(@fieldParentPtr(*S, "a", &s.a) == &s);
697697}
test/behavior/field_parent_ptr.zig+1882-84
......@@ -1,126 +1,1924 @@
11const expect = @import("std").testing.expect;
22const builtin = @import("builtin");
33
4test "@fieldParentPtr non-first field" {
5 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4test "@fieldParentPtr struct" {
5 const C = struct {
6 a: bool = true,
7 b: f32 = 3.14,
8 c: struct { u8 } = .{42},
9 d: i32 = 12345,
10 };
711
8 try testParentFieldPtr(&foo.c);
9 try comptime testParentFieldPtr(&foo.c);
12 {
13 const c: C = .{ .a = false };
14 const pcf = &c.a;
15 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
16 try expect(pc == &c);
17 }
18 {
19 const c: C = .{ .a = false };
20 const pcf = &c.a;
21 var pc: *const C = undefined;
22 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
23 try expect(pc == &c);
24 }
25 {
26 const c: C = .{ .a = false };
27 var pcf: @TypeOf(&c.a) = undefined;
28 pcf = &c.a;
29 var pc: *const C = undefined;
30 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
31 try expect(pc == &c);
32 }
33 {
34 var c: C = undefined;
35 c = .{ .a = false };
36 var pcf: @TypeOf(&c.a) = undefined;
37 pcf = &c.a;
38 var pc: *C = undefined;
39 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
40 try expect(pc == &c);
41 }
42
43 {
44 const c: C = .{ .b = 666.667 };
45 const pcf = &c.b;
46 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
47 try expect(pc == &c);
48 }
49 {
50 const c: C = .{ .b = 666.667 };
51 const pcf = &c.b;
52 var pc: *const C = undefined;
53 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
54 try expect(pc == &c);
55 }
56 {
57 const c: C = .{ .b = 666.667 };
58 var pcf: @TypeOf(&c.b) = undefined;
59 pcf = &c.b;
60 var pc: *const C = undefined;
61 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
62 try expect(pc == &c);
63 }
64 {
65 var c: C = undefined;
66 c = .{ .b = 666.667 };
67 var pcf: @TypeOf(&c.b) = undefined;
68 pcf = &c.b;
69 var pc: *C = undefined;
70 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
71 try expect(pc == &c);
72 }
73
74 {
75 const c: C = .{ .c = .{255} };
76 const pcf = &c.c;
77 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
78 try expect(pc == &c);
79 }
80 {
81 const c: C = .{ .c = .{255} };
82 const pcf = &c.c;
83 var pc: *const C = undefined;
84 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
85 try expect(pc == &c);
86 }
87 {
88 const c: C = .{ .c = .{255} };
89 var pcf: @TypeOf(&c.c) = undefined;
90 pcf = &c.c;
91 var pc: *const C = undefined;
92 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
93 try expect(pc == &c);
94 }
95 {
96 var c: C = undefined;
97 c = .{ .c = .{255} };
98 var pcf: @TypeOf(&c.c) = undefined;
99 pcf = &c.c;
100 var pc: *C = undefined;
101 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
102 try expect(pc == &c);
103 }
104
105 {
106 const c: C = .{ .d = -1111111111 };
107 const pcf = &c.d;
108 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
109 try expect(pc == &c);
110 }
111 {
112 const c: C = .{ .d = -1111111111 };
113 const pcf = &c.d;
114 var pc: *const C = undefined;
115 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
116 try expect(pc == &c);
117 }
118 {
119 const c: C = .{ .d = -1111111111 };
120 var pcf: @TypeOf(&c.d) = undefined;
121 pcf = &c.d;
122 var pc: *const C = undefined;
123 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
124 try expect(pc == &c);
125 }
126 {
127 var c: C = undefined;
128 c = .{ .d = -1111111111 };
129 var pcf: @TypeOf(&c.d) = undefined;
130 pcf = &c.d;
131 var pc: *C = undefined;
132 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
133 try expect(pc == &c);
134 }
10135}
11136
12test "@fieldParentPtr first field" {
13 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137test "@fieldParentPtr extern struct" {
138 const C = extern struct {
139 a: bool = true,
140 b: f32 = 3.14,
141 c: extern struct { x: u8 } = .{ .x = 42 },
142 d: i32 = 12345,
143 };
144
145 {
146 const c: C = .{ .a = false };
147 const pcf = &c.a;
148 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
149 try expect(pc == &c);
150 }
151 {
152 const c: C = .{ .a = false };
153 const pcf = &c.a;
154 var pc: *const C = undefined;
155 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
156 try expect(pc == &c);
157 }
158 {
159 const c: C = .{ .a = false };
160 var pcf: @TypeOf(&c.a) = undefined;
161 pcf = &c.a;
162 var pc: *const C = undefined;
163 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
164 try expect(pc == &c);
165 }
166 {
167 var c: C = undefined;
168 c = .{ .a = false };
169 var pcf: @TypeOf(&c.a) = undefined;
170 pcf = &c.a;
171 var pc: *C = undefined;
172 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
173 try expect(pc == &c);
174 }
175
176 {
177 const c: C = .{ .b = 666.667 };
178 const pcf = &c.b;
179 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
180 try expect(pc == &c);
181 }
182 {
183 const c: C = .{ .b = 666.667 };
184 const pcf = &c.b;
185 var pc: *const C = undefined;
186 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
187 try expect(pc == &c);
188 }
189 {
190 const c: C = .{ .b = 666.667 };
191 var pcf: @TypeOf(&c.b) = undefined;
192 pcf = &c.b;
193 var pc: *const C = undefined;
194 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
195 try expect(pc == &c);
196 }
197 {
198 var c: C = undefined;
199 c = .{ .b = 666.667 };
200 var pcf: @TypeOf(&c.b) = undefined;
201 pcf = &c.b;
202 var pc: *C = undefined;
203 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
204 try expect(pc == &c);
205 }
15206
16 try testParentFieldPtrFirst(&foo.a);
17 try comptime testParentFieldPtrFirst(&foo.a);
207 {
208 const c: C = .{ .c = .{ .x = 255 } };
209 const pcf = &c.c;
210 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
211 try expect(pc == &c);
212 }
213 {
214 const c: C = .{ .c = .{ .x = 255 } };
215 const pcf = &c.c;
216 var pc: *const C = undefined;
217 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
218 try expect(pc == &c);
219 }
220 {
221 const c: C = .{ .c = .{ .x = 255 } };
222 var pcf: @TypeOf(&c.c) = undefined;
223 pcf = &c.c;
224 var pc: *const C = undefined;
225 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
226 try expect(pc == &c);
227 }
228 {
229 var c: C = undefined;
230 c = .{ .c = .{ .x = 255 } };
231 var pcf: @TypeOf(&c.c) = undefined;
232 pcf = &c.c;
233 var pc: *C = undefined;
234 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
235 try expect(pc == &c);
236 }
237
238 {
239 const c: C = .{ .d = -1111111111 };
240 const pcf = &c.d;
241 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
242 try expect(pc == &c);
243 }
244 {
245 const c: C = .{ .d = -1111111111 };
246 const pcf = &c.d;
247 var pc: *const C = undefined;
248 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
249 try expect(pc == &c);
250 }
251 {
252 const c: C = .{ .d = -1111111111 };
253 var pcf: @TypeOf(&c.d) = undefined;
254 pcf = &c.d;
255 var pc: *const C = undefined;
256 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
257 try expect(pc == &c);
258 }
259 {
260 var c: C = undefined;
261 c = .{ .d = -1111111111 };
262 var pcf: @TypeOf(&c.d) = undefined;
263 pcf = &c.d;
264 var pc: *C = undefined;
265 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
266 try expect(pc == &c);
267 }
18268}
19269
20const Foo = struct {
21 a: bool,
22 b: f32,
23 c: i32,
24 d: i32,
25};
270test "@fieldParentPtr extern struct first zero-bit field" {
271 const C = extern struct {
272 a: u0 = 0,
273 b: f32 = 3.14,
274 c: i32 = 12345,
275 };
26276
27const foo = Foo{
28 .a = true,
29 .b = 0.123,
30 .c = 1234,
31 .d = -10,
32};
277 {
278 const c: C = .{ .a = 0 };
279 const pcf = &c.a;
280 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
281 try expect(pc == &c);
282 }
283 {
284 const c: C = .{ .a = 0 };
285 const pcf = &c.a;
286 var pc: *const C = undefined;
287 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
288 try expect(pc == &c);
289 }
290 {
291 const c: C = .{ .a = 0 };
292 var pcf: @TypeOf(&c.a) = undefined;
293 pcf = &c.a;
294 var pc: *const C = undefined;
295 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
296 try expect(pc == &c);
297 }
298 {
299 var c: C = undefined;
300 c = .{ .a = 0 };
301 var pcf: @TypeOf(&c.a) = undefined;
302 pcf = &c.a;
303 var pc: *C = undefined;
304 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
305 try expect(pc == &c);
306 }
33307
34fn testParentFieldPtr(c: *const i32) !void {
35 try expect(c == &foo.c);
308 {
309 const c: C = .{ .b = 666.667 };
310 const pcf = &c.b;
311 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
312 try expect(pc == &c);
313 }
314 {
315 const c: C = .{ .b = 666.667 };
316 const pcf = &c.b;
317 var pc: *const C = undefined;
318 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
319 try expect(pc == &c);
320 }
321 {
322 const c: C = .{ .b = 666.667 };
323 var pcf: @TypeOf(&c.b) = undefined;
324 pcf = &c.b;
325 var pc: *const C = undefined;
326 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
327 try expect(pc == &c);
328 }
329 {
330 var c: C = undefined;
331 c = .{ .b = 666.667 };
332 var pcf: @TypeOf(&c.b) = undefined;
333 pcf = &c.b;
334 var pc: *C = undefined;
335 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
336 try expect(pc == &c);
337 }
36338
37 const base = @fieldParentPtr(Foo, "c", c);
38 try expect(base == &foo);
39 try expect(&base.c == c);
339 {
340 const c: C = .{ .c = -1111111111 };
341 const pcf = &c.c;
342 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
343 try expect(pc == &c);
344 }
345 {
346 const c: C = .{ .c = -1111111111 };
347 const pcf = &c.c;
348 var pc: *const C = undefined;
349 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
350 try expect(pc == &c);
351 }
352 {
353 const c: C = .{ .c = -1111111111 };
354 var pcf: @TypeOf(&c.c) = undefined;
355 pcf = &c.c;
356 var pc: *const C = undefined;
357 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
358 try expect(pc == &c);
359 }
360 {
361 var c: C = undefined;
362 c = .{ .c = -1111111111 };
363 var pcf: @TypeOf(&c.c) = undefined;
364 pcf = &c.c;
365 var pc: *C = undefined;
366 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
367 try expect(pc == &c);
368 }
40369}
41370
42fn testParentFieldPtrFirst(a: *const bool) !void {
43 try expect(a == &foo.a);
371test "@fieldParentPtr extern struct middle zero-bit field" {
372 const C = extern struct {
373 a: f32 = 3.14,
374 b: u0 = 0,
375 c: i32 = 12345,
376 };
377
378 {
379 const c: C = .{ .a = 666.667 };
380 const pcf = &c.a;
381 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
382 try expect(pc == &c);
383 }
384 {
385 const c: C = .{ .a = 666.667 };
386 const pcf = &c.a;
387 var pc: *const C = undefined;
388 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
389 try expect(pc == &c);
390 }
391 {
392 const c: C = .{ .a = 666.667 };
393 var pcf: @TypeOf(&c.a) = undefined;
394 pcf = &c.a;
395 var pc: *const C = undefined;
396 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
397 try expect(pc == &c);
398 }
399 {
400 var c: C = undefined;
401 c = .{ .a = 666.667 };
402 var pcf: @TypeOf(&c.a) = undefined;
403 pcf = &c.a;
404 var pc: *C = undefined;
405 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
406 try expect(pc == &c);
407 }
44408
45 const base = @fieldParentPtr(Foo, "a", a);
46 try expect(base == &foo);
47 try expect(&base.a == a);
409 {
410 const c: C = .{ .b = 0 };
411 const pcf = &c.b;
412 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
413 try expect(pc == &c);
414 }
415 {
416 const c: C = .{ .b = 0 };
417 const pcf = &c.b;
418 var pc: *const C = undefined;
419 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
420 try expect(pc == &c);
421 }
422 {
423 const c: C = .{ .b = 0 };
424 var pcf: @TypeOf(&c.b) = undefined;
425 pcf = &c.b;
426 var pc: *const C = undefined;
427 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
428 try expect(pc == &c);
429 }
430 {
431 var c: C = undefined;
432 c = .{ .b = 0 };
433 var pcf: @TypeOf(&c.b) = undefined;
434 pcf = &c.b;
435 var pc: *C = undefined;
436 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
437 try expect(pc == &c);
438 }
439
440 {
441 const c: C = .{ .c = -1111111111 };
442 const pcf = &c.c;
443 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
444 try expect(pc == &c);
445 }
446 {
447 const c: C = .{ .c = -1111111111 };
448 const pcf = &c.c;
449 var pc: *const C = undefined;
450 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
451 try expect(pc == &c);
452 }
453 {
454 const c: C = .{ .c = -1111111111 };
455 var pcf: @TypeOf(&c.c) = undefined;
456 pcf = &c.c;
457 var pc: *const C = undefined;
458 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
459 try expect(pc == &c);
460 }
461 {
462 var c: C = undefined;
463 c = .{ .c = -1111111111 };
464 var pcf: @TypeOf(&c.c) = undefined;
465 pcf = &c.c;
466 var pc: *C = undefined;
467 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
468 try expect(pc == &c);
469 }
48470}
49471
50test "@fieldParentPtr untagged union" {
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
472test "@fieldParentPtr extern struct last zero-bit field" {
473 const C = extern struct {
474 a: f32 = 3.14,
475 b: i32 = 12345,
476 c: u0 = 0,
477 };
478
479 {
480 const c: C = .{ .a = 666.667 };
481 const pcf = &c.a;
482 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
483 try expect(pc == &c);
484 }
485 {
486 const c: C = .{ .a = 666.667 };
487 const pcf = &c.a;
488 var pc: *const C = undefined;
489 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
490 try expect(pc == &c);
491 }
492 {
493 const c: C = .{ .a = 666.667 };
494 var pcf: @TypeOf(&c.a) = undefined;
495 pcf = &c.a;
496 var pc: *const C = undefined;
497 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
498 try expect(pc == &c);
499 }
500 {
501 var c: C = undefined;
502 c = .{ .a = 666.667 };
503 var pcf: @TypeOf(&c.a) = undefined;
504 pcf = &c.a;
505 var pc: *C = undefined;
506 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
507 try expect(pc == &c);
508 }
509
510 {
511 const c: C = .{ .b = -1111111111 };
512 const pcf = &c.b;
513 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
514 try expect(pc == &c);
515 }
516 {
517 const c: C = .{ .b = -1111111111 };
518 const pcf = &c.b;
519 var pc: *const C = undefined;
520 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
521 try expect(pc == &c);
522 }
523 {
524 const c: C = .{ .b = -1111111111 };
525 var pcf: @TypeOf(&c.b) = undefined;
526 pcf = &c.b;
527 var pc: *const C = undefined;
528 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
529 try expect(pc == &c);
530 }
531 {
532 var c: C = undefined;
533 c = .{ .b = -1111111111 };
534 var pcf: @TypeOf(&c.b) = undefined;
535 pcf = &c.b;
536 var pc: *C = undefined;
537 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
538 try expect(pc == &c);
539 }
540
541 {
542 const c: C = .{ .c = 0 };
543 const pcf = &c.c;
544 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
545 try expect(pc == &c);
546 }
547 {
548 const c: C = .{ .c = 0 };
549 const pcf = &c.c;
550 var pc: *const C = undefined;
551 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
552 try expect(pc == &c);
553 }
554 {
555 const c: C = .{ .c = 0 };
556 var pcf: @TypeOf(&c.c) = undefined;
557 pcf = &c.c;
558 var pc: *const C = undefined;
559 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
560 try expect(pc == &c);
561 }
562 {
563 var c: C = undefined;
564 c = .{ .c = 0 };
565 var pcf: @TypeOf(&c.c) = undefined;
566 pcf = &c.c;
567 var pc: *C = undefined;
568 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
569 try expect(pc == &c);
570 }
571}
572
573test "@fieldParentPtr unaligned packed struct" {
574 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
575 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
576 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
577
578 const C = packed struct {
579 a: bool = true,
580 b: f32 = 3.14,
581 c: packed struct { x: u8 } = .{ .x = 42 },
582 d: i32 = 12345,
583 };
584
585 {
586 const c: C = .{ .a = false };
587 const pcf = &c.a;
588 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
589 try expect(pc == &c);
590 }
591 {
592 const c: C = .{ .a = false };
593 const pcf = &c.a;
594 var pc: *const C = undefined;
595 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
596 try expect(pc == &c);
597 }
598 {
599 const c: C = .{ .a = false };
600 var pcf: @TypeOf(&c.a) = undefined;
601 pcf = &c.a;
602 var pc: *const C = undefined;
603 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
604 try expect(pc == &c);
605 }
606 {
607 var c: C = undefined;
608 c = .{ .a = false };
609 var pcf: @TypeOf(&c.a) = undefined;
610 pcf = &c.a;
611 var pc: *C = undefined;
612 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
613 try expect(pc == &c);
614 }
615
616 {
617 const c: C = .{ .b = 666.667 };
618 const pcf = &c.b;
619 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
620 try expect(pc == &c);
621 }
622 {
623 const c: C = .{ .b = 666.667 };
624 const pcf = &c.b;
625 var pc: *const C = undefined;
626 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
627 try expect(pc == &c);
628 }
629 {
630 const c: C = .{ .b = 666.667 };
631 var pcf: @TypeOf(&c.b) = undefined;
632 pcf = &c.b;
633 var pc: *const C = undefined;
634 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
635 try expect(pc == &c);
636 }
637 {
638 var c: C = undefined;
639 c = .{ .b = 666.667 };
640 var pcf: @TypeOf(&c.b) = undefined;
641 pcf = &c.b;
642 var pc: *C = undefined;
643 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
644 try expect(pc == &c);
645 }
54646
55 try testFieldParentPtrUnion(&bar.c);
56 try comptime testFieldParentPtrUnion(&bar.c);
647 {
648 const c: C = .{ .c = .{ .x = 255 } };
649 const pcf = &c.c;
650 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
651 try expect(pc == &c);
652 }
653 {
654 const c: C = .{ .c = .{ .x = 255 } };
655 const pcf = &c.c;
656 var pc: *const C = undefined;
657 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
658 try expect(pc == &c);
659 }
660 {
661 const c: C = .{ .c = .{ .x = 255 } };
662 var pcf: @TypeOf(&c.c) = undefined;
663 pcf = &c.c;
664 var pc: *const C = undefined;
665 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
666 try expect(pc == &c);
667 }
668 {
669 var c: C = undefined;
670 c = .{ .c = .{ .x = 255 } };
671 var pcf: @TypeOf(&c.c) = undefined;
672 pcf = &c.c;
673 var pc: *C = undefined;
674 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
675 try expect(pc == &c);
676 }
677
678 {
679 const c: C = .{ .d = -1111111111 };
680 const pcf = &c.d;
681 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
682 try expect(pc == &c);
683 }
684 {
685 const c: C = .{ .d = -1111111111 };
686 const pcf = &c.d;
687 var pc: *const C = undefined;
688 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
689 try expect(pc == &c);
690 }
691 {
692 const c: C = .{ .d = -1111111111 };
693 var pcf: @TypeOf(&c.d) = undefined;
694 pcf = &c.d;
695 var pc: *const C = undefined;
696 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
697 try expect(pc == &c);
698 }
699 {
700 var c: C = undefined;
701 c = .{ .d = -1111111111 };
702 var pcf: @TypeOf(&c.d) = undefined;
703 pcf = &c.d;
704 var pc: *C = undefined;
705 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
706 try expect(pc == &c);
707 }
57708}
58709
59const Bar = union(enum) {
60 a: bool,
61 b: f32,
62 c: i32,
63 d: i32,
64};
710test "@fieldParentPtr aligned packed struct" {
711 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
712 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
713 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
714
715 const C = packed struct {
716 a: f32 = 3.14,
717 b: i32 = 12345,
718 c: packed struct { x: u8 } = .{ .x = 42 },
719 d: bool = true,
720 };
721
722 {
723 const c: C = .{ .a = 666.667 };
724 const pcf = &c.a;
725 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
726 try expect(pc == &c);
727 }
728 {
729 const c: C = .{ .a = 666.667 };
730 const pcf = &c.a;
731 var pc: *const C = undefined;
732 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
733 try expect(pc == &c);
734 }
735 {
736 const c: C = .{ .a = 666.667 };
737 var pcf: @TypeOf(&c.a) = undefined;
738 pcf = &c.a;
739 var pc: *const C = undefined;
740 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
741 try expect(pc == &c);
742 }
743 {
744 var c: C = undefined;
745 c = .{ .a = 666.667 };
746 var pcf: @TypeOf(&c.a) = undefined;
747 pcf = &c.a;
748 var pc: *C = undefined;
749 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
750 try expect(pc == &c);
751 }
752
753 {
754 const c: C = .{ .b = -1111111111 };
755 const pcf = &c.b;
756 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
757 try expect(pc == &c);
758 }
759 {
760 const c: C = .{ .b = -1111111111 };
761 const pcf = &c.b;
762 var pc: *const C = undefined;
763 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
764 try expect(pc == &c);
765 }
766 {
767 const c: C = .{ .b = -1111111111 };
768 var pcf: @TypeOf(&c.b) = undefined;
769 pcf = &c.b;
770 var pc: *const C = undefined;
771 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
772 try expect(pc == &c);
773 }
774 {
775 var c: C = undefined;
776 c = .{ .b = -1111111111 };
777 var pcf: @TypeOf(&c.b) = undefined;
778 pcf = &c.b;
779 var pc: *C = undefined;
780 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
781 try expect(pc == &c);
782 }
783
784 {
785 const c: C = .{ .c = .{ .x = 255 } };
786 const pcf = &c.c;
787 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
788 try expect(pc == &c);
789 }
790 {
791 const c: C = .{ .c = .{ .x = 255 } };
792 const pcf = &c.c;
793 var pc: *const C = undefined;
794 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
795 try expect(pc == &c);
796 }
797 {
798 const c: C = .{ .c = .{ .x = 255 } };
799 var pcf: @TypeOf(&c.c) = undefined;
800 pcf = &c.c;
801 var pc: *const C = undefined;
802 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
803 try expect(pc == &c);
804 }
805 {
806 var c: C = undefined;
807 c = .{ .c = .{ .x = 255 } };
808 var pcf: @TypeOf(&c.c) = undefined;
809 pcf = &c.c;
810 var pc: *C = undefined;
811 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
812 try expect(pc == &c);
813 }
814
815 {
816 const c: C = .{ .d = false };
817 const pcf = &c.d;
818 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
819 try expect(pc == &c);
820 }
821 {
822 const c: C = .{ .d = false };
823 const pcf = &c.d;
824 var pc: *const C = undefined;
825 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
826 try expect(pc == &c);
827 }
828 {
829 const c: C = .{ .d = false };
830 var pcf: @TypeOf(&c.d) = undefined;
831 pcf = &c.d;
832 var pc: *const C = undefined;
833 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
834 try expect(pc == &c);
835 }
836 {
837 var c: C = undefined;
838 c = .{ .d = false };
839 var pcf: @TypeOf(&c.d) = undefined;
840 pcf = &c.d;
841 var pc: *C = undefined;
842 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
843 try expect(pc == &c);
844 }
845}
846
847test "@fieldParentPtr nested packed struct" {
848 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
849 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
850
851 {
852 const C = packed struct {
853 a: u8,
854 b: packed struct {
855 a: u8,
856 b: packed struct {
857 a: u8,
858 },
859 },
860 };
861
862 {
863 const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
864 const pcbba = &c.b.b.a;
865 const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr(*align(1) const @TypeOf(c.b.b), "a", pcbba));
866 try expect(pcbb == &c.b.b);
867 const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr(*align(1) const @TypeOf(c.b), "b", pcbb));
868 try expect(pcb == &c.b);
869 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcb));
870 try expect(pc == &c);
871 }
872
873 {
874 var c: C = undefined;
875 c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
876 var pcbba: @TypeOf(&c.b.b.a) = undefined;
877 pcbba = &c.b.b.a;
878 var pcbb: @TypeOf(&c.b.b) = undefined;
879 pcbb = @alignCast(@fieldParentPtr(*align(1) @TypeOf(c.b.b), "a", pcbba));
880 try expect(pcbb == &c.b.b);
881 var pcb: @TypeOf(&c.b) = undefined;
882 pcb = @alignCast(@fieldParentPtr(*align(1) @TypeOf(c.b), "b", pcbb));
883 try expect(pcb == &c.b);
884 var pc: *C = undefined;
885 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcb));
886 try expect(pc == &c);
887 }
888 }
889
890 {
891 const C = packed struct {
892 a: u8,
893 b: packed struct {
894 a: u9,
895 b: packed struct {
896 a: u8,
897 },
898 },
899 };
900
901 {
902 const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
903 const pcbba = &c.b.b.a;
904 const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr(*align(1:17:4) const @TypeOf(c.b.b), "a", pcbba));
905 try expect(pcbb == &c.b.b);
906 const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr(*align(1:8:4) const @TypeOf(c.b), "b", pcbb));
907 try expect(pcb == &c.b);
908 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcb));
909 try expect(pc == &c);
910 }
911
912 {
913 var c: C = undefined;
914 c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
915 var pcbba: @TypeOf(&c.b.b.a) = undefined;
916 pcbba = &c.b.b.a;
917 var pcbb: @TypeOf(&c.b.b) = undefined;
918 pcbb = @alignCast(@fieldParentPtr(*align(1:17:4) @TypeOf(c.b.b), "a", pcbba));
919 try expect(pcbb == &c.b.b);
920 var pcb: @TypeOf(&c.b) = undefined;
921 pcb = @alignCast(@fieldParentPtr(*align(1:8:4) @TypeOf(c.b), "b", pcbb));
922 try expect(pcb == &c.b);
923 var pc: *C = undefined;
924 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcb));
925 try expect(pc == &c);
926 }
927 }
928
929 {
930 const C = packed struct {
931 a: u9,
932 b: packed struct {
933 a: u7,
934 b: packed struct {
935 a: u8,
936 },
937 },
938 };
939
940 {
941 const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
942 const pcbba = &c.b.b.a;
943 const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr(*align(1) const @TypeOf(c.b.b), "a", pcbba));
944 try expect(pcbb == &c.b.b);
945 const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr(*align(1:9:3) const @TypeOf(c.b), "b", pcbb));
946 try expect(pcb == &c.b);
947 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcb));
948 try expect(pc == &c);
949 }
950
951 {
952 var c: C = undefined;
953 c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
954 var pcbba: @TypeOf(&c.b.b.a) = undefined;
955 pcbba = &c.b.b.a;
956 var pcbb: @TypeOf(&c.b.b) = undefined;
957 pcbb = @alignCast(@fieldParentPtr(*align(1) @TypeOf(c.b.b), "a", pcbba));
958 try expect(pcbb == &c.b.b);
959 var pcb: @TypeOf(&c.b) = undefined;
960 pcb = @alignCast(@fieldParentPtr(*align(1:9:3) @TypeOf(c.b), "b", pcbb));
961 try expect(pcb == &c.b);
962 var pc: *C = undefined;
963 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcb));
964 try expect(pc == &c);
965 }
966 }
65967
66const bar = Bar{ .c = 42 };
968 {
969 const C = packed struct {
970 a: u9,
971 b: packed struct {
972 a: u8,
973 b: packed struct {
974 a: u8,
975 },
976 },
977 };
67978
68fn testFieldParentPtrUnion(c: *const i32) !void {
69 try expect(c == &bar.c);
979 {
980 const c: C = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
981 const pcbba = &c.b.b.a;
982 const pcbb: @TypeOf(&c.b.b) = @alignCast(@fieldParentPtr(*align(1:17:4) const @TypeOf(c.b.b), "a", pcbba));
983 try expect(pcbb == &c.b.b);
984 const pcb: @TypeOf(&c.b) = @alignCast(@fieldParentPtr(*align(1:9:4) const @TypeOf(c.b), "b", pcbb));
985 try expect(pcb == &c.b);
986 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcb));
987 try expect(pc == &c);
988 }
70989
71 const base = @fieldParentPtr(Bar, "c", c);
72 try expect(base == &bar);
73 try expect(&base.c == c);
990 {
991 var c: C = undefined;
992 c = .{ .a = 0, .b = .{ .a = 0, .b = .{ .a = 0 } } };
993 var pcbba: @TypeOf(&c.b.b.a) = undefined;
994 pcbba = &c.b.b.a;
995 var pcbb: @TypeOf(&c.b.b) = undefined;
996 pcbb = @alignCast(@fieldParentPtr(*align(1:17:4) @TypeOf(c.b.b), "a", pcbba));
997 try expect(pcbb == &c.b.b);
998 var pcb: @TypeOf(&c.b) = undefined;
999 pcb = @alignCast(@fieldParentPtr(*align(1:9:4) @TypeOf(c.b), "b", pcbb));
1000 try expect(pcb == &c.b);
1001 var pc: *C = undefined;
1002 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcb));
1003 try expect(pc == &c);
1004 }
1005 }
1006}
1007
1008test "@fieldParentPtr packed struct first zero-bit field" {
1009 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1011
1012 const C = packed struct {
1013 a: u0 = 0,
1014 b: f32 = 3.14,
1015 c: i32 = 12345,
1016 };
1017
1018 {
1019 const c: C = .{ .a = 0 };
1020 const pcf = &c.a;
1021 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1022 try expect(pc == &c);
1023 }
1024 {
1025 const c: C = .{ .a = 0 };
1026 const pcf = &c.a;
1027 var pc: *const C = undefined;
1028 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1029 try expect(pc == &c);
1030 }
1031 {
1032 const c: C = .{ .a = 0 };
1033 var pcf: @TypeOf(&c.a) = undefined;
1034 pcf = &c.a;
1035 var pc: *const C = undefined;
1036 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1037 try expect(pc == &c);
1038 }
1039 {
1040 var c: C = undefined;
1041 c = .{ .a = 0 };
1042 var pcf: @TypeOf(&c.a) = undefined;
1043 pcf = &c.a;
1044 var pc: *C = undefined;
1045 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1046 try expect(pc == &c);
1047 }
1048
1049 {
1050 const c: C = .{ .b = 666.667 };
1051 const pcf = &c.b;
1052 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1053 try expect(pc == &c);
1054 }
1055 {
1056 const c: C = .{ .b = 666.667 };
1057 const pcf = &c.b;
1058 var pc: *const C = undefined;
1059 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1060 try expect(pc == &c);
1061 }
1062 {
1063 const c: C = .{ .b = 666.667 };
1064 var pcf: @TypeOf(&c.b) = undefined;
1065 pcf = &c.b;
1066 var pc: *const C = undefined;
1067 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1068 try expect(pc == &c);
1069 }
1070 {
1071 var c: C = undefined;
1072 c = .{ .b = 666.667 };
1073 var pcf: @TypeOf(&c.b) = undefined;
1074 pcf = &c.b;
1075 var pc: *C = undefined;
1076 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1077 try expect(pc == &c);
1078 }
1079
1080 {
1081 const c: C = .{ .c = -1111111111 };
1082 const pcf = &c.c;
1083 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1084 try expect(pc == &c);
1085 }
1086 {
1087 const c: C = .{ .c = -1111111111 };
1088 const pcf = &c.c;
1089 var pc: *const C = undefined;
1090 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1091 try expect(pc == &c);
1092 }
1093 {
1094 const c: C = .{ .c = -1111111111 };
1095 var pcf: @TypeOf(&c.c) = undefined;
1096 pcf = &c.c;
1097 var pc: *const C = undefined;
1098 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1099 try expect(pc == &c);
1100 }
1101 {
1102 var c: C = undefined;
1103 c = .{ .c = -1111111111 };
1104 var pcf: @TypeOf(&c.c) = undefined;
1105 pcf = &c.c;
1106 var pc: *C = undefined;
1107 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
1108 try expect(pc == &c);
1109 }
1110}
1111
1112test "@fieldParentPtr packed struct middle zero-bit field" {
1113 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1114 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1115
1116 const C = packed struct {
1117 a: f32 = 3.14,
1118 b: u0 = 0,
1119 c: i32 = 12345,
1120 };
1121
1122 {
1123 const c: C = .{ .a = 666.667 };
1124 const pcf = &c.a;
1125 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1126 try expect(pc == &c);
1127 }
1128 {
1129 const c: C = .{ .a = 666.667 };
1130 const pcf = &c.a;
1131 var pc: *const C = undefined;
1132 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1133 try expect(pc == &c);
1134 }
1135 {
1136 const c: C = .{ .a = 666.667 };
1137 var pcf: @TypeOf(&c.a) = undefined;
1138 pcf = &c.a;
1139 var pc: *const C = undefined;
1140 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1141 try expect(pc == &c);
1142 }
1143 {
1144 var c: C = undefined;
1145 c = .{ .a = 666.667 };
1146 var pcf: @TypeOf(&c.a) = undefined;
1147 pcf = &c.a;
1148 var pc: *C = undefined;
1149 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1150 try expect(pc == &c);
1151 }
1152
1153 {
1154 const c: C = .{ .b = 0 };
1155 const pcf = &c.b;
1156 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1157 try expect(pc == &c);
1158 }
1159 {
1160 const c: C = .{ .b = 0 };
1161 const pcf = &c.b;
1162 var pc: *const C = undefined;
1163 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1164 try expect(pc == &c);
1165 }
1166 {
1167 const c: C = .{ .b = 0 };
1168 var pcf: @TypeOf(&c.b) = undefined;
1169 pcf = &c.b;
1170 var pc: *const C = undefined;
1171 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1172 try expect(pc == &c);
1173 }
1174 {
1175 var c: C = undefined;
1176 c = .{ .b = 0 };
1177 var pcf: @TypeOf(&c.b) = undefined;
1178 pcf = &c.b;
1179 var pc: *C = undefined;
1180 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1181 try expect(pc == &c);
1182 }
1183
1184 {
1185 const c: C = .{ .c = -1111111111 };
1186 const pcf = &c.c;
1187 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1188 try expect(pc == &c);
1189 }
1190 {
1191 const c: C = .{ .c = -1111111111 };
1192 const pcf = &c.c;
1193 var pc: *const C = undefined;
1194 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1195 try expect(pc == &c);
1196 }
1197 {
1198 const c: C = .{ .c = -1111111111 };
1199 var pcf: @TypeOf(&c.c) = undefined;
1200 pcf = &c.c;
1201 var pc: *const C = undefined;
1202 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1203 try expect(pc == &c);
1204 }
1205 {
1206 var c: C = undefined;
1207 c = .{ .c = -1111111111 };
1208 var pcf: @TypeOf(&c.c) = undefined;
1209 pcf = &c.c;
1210 var pc: *C = undefined;
1211 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
1212 try expect(pc == &c);
1213 }
1214}
1215
1216test "@fieldParentPtr packed struct last zero-bit field" {
1217 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1218 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1219
1220 const C = packed struct {
1221 a: f32 = 3.14,
1222 b: i32 = 12345,
1223 c: u0 = 0,
1224 };
1225
1226 {
1227 const c: C = .{ .a = 666.667 };
1228 const pcf = &c.a;
1229 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1230 try expect(pc == &c);
1231 }
1232 {
1233 const c: C = .{ .a = 666.667 };
1234 const pcf = &c.a;
1235 var pc: *const C = undefined;
1236 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1237 try expect(pc == &c);
1238 }
1239 {
1240 const c: C = .{ .a = 666.667 };
1241 var pcf: @TypeOf(&c.a) = undefined;
1242 pcf = &c.a;
1243 var pc: *const C = undefined;
1244 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1245 try expect(pc == &c);
1246 }
1247 {
1248 var c: C = undefined;
1249 c = .{ .a = 666.667 };
1250 var pcf: @TypeOf(&c.a) = undefined;
1251 pcf = &c.a;
1252 var pc: *C = undefined;
1253 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1254 try expect(pc == &c);
1255 }
1256
1257 {
1258 const c: C = .{ .b = -1111111111 };
1259 const pcf = &c.b;
1260 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1261 try expect(pc == &c);
1262 }
1263 {
1264 const c: C = .{ .b = -1111111111 };
1265 const pcf = &c.b;
1266 var pc: *const C = undefined;
1267 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1268 try expect(pc == &c);
1269 }
1270 {
1271 const c: C = .{ .b = -1111111111 };
1272 var pcf: @TypeOf(&c.b) = undefined;
1273 pcf = &c.b;
1274 var pc: *const C = undefined;
1275 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1276 try expect(pc == &c);
1277 }
1278 {
1279 var c: C = undefined;
1280 c = .{ .b = -1111111111 };
1281 var pcf: @TypeOf(&c.b) = undefined;
1282 pcf = &c.b;
1283 var pc: *C = undefined;
1284 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1285 try expect(pc == &c);
1286 }
1287
1288 {
1289 const c: C = .{ .c = 0 };
1290 const pcf = &c.c;
1291 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1292 try expect(pc == &c);
1293 }
1294 {
1295 const c: C = .{ .c = 0 };
1296 const pcf = &c.c;
1297 var pc: *const C = undefined;
1298 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1299 try expect(pc == &c);
1300 }
1301 {
1302 const c: C = .{ .c = 0 };
1303 var pcf: @TypeOf(&c.c) = undefined;
1304 pcf = &c.c;
1305 var pc: *const C = undefined;
1306 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1307 try expect(pc == &c);
1308 }
1309 {
1310 var c: C = undefined;
1311 c = .{ .c = 0 };
1312 var pcf: @TypeOf(&c.c) = undefined;
1313 pcf = &c.c;
1314 var pc: *C = undefined;
1315 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
1316 try expect(pc == &c);
1317 }
741318}
751319
761320test "@fieldParentPtr tagged union" {
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1321 const C = union(enum) {
1322 a: bool,
1323 b: f32,
1324 c: struct { u8 },
1325 d: i32,
1326 };
1327
1328 {
1329 const c: C = .{ .a = false };
1330 const pcf = &c.a;
1331 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1332 try expect(pc == &c);
1333 }
1334 {
1335 const c: C = .{ .a = false };
1336 const pcf = &c.a;
1337 var pc: *const C = undefined;
1338 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1339 try expect(pc == &c);
1340 }
1341 {
1342 const c: C = .{ .a = false };
1343 var pcf: @TypeOf(&c.a) = undefined;
1344 pcf = &c.a;
1345 var pc: *const C = undefined;
1346 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1347 try expect(pc == &c);
1348 }
1349 {
1350 var c: C = undefined;
1351 c = .{ .a = false };
1352 var pcf: @TypeOf(&c.a) = undefined;
1353 pcf = &c.a;
1354 var pc: *C = undefined;
1355 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1356 try expect(pc == &c);
1357 }
1358
1359 {
1360 const c: C = .{ .b = 0 };
1361 const pcf = &c.b;
1362 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1363 try expect(pc == &c);
1364 }
1365 {
1366 const c: C = .{ .b = 0 };
1367 const pcf = &c.b;
1368 var pc: *const C = undefined;
1369 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1370 try expect(pc == &c);
1371 }
1372 {
1373 const c: C = .{ .b = 0 };
1374 var pcf: @TypeOf(&c.b) = undefined;
1375 pcf = &c.b;
1376 var pc: *const C = undefined;
1377 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1378 try expect(pc == &c);
1379 }
1380 {
1381 var c: C = undefined;
1382 c = .{ .b = 0 };
1383 var pcf: @TypeOf(&c.b) = undefined;
1384 pcf = &c.b;
1385 var pc: *C = undefined;
1386 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1387 try expect(pc == &c);
1388 }
1389
1390 {
1391 const c: C = .{ .c = .{255} };
1392 const pcf = &c.c;
1393 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1394 try expect(pc == &c);
1395 }
1396 {
1397 const c: C = .{ .c = .{255} };
1398 const pcf = &c.c;
1399 var pc: *const C = undefined;
1400 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1401 try expect(pc == &c);
1402 }
1403 {
1404 const c: C = .{ .c = .{255} };
1405 var pcf: @TypeOf(&c.c) = undefined;
1406 pcf = &c.c;
1407 var pc: *const C = undefined;
1408 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1409 try expect(pc == &c);
1410 }
1411 {
1412 var c: C = undefined;
1413 c = .{ .c = .{255} };
1414 var pcf: @TypeOf(&c.c) = undefined;
1415 pcf = &c.c;
1416 var pc: *C = undefined;
1417 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
1418 try expect(pc == &c);
1419 }
801420
81 try testFieldParentPtrTaggedUnion(&bar_tagged.c);
82 try comptime testFieldParentPtrTaggedUnion(&bar_tagged.c);
1421 {
1422 const c: C = .{ .d = -1111111111 };
1423 const pcf = &c.d;
1424 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1425 try expect(pc == &c);
1426 }
1427 {
1428 const c: C = .{ .d = -1111111111 };
1429 const pcf = &c.d;
1430 var pc: *const C = undefined;
1431 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1432 try expect(pc == &c);
1433 }
1434 {
1435 const c: C = .{ .d = -1111111111 };
1436 var pcf: @TypeOf(&c.d) = undefined;
1437 pcf = &c.d;
1438 var pc: *const C = undefined;
1439 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1440 try expect(pc == &c);
1441 }
1442 {
1443 var c: C = undefined;
1444 c = .{ .d = -1111111111 };
1445 var pcf: @TypeOf(&c.d) = undefined;
1446 pcf = &c.d;
1447 var pc: *C = undefined;
1448 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
1449 try expect(pc == &c);
1450 }
831451}
841452
85const BarTagged = union(enum) {
86 a: bool,
87 b: f32,
88 c: i32,
89 d: i32,
90};
1453test "@fieldParentPtr untagged union" {
1454 const C = union {
1455 a: bool,
1456 b: f32,
1457 c: struct { u8 },
1458 d: i32,
1459 };
1460
1461 {
1462 const c: C = .{ .a = false };
1463 const pcf = &c.a;
1464 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1465 try expect(pc == &c);
1466 }
1467 {
1468 const c: C = .{ .a = false };
1469 const pcf = &c.a;
1470 var pc: *const C = undefined;
1471 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1472 try expect(pc == &c);
1473 }
1474 {
1475 const c: C = .{ .a = false };
1476 var pcf: @TypeOf(&c.a) = undefined;
1477 pcf = &c.a;
1478 var pc: *const C = undefined;
1479 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1480 try expect(pc == &c);
1481 }
1482 {
1483 var c: C = undefined;
1484 c = .{ .a = false };
1485 var pcf: @TypeOf(&c.a) = undefined;
1486 pcf = &c.a;
1487 var pc: *C = undefined;
1488 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1489 try expect(pc == &c);
1490 }
911491
92const bar_tagged = BarTagged{ .c = 42 };
1492 {
1493 const c: C = .{ .b = 0 };
1494 const pcf = &c.b;
1495 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1496 try expect(pc == &c);
1497 }
1498 {
1499 const c: C = .{ .b = 0 };
1500 const pcf = &c.b;
1501 var pc: *const C = undefined;
1502 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1503 try expect(pc == &c);
1504 }
1505 {
1506 const c: C = .{ .b = 0 };
1507 var pcf: @TypeOf(&c.b) = undefined;
1508 pcf = &c.b;
1509 var pc: *const C = undefined;
1510 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1511 try expect(pc == &c);
1512 }
1513 {
1514 var c: C = undefined;
1515 c = .{ .b = 0 };
1516 var pcf: @TypeOf(&c.b) = undefined;
1517 pcf = &c.b;
1518 var pc: *C = undefined;
1519 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1520 try expect(pc == &c);
1521 }
931522
94fn testFieldParentPtrTaggedUnion(c: *const i32) !void {
95 try expect(c == &bar_tagged.c);
1523 {
1524 const c: C = .{ .c = .{255} };
1525 const pcf = &c.c;
1526 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1527 try expect(pc == &c);
1528 }
1529 {
1530 const c: C = .{ .c = .{255} };
1531 const pcf = &c.c;
1532 var pc: *const C = undefined;
1533 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1534 try expect(pc == &c);
1535 }
1536 {
1537 const c: C = .{ .c = .{255} };
1538 var pcf: @TypeOf(&c.c) = undefined;
1539 pcf = &c.c;
1540 var pc: *const C = undefined;
1541 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1542 try expect(pc == &c);
1543 }
1544 {
1545 var c: C = undefined;
1546 c = .{ .c = .{255} };
1547 var pcf: @TypeOf(&c.c) = undefined;
1548 pcf = &c.c;
1549 var pc: *C = undefined;
1550 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
1551 try expect(pc == &c);
1552 }
961553
97 const base = @fieldParentPtr(BarTagged, "c", c);
98 try expect(base == &bar_tagged);
99 try expect(&base.c == c);
1554 {
1555 const c: C = .{ .d = -1111111111 };
1556 const pcf = &c.d;
1557 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1558 try expect(pc == &c);
1559 }
1560 {
1561 const c: C = .{ .d = -1111111111 };
1562 const pcf = &c.d;
1563 var pc: *const C = undefined;
1564 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1565 try expect(pc == &c);
1566 }
1567 {
1568 const c: C = .{ .d = -1111111111 };
1569 var pcf: @TypeOf(&c.d) = undefined;
1570 pcf = &c.d;
1571 var pc: *const C = undefined;
1572 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1573 try expect(pc == &c);
1574 }
1575 {
1576 var c: C = undefined;
1577 c = .{ .d = -1111111111 };
1578 var pcf: @TypeOf(&c.d) = undefined;
1579 pcf = &c.d;
1580 var pc: *C = undefined;
1581 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
1582 try expect(pc == &c);
1583 }
1001584}
1011585
1021586test "@fieldParentPtr extern union" {
103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1587 const C = extern union {
1588 a: bool,
1589 b: f32,
1590 c: extern struct { x: u8 },
1591 d: i32,
1592 };
1593
1594 {
1595 const c: C = .{ .a = false };
1596 const pcf = &c.a;
1597 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1598 try expect(pc == &c);
1599 }
1600 {
1601 const c: C = .{ .a = false };
1602 const pcf = &c.a;
1603 var pc: *const C = undefined;
1604 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1605 try expect(pc == &c);
1606 }
1607 {
1608 const c: C = .{ .a = false };
1609 var pcf: @TypeOf(&c.a) = undefined;
1610 pcf = &c.a;
1611 var pc: *const C = undefined;
1612 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1613 try expect(pc == &c);
1614 }
1615 {
1616 var c: C = undefined;
1617 c = .{ .a = false };
1618 var pcf: @TypeOf(&c.a) = undefined;
1619 pcf = &c.a;
1620 var pc: *C = undefined;
1621 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1622 try expect(pc == &c);
1623 }
1624
1625 {
1626 const c: C = .{ .b = 0 };
1627 const pcf = &c.b;
1628 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1629 try expect(pc == &c);
1630 }
1631 {
1632 const c: C = .{ .b = 0 };
1633 const pcf = &c.b;
1634 var pc: *const C = undefined;
1635 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1636 try expect(pc == &c);
1637 }
1638 {
1639 const c: C = .{ .b = 0 };
1640 var pcf: @TypeOf(&c.b) = undefined;
1641 pcf = &c.b;
1642 var pc: *const C = undefined;
1643 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1644 try expect(pc == &c);
1645 }
1646 {
1647 var c: C = undefined;
1648 c = .{ .b = 0 };
1649 var pcf: @TypeOf(&c.b) = undefined;
1650 pcf = &c.b;
1651 var pc: *C = undefined;
1652 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1653 try expect(pc == &c);
1654 }
1655
1656 {
1657 const c: C = .{ .c = .{ .x = 255 } };
1658 const pcf = &c.c;
1659 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1660 try expect(pc == &c);
1661 }
1662 {
1663 const c: C = .{ .c = .{ .x = 255 } };
1664 const pcf = &c.c;
1665 var pc: *const C = undefined;
1666 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1667 try expect(pc == &c);
1668 }
1669 {
1670 const c: C = .{ .c = .{ .x = 255 } };
1671 var pcf: @TypeOf(&c.c) = undefined;
1672 pcf = &c.c;
1673 var pc: *const C = undefined;
1674 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1675 try expect(pc == &c);
1676 }
1677 {
1678 var c: C = undefined;
1679 c = .{ .c = .{ .x = 255 } };
1680 var pcf: @TypeOf(&c.c) = undefined;
1681 pcf = &c.c;
1682 var pc: *C = undefined;
1683 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
1684 try expect(pc == &c);
1685 }
1686
1687 {
1688 const c: C = .{ .d = -1111111111 };
1689 const pcf = &c.d;
1690 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1691 try expect(pc == &c);
1692 }
1693 {
1694 const c: C = .{ .d = -1111111111 };
1695 const pcf = &c.d;
1696 var pc: *const C = undefined;
1697 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1698 try expect(pc == &c);
1699 }
1700 {
1701 const c: C = .{ .d = -1111111111 };
1702 var pcf: @TypeOf(&c.d) = undefined;
1703 pcf = &c.d;
1704 var pc: *const C = undefined;
1705 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1706 try expect(pc == &c);
1707 }
1708 {
1709 var c: C = undefined;
1710 c = .{ .d = -1111111111 };
1711 var pcf: @TypeOf(&c.d) = undefined;
1712 pcf = &c.d;
1713 var pc: *C = undefined;
1714 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
1715 try expect(pc == &c);
1716 }
1717}
1718
1719test "@fieldParentPtr packed union" {
1720 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1721
1722 const C = packed union {
1723 a: bool,
1724 b: f32,
1725 c: packed struct { x: u8 },
1726 d: i32,
1727 };
1728
1729 {
1730 const c: C = .{ .a = false };
1731 const pcf = &c.a;
1732 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1733 try expect(pc == &c);
1734 }
1735 {
1736 const c: C = .{ .a = false };
1737 const pcf = &c.a;
1738 var pc: *const C = undefined;
1739 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1740 try expect(pc == &c);
1741 }
1742 {
1743 const c: C = .{ .a = false };
1744 var pcf: @TypeOf(&c.a) = undefined;
1745 pcf = &c.a;
1746 var pc: *const C = undefined;
1747 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1748 try expect(pc == &c);
1749 }
1750 {
1751 var c: C = undefined;
1752 c = .{ .a = false };
1753 var pcf: @TypeOf(&c.a) = undefined;
1754 pcf = &c.a;
1755 var pc: *C = undefined;
1756 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1757 try expect(pc == &c);
1758 }
1759
1760 {
1761 const c: C = .{ .b = 0 };
1762 const pcf = &c.b;
1763 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1764 try expect(pc == &c);
1765 }
1766 {
1767 const c: C = .{ .b = 0 };
1768 const pcf = &c.b;
1769 var pc: *const C = undefined;
1770 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1771 try expect(pc == &c);
1772 }
1773 {
1774 const c: C = .{ .b = 0 };
1775 var pcf: @TypeOf(&c.b) = undefined;
1776 pcf = &c.b;
1777 var pc: *const C = undefined;
1778 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1779 try expect(pc == &c);
1780 }
1781 {
1782 var c: C = undefined;
1783 c = .{ .b = 0 };
1784 var pcf: @TypeOf(&c.b) = undefined;
1785 pcf = &c.b;
1786 var pc: *C = undefined;
1787 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1788 try expect(pc == &c);
1789 }
1790
1791 {
1792 const c: C = .{ .c = .{ .x = 255 } };
1793 const pcf = &c.c;
1794 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1795 try expect(pc == &c);
1796 }
1797 {
1798 const c: C = .{ .c = .{ .x = 255 } };
1799 const pcf = &c.c;
1800 var pc: *const C = undefined;
1801 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1802 try expect(pc == &c);
1803 }
1804 {
1805 const c: C = .{ .c = .{ .x = 255 } };
1806 var pcf: @TypeOf(&c.c) = undefined;
1807 pcf = &c.c;
1808 var pc: *const C = undefined;
1809 pc = @alignCast(@fieldParentPtr(*align(1) const C, "c", pcf));
1810 try expect(pc == &c);
1811 }
1812 {
1813 var c: C = undefined;
1814 c = .{ .c = .{ .x = 255 } };
1815 var pcf: @TypeOf(&c.c) = undefined;
1816 pcf = &c.c;
1817 var pc: *C = undefined;
1818 pc = @alignCast(@fieldParentPtr(*align(1) C, "c", pcf));
1819 try expect(pc == &c);
1820 }
1061821
107 try testFieldParentPtrExternUnion(&bar_extern.c);
108 try comptime testFieldParentPtrExternUnion(&bar_extern.c);
1822 {
1823 const c: C = .{ .d = -1111111111 };
1824 const pcf = &c.d;
1825 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1826 try expect(pc == &c);
1827 }
1828 {
1829 const c: C = .{ .d = -1111111111 };
1830 const pcf = &c.d;
1831 var pc: *const C = undefined;
1832 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1833 try expect(pc == &c);
1834 }
1835 {
1836 const c: C = .{ .d = -1111111111 };
1837 var pcf: @TypeOf(&c.d) = undefined;
1838 pcf = &c.d;
1839 var pc: *const C = undefined;
1840 pc = @alignCast(@fieldParentPtr(*align(1) const C, "d", pcf));
1841 try expect(pc == &c);
1842 }
1843 {
1844 var c: C = undefined;
1845 c = .{ .d = -1111111111 };
1846 var pcf: @TypeOf(&c.d) = undefined;
1847 pcf = &c.d;
1848 var pc: *C = undefined;
1849 pc = @alignCast(@fieldParentPtr(*align(1) C, "d", pcf));
1850 try expect(pc == &c);
1851 }
1091852}
1101853
111const BarExtern = extern union {
112 a: bool,
113 b: f32,
114 c: i32,
115 d: i32,
116};
1854test "@fieldParentPtr tagged union all zero-bit fields" {
1855 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1856 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1171857
118const bar_extern = BarExtern{ .c = 42 };
1858 const C = union(enum) {
1859 a: u0,
1860 b: i0,
1861 };
1191862
120fn testFieldParentPtrExternUnion(c: *const i32) !void {
121 try expect(c == &bar_extern.c);
1863 {
1864 const c: C = .{ .a = 0 };
1865 const pcf = &c.a;
1866 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1867 try expect(pc == &c);
1868 }
1869 {
1870 const c: C = .{ .a = 0 };
1871 const pcf = &c.a;
1872 var pc: *const C = undefined;
1873 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1874 try expect(pc == &c);
1875 }
1876 {
1877 const c: C = .{ .a = 0 };
1878 var pcf: @TypeOf(&c.a) = undefined;
1879 pcf = &c.a;
1880 var pc: *const C = undefined;
1881 pc = @alignCast(@fieldParentPtr(*align(1) const C, "a", pcf));
1882 try expect(pc == &c);
1883 }
1884 {
1885 var c: C = undefined;
1886 c = .{ .a = 0 };
1887 var pcf: @TypeOf(&c.a) = undefined;
1888 pcf = &c.a;
1889 var pc: *C = undefined;
1890 pc = @alignCast(@fieldParentPtr(*align(1) C, "a", pcf));
1891 try expect(pc == &c);
1892 }
1221893
123 const base = @fieldParentPtr(BarExtern, "c", c);
124 try expect(base == &bar_extern);
125 try expect(&base.c == c);
1894 {
1895 const c: C = .{ .b = 0 };
1896 const pcf = &c.b;
1897 const pc: *const C = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1898 try expect(pc == &c);
1899 }
1900 {
1901 const c: C = .{ .b = 0 };
1902 const pcf = &c.b;
1903 var pc: *const C = undefined;
1904 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1905 try expect(pc == &c);
1906 }
1907 {
1908 const c: C = .{ .b = 0 };
1909 var pcf: @TypeOf(&c.b) = undefined;
1910 pcf = &c.b;
1911 var pc: *const C = undefined;
1912 pc = @alignCast(@fieldParentPtr(*align(1) const C, "b", pcf));
1913 try expect(pc == &c);
1914 }
1915 {
1916 var c: C = undefined;
1917 c = .{ .b = 0 };
1918 var pcf: @TypeOf(&c.b) = undefined;
1919 pcf = &c.b;
1920 var pc: *C = undefined;
1921 pc = @alignCast(@fieldParentPtr(*align(1) C, "b", pcf));
1922 try expect(pc == &c);
1923 }
1261924}
test/behavior/struct.zig+6-6
......@@ -1392,13 +1392,13 @@ test "fieldParentPtr of a zero-bit field" {
13921392 {
13931393 const a = A{ .u = 0 };
13941394 const b_ptr = &a.b;
1395 const a_ptr = @fieldParentPtr(A, "b", b_ptr);
1395 const a_ptr = @fieldParentPtr(*const A, "b", b_ptr);
13961396 try std.testing.expectEqual(&a, a_ptr);
13971397 }
13981398 {
13991399 var a = A{ .u = 0 };
14001400 const b_ptr = &a.b;
1401 const a_ptr = @fieldParentPtr(A, "b", b_ptr);
1401 const a_ptr = @fieldParentPtr(*const A, "b", b_ptr);
14021402 try std.testing.expectEqual(&a, a_ptr);
14031403 }
14041404 }
......@@ -1406,17 +1406,17 @@ test "fieldParentPtr of a zero-bit field" {
14061406 {
14071407 const a = A{ .u = 0 };
14081408 const c_ptr = &a.b.c;
1409 const b_ptr = @fieldParentPtr(@TypeOf(a.b), "c", c_ptr);
1409 const b_ptr = @fieldParentPtr(*const @TypeOf(a.b), "c", c_ptr);
14101410 try std.testing.expectEqual(&a.b, b_ptr);
1411 const a_ptr = @fieldParentPtr(A, "b", b_ptr);
1411 const a_ptr = @fieldParentPtr(*const A, "b", b_ptr);
14121412 try std.testing.expectEqual(&a, a_ptr);
14131413 }
14141414 {
14151415 var a = A{ .u = 0 };
14161416 const c_ptr = &a.b.c;
1417 const b_ptr = @fieldParentPtr(@TypeOf(a.b), "c", c_ptr);
1417 const b_ptr = @fieldParentPtr(*const @TypeOf(a.b), "c", c_ptr);
14181418 try std.testing.expectEqual(&a.b, b_ptr);
1419 const a_ptr = @fieldParentPtr(A, "b", b_ptr);
1419 const a_ptr = @fieldParentPtr(*const A, "b", b_ptr);
14201420 try std.testing.expectEqual(&a, a_ptr);
14211421 }
14221422 }
test/behavior/tuple.zig+2-2
......@@ -222,7 +222,7 @@ test "fieldParentPtr of tuple" {
222222 var x: u32 = 0;
223223 _ = &x;
224224 const tuple = .{ x, x };
225 try testing.expect(&tuple == @fieldParentPtr(@TypeOf(tuple), "1", &tuple[1]));
225 try testing.expect(&tuple == @fieldParentPtr(*const @TypeOf(tuple), "1", &tuple[1]));
226226}
227227
228228test "fieldParentPtr of anon struct" {
......@@ -233,7 +233,7 @@ test "fieldParentPtr of anon struct" {
233233 var x: u32 = 0;
234234 _ = &x;
235235 const anon_st = .{ .foo = x, .bar = x };
236 try testing.expect(&anon_st == @fieldParentPtr(@TypeOf(anon_st), "bar", &anon_st.bar));
236 try testing.expect(&anon_st == @fieldParentPtr(*const @TypeOf(anon_st), "bar", &anon_st.bar));
237237}
238238
239239test "offsetOf tuple" {
test/cases/compile_errors/fieldParentPtr-bad_field_name.zig+2-2
......@@ -2,12 +2,12 @@ const Foo = extern struct {
22 derp: i32,
33};
44export fn foo(a: *i32) *Foo {
5 return @fieldParentPtr(Foo, "a", a);
5 return @fieldParentPtr(*Foo, "a", a);
66}
77
88// error
99// backend=stage2
1010// target=native
1111//
12// :5:33: error: no field named 'a' in struct 'tmp.Foo'
12// :5:34: error: no field named 'a' in struct 'tmp.Foo'
1313// :1:20: note: struct declared here
test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig+2-2
......@@ -9,7 +9,7 @@ const foo = Foo{
99
1010comptime {
1111 const field_ptr: *i32 = @ptrFromInt(0x1234);
12 const another_foo_ptr = @fieldParentPtr(Foo, "b", field_ptr);
12 const another_foo_ptr = @fieldParentPtr(*const Foo, "b", field_ptr);
1313 _ = another_foo_ptr;
1414}
1515
......@@ -17,4 +17,4 @@ comptime {
1717// backend=stage2
1818// target=native
1919//
20// :12:55: error: pointer value not based on parent struct
20// :12:62: error: pointer value not based on parent struct
test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig+1-1
......@@ -8,7 +8,7 @@ const foo = Foo{
88};
99
1010comptime {
11 const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a);
11 const another_foo_ptr = @fieldParentPtr(*const Foo, "b", &foo.a);
1212 _ = another_foo_ptr;
1313}
1414
test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig+2-2
......@@ -2,11 +2,11 @@ const Foo = extern struct {
22 a: i32,
33};
44export fn foo(a: i32) *Foo {
5 return @fieldParentPtr(Foo, "a", a);
5 return @fieldParentPtr(*const Foo, "a", a);
66}
77
88// error
99// backend=stage2
1010// target=native
1111//
12// :5:38: error: expected pointer type, found 'i32'
12// :5:45: error: expected pointer type, found 'i32'
test/cases/compile_errors/fieldParentPtr-non_pointer.zig created+10
......@@ -0,0 +1,10 @@
1const Foo = i32;
2export fn foo(a: *i32) *Foo {
3 return @fieldParentPtr(Foo, "a", a);
4}
5
6// error
7// backend=llvm
8// target=native
9//
10// :3:28: error: expected pointer type, found 'i32'
test/cases/compile_errors/fieldParentPtr-non_struct.zig deleted-10
......@@ -1,10 +0,0 @@
1const Foo = i32;
2export fn foo(a: *i32) *Foo {
3 return @fieldParentPtr(Foo, "a", a);
4}
5
6// error
7// backend=llvm
8// target=native
9//
10// :3:28: error: expected struct or union type, found 'i32'
test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig+2-2
......@@ -5,7 +5,7 @@ pub export fn entry1() void {
55 @offsetOf(T, "a");
66}
77pub export fn entry2() void {
8 @fieldParentPtr(T, "a", undefined);
8 @fieldParentPtr(*T, "a", undefined);
99}
1010
1111// error
......@@ -13,4 +13,4 @@ pub export fn entry2() void {
1313// target=native
1414//
1515// :5:5: error: no offset available for comptime field
16// :8:5: error: cannot get @fieldParentPtr of a comptime field
16// :8:25: error: cannot get @fieldParentPtr of a comptime field
test/cases/compile_errors/invalid_bit_pointer.zig created+13
......@@ -0,0 +1,13 @@
1comptime {
2 _ = *align(1:32:4) u8;
3}
4comptime {
5 _ = *align(1:25:4) u8;
6}
7
8// error
9// backend=stage2
10// target=native
11//
12// :2:18: error: packed type 'u8' at bit offset 32 starts 0 bits after the end of a 4 byte host integer
13// :5:18: error: packed type 'u8' at bit offset 25 ends 1 bits after the end of a 4 byte host integer