Sema: allow void as an extern union field & fix invalid extern unions

This commit is contained in:
Veikka Tuominen 2022-07-11 19:57:41 +03:00
parent d00da05ecb
commit 122c76a167
5 changed files with 14 additions and 12 deletions

View File

@ -59,12 +59,12 @@ const twords = extern union {
s: S,
const S = if (native_endian == .Little)
struct {
extern struct {
low: u64,
high: u64,
}
else
struct {
extern struct {
high: u64,
low: u64,
};

View File

@ -31,9 +31,9 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type {
all: T,
s: if (native_endian == .Little)
struct { low: HalfT, high: HalfT }
extern struct { low: HalfT, high: HalfT }
else
struct { high: HalfT, low: HalfT },
extern struct { high: HalfT, low: HalfT },
};
}

View File

@ -30,8 +30,8 @@ pub extern "c" fn _kern_get_current_team() i32;
pub const sem_t = extern struct {
type: i32,
u: extern union {
named_sem_id: ?i32,
unnamed_sem: ?i32,
named_sem_id: i32,
unnamed_sem: i32,
},
padding: [2]i32,
};

View File

@ -18192,6 +18192,7 @@ fn explainWhyTypeIsComptime(
const ExternPosition = enum {
ret_ty,
param_ty,
union_field,
other,
};
@ -18206,9 +18207,9 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr
.ErrorUnion,
.ErrorSet,
.BoundFn,
.Void,
.Frame,
=> return false,
.Void => return position == .union_field,
.NoReturn => return position == .ret_ty,
.Opaque,
.Bool,
@ -24193,13 +24194,13 @@ fn resolveUnionFully(
for (union_obj.fields.values()) |field| {
try sema.resolveTypeFully(block, src, field.ty);
if (union_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) {
if (union_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .union_field))) {
const msg = msg: {
const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
const src_decl = sema.mod.declPtr(block.src_decl);
try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), field.ty, .other);
try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), field.ty, .union_field);
try sema.addDeclaredHereNote(msg, field.ty);
break :msg msg;

View File

@ -84,18 +84,19 @@ test "comptime union field access" {
const FooExtern = extern union {
int: i32,
str: struct {
slice: []const u8,
str: extern struct {
slice: [*:0]const u8,
},
};
test "basic extern unions" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
var foo = FooExtern{ .int = 1 };
try expect(foo.int == 1);
foo.str.slice = "Well";
try expect(std.mem.eql(u8, foo.str.slice, "Well"));
try expect(std.mem.eql(u8, std.mem.sliceTo(foo.str.slice, 0), "Well"));
}
const ExternPtrOrInt = extern union {