aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2023-02-20 23:31:48 +0100
committerVeikka Tuominen <git@vexu.eu>2023-02-21 15:57:13 +0200
commit05da5b32a820c031001098034840940964f41a81 (patch)
treead6dfd90922e168d536f8adba3f97af2e1843e31 /src/Sema.zig
parentdc1f50e505105cabe1ed53951ca612778d6019ee (diff)
downloadzig-05da5b32a820c031001098034840940964f41a81.tar.gz
zig-05da5b32a820c031001098034840940964f41a81.zip
Sema: implement @fieldParentPtr for unions
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig54
1 files changed, 34 insertions, 20 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 41e5fdc20e..40a4a114b4 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -21482,24 +21482,32 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
- const struct_ty = try sema.resolveType(block, ty_src, extra.parent_type);
+ const parent_ty = try sema.resolveType(block, ty_src, extra.parent_type);
const field_name = try sema.resolveConstString(block, name_src, extra.field_name, "field name must be comptime-known");
const field_ptr = try sema.resolveInst(extra.field_ptr);
const field_ptr_ty = sema.typeOf(field_ptr);
- if (struct_ty.zigTypeTag() != .Struct) {
- return sema.fail(block, ty_src, "expected struct type, found '{}'", .{struct_ty.fmt(sema.mod)});
+ if (parent_ty.zigTypeTag() != .Struct and parent_ty.zigTypeTag() != .Union) {
+ return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)});
}
- try sema.resolveTypeLayout(struct_ty);
+ try sema.resolveTypeLayout(parent_ty);
- const field_index = if (struct_ty.isTuple()) blk: {
- if (mem.eql(u8, field_name, "len")) {
- return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
- }
- break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src);
- } else try sema.structFieldIndex(block, struct_ty, field_name, name_src);
+ const field_index = switch (parent_ty.zigTypeTag()) {
+ .Struct => blk: {
+ if (parent_ty.isTuple()) {
+ if (mem.eql(u8, field_name, "len")) {
+ return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
+ }
+ break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, name_src);
+ } else {
+ break :blk try sema.structFieldIndex(block, parent_ty, field_name, name_src);
+ }
+ },
+ .Union => try sema.unionFieldIndex(block, parent_ty, field_name, name_src),
+ else => unreachable,
+ };
- if (struct_ty.structFieldIsComptime(field_index)) {
+ if (parent_ty.zigTypeTag() == .Struct and parent_ty.structFieldIsComptime(field_index)) {
return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
}
@@ -21507,23 +21515,29 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
var ptr_ty_data: Type.Payload.Pointer.Data = .{
- .pointee_type = struct_ty.structFieldType(field_index),
+ .pointee_type = parent_ty.structFieldType(field_index),
.mutable = field_ptr_ty_info.mutable,
.@"addrspace" = field_ptr_ty_info.@"addrspace",
};
- if (struct_ty.containerLayout() == .Packed) {
- return sema.fail(block, src, "TODO handle packed structs with @fieldParentPtr", .{});
+ if (parent_ty.containerLayout() == .Packed) {
+ return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});
} else {
- ptr_ty_data.@"align" = if (struct_ty.castTag(.@"struct")) |struct_obj| b: {
- break :b struct_obj.data.fields.values()[field_index].abi_align;
- } else 0;
+ ptr_ty_data.@"align" = blk: {
+ if (parent_ty.castTag(.@"struct")) |struct_obj| {
+ break :blk struct_obj.data.fields.values()[field_index].abi_align;
+ } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| {
+ break :blk union_obj.data.fields.values()[field_index].abi_align;
+ } else {
+ break :blk 0;
+ }
+ };
}
const actual_field_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, ptr_src);
- ptr_ty_data.pointee_type = struct_ty;
+ ptr_ty_data.pointee_type = parent_ty;
const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
@@ -21540,11 +21554,11 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
field_name,
field_index,
payload.data.field_index,
- struct_ty.fmt(sema.mod),
+ parent_ty.fmt(sema.mod),
},
);
errdefer msg.destroy(sema.gpa);
- try sema.addDeclaredHereNote(msg, struct_ty);
+ try sema.addDeclaredHereNote(msg, parent_ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(msg);