Sema: validate packed struct field types

This commit is contained in:
Veikka Tuominen 2022-07-28 21:03:10 +03:00
parent f1768b40b2
commit e47706f344
6 changed files with 232 additions and 148 deletions

View File

@ -5049,13 +5049,13 @@ pub fn analyzeExport(
try mod.ensureDeclAnalyzed(exported_decl_index); try mod.ensureDeclAnalyzed(exported_decl_index);
const exported_decl = mod.declPtr(exported_decl_index); const exported_decl = mod.declPtr(exported_decl_index);
if (!(try sema.validateExternType(exported_decl.ty, .other))) { if (!sema.validateExternType(exported_decl.ty, .other)) {
const msg = msg: { const msg = msg: {
const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)}); const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa); errdefer msg.destroy(sema.gpa);
const src_decl = sema.mod.declPtr(block.src_decl); const src_decl = sema.mod.declPtr(block.src_decl);
try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), exported_decl.ty, .other); try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
try sema.addDeclaredHereNote(msg, exported_decl.ty); try sema.addDeclaredHereNote(msg, exported_decl.ty);
break :msg msg; break :msg msg;
@ -7634,7 +7634,7 @@ fn funcCommon(
}; };
return sema.failWithOwnedErrorMsg(block, msg); return sema.failWithOwnedErrorMsg(block, msg);
} }
if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(return_type, .ret_ty))) { if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) {
const msg = msg: { const msg = msg: {
const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
return_type.fmt(sema.mod), @tagName(cc_workaround), return_type.fmt(sema.mod), @tagName(cc_workaround),
@ -7642,7 +7642,7 @@ fn funcCommon(
errdefer msg.destroy(sema.gpa); errdefer msg.destroy(sema.gpa);
const src_decl = sema.mod.declPtr(block.src_decl); const src_decl = sema.mod.declPtr(block.src_decl);
try sema.explainWhyTypeIsNotExtern(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty); try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
try sema.addDeclaredHereNote(msg, return_type); try sema.addDeclaredHereNote(msg, return_type);
break :msg msg; break :msg msg;
@ -7830,7 +7830,7 @@ fn analyzeParameter(
}; };
return sema.failWithOwnedErrorMsg(block, msg); return sema.failWithOwnedErrorMsg(block, msg);
} }
if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty))) { if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) {
const msg = msg: { const msg = msg: {
const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
param.ty.fmt(sema.mod), @tagName(cc), param.ty.fmt(sema.mod), @tagName(cc),
@ -7838,7 +7838,7 @@ fn analyzeParameter(
errdefer msg.destroy(sema.gpa); errdefer msg.destroy(sema.gpa);
const src_decl = sema.mod.declPtr(block.src_decl); const src_decl = sema.mod.declPtr(block.src_decl);
try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty); try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
try sema.addDeclaredHereNote(msg, param.ty); try sema.addDeclaredHereNote(msg, param.ty);
break :msg msg; break :msg msg;
@ -14866,13 +14866,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
} else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) { } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
} else if (inst_data.size == .C) { } else if (inst_data.size == .C) {
if (!(try sema.validateExternType(elem_ty, .other))) { if (!sema.validateExternType(elem_ty, .other)) {
const msg = msg: { const msg = msg: {
const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa); errdefer msg.destroy(sema.gpa);
const src_decl = sema.mod.declPtr(block.src_decl); const src_decl = sema.mod.declPtr(block.src_decl);
try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other); try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
try sema.addDeclaredHereNote(msg, elem_ty); try sema.addDeclaredHereNote(msg, elem_ty);
break :msg msg; break :msg msg;
@ -15950,13 +15950,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
} else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {
return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
} else if (ptr_size == .C) { } else if (ptr_size == .C) {
if (!(try sema.validateExternType(elem_ty, .other))) { if (!sema.validateExternType(elem_ty, .other)) {
const msg = msg: { const msg = msg: {
const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa); errdefer msg.destroy(sema.gpa);
const src_decl = sema.mod.declPtr(block.src_decl); const src_decl = sema.mod.declPtr(block.src_decl);
try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other); try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other);
try sema.addDeclaredHereNote(msg, elem_ty); try sema.addDeclaredHereNote(msg, elem_ty);
break :msg msg; break :msg msg;
@ -19736,7 +19736,7 @@ const ExternPosition = enum {
/// Returns true if `ty` is allowed in extern types. /// Returns true if `ty` is allowed in extern types.
/// Does *NOT* require `ty` to be resolved in any way. /// Does *NOT* require `ty` to be resolved in any way.
fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileError!bool { fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {
switch (ty.zigTypeTag()) { switch (ty.zigTypeTag()) {
.Type, .Type,
.ComptimeFloat, .ComptimeFloat,
@ -19781,8 +19781,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr
fn explainWhyTypeIsNotExtern( fn explainWhyTypeIsNotExtern(
sema: *Sema, sema: *Sema,
block: *Block,
src: LazySrcLoc,
msg: *Module.ErrorMsg, msg: *Module.ErrorMsg,
src_loc: Module.SrcLoc, src_loc: Module.SrcLoc,
ty: Type, ty: Type,
@ -19826,7 +19824,7 @@ fn explainWhyTypeIsNotExtern(
var buf: Type.Payload.Bits = undefined; var buf: Type.Payload.Bits = undefined;
const tag_ty = ty.intTagType(&buf); const tag_ty = ty.intTagType(&buf);
try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, tag_ty, position); try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
}, },
.Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}), .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),
.Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}), .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),
@ -19836,13 +19834,87 @@ fn explainWhyTypeIsNotExtern(
} else if (position == .param_ty) { } else if (position == .param_ty) {
return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{}); return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
} }
try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position); try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position);
}, },
.Vector => try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position), .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position),
.Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}), .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
} }
} }
/// Returns true if `ty` is allowed in packed types.
/// Does *NOT* require `ty` to be resolved in any way.
fn validatePackedType(ty: Type) bool {
switch (ty.zigTypeTag()) {
.Type,
.ComptimeFloat,
.ComptimeInt,
.EnumLiteral,
.Undefined,
.Null,
.ErrorUnion,
.ErrorSet,
.BoundFn,
.Frame,
.NoReturn,
.Opaque,
.AnyFrame,
.Fn,
.Array,
.Optional,
=> return false,
.Void,
.Bool,
.Float,
.Pointer,
.Int,
.Vector,
.Enum,
=> return true,
.Struct, .Union => return ty.containerLayout() == .Packed,
}
}
fn explainWhyTypeIsNotPacked(
sema: *Sema,
msg: *Module.ErrorMsg,
src_loc: Module.SrcLoc,
ty: Type,
) CompileError!void {
const mod = sema.mod;
switch (ty.zigTypeTag()) {
.Void,
.Bool,
.Float,
.Pointer,
.Int,
.Vector,
.Enum,
=> return,
.Type,
.ComptimeFloat,
.ComptimeInt,
.EnumLiteral,
.Undefined,
.Null,
.BoundFn,
.Frame,
.NoReturn,
.Opaque,
.ErrorUnion,
.ErrorSet,
.AnyFrame,
.Optional,
.Array,
=> try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}),
.Fn => {
try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
},
.Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}),
.Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}),
}
}
pub const PanicId = enum { pub const PanicId = enum {
unreach, unreach,
unwrap_null, unwrap_null,
@ -26919,20 +26991,6 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
const field = &struct_obj.fields.values()[i]; const field = &struct_obj.fields.values()[i];
field.ty = try field_ty.copy(decl_arena_allocator); field.ty = try field_ty.copy(decl_arena_allocator);
if (struct_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) {
const msg = msg: {
const tree = try sema.getAstTree(&block_scope);
const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
try sema.explainWhyTypeIsNotExtern(&block_scope, fields_src, msg, fields_src.toSrcLoc(decl), field.ty, .other);
try sema.addDeclaredHereNote(msg, field.ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
}
if (field_ty.zigTypeTag() == .Opaque) { if (field_ty.zigTypeTag() == .Opaque) {
const msg = msg: { const msg = msg: {
const tree = try sema.getAstTree(&block_scope); const tree = try sema.getAstTree(&block_scope);
@ -26945,6 +27003,33 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
}; };
return sema.failWithOwnedErrorMsg(&block_scope, msg); return sema.failWithOwnedErrorMsg(&block_scope, msg);
} }
if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) {
const msg = msg: {
const tree = try sema.getAstTree(&block_scope);
const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other);
try sema.addDeclaredHereNote(msg, field.ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
} else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
const msg = msg: {
const tree = try sema.getAstTree(&block_scope);
const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty);
try sema.addDeclaredHereNote(msg, field.ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
}
if (zir_field.align_body_len > 0) { if (zir_field.align_body_len > 0) {
const body = zir.extra[extra_index..][0..zir_field.align_body_len]; const body = zir.extra[extra_index..][0..zir_field.align_body_len];
@ -27243,20 +27328,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
} }
} }
if (union_obj.layout == .Extern and !(try sema.validateExternType(field_ty, .union_field))) {
const msg = msg: {
const tree = try sema.getAstTree(&block_scope);
const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
try sema.explainWhyTypeIsNotExtern(&block_scope, field_src, msg, field_src.toSrcLoc(decl), field_ty, .union_field);
try sema.addDeclaredHereNote(msg, field_ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
}
if (field_ty.zigTypeTag() == .Opaque) { if (field_ty.zigTypeTag() == .Opaque) {
const msg = msg: { const msg = msg: {
const tree = try sema.getAstTree(&block_scope); const tree = try sema.getAstTree(&block_scope);
@ -27269,6 +27340,33 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
}; };
return sema.failWithOwnedErrorMsg(&block_scope, msg); return sema.failWithOwnedErrorMsg(&block_scope, msg);
} }
if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) {
const msg = msg: {
const tree = try sema.getAstTree(&block_scope);
const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field);
try sema.addDeclaredHereNote(msg, field_ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
} else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
const msg = msg: {
const tree = try sema.getAstTree(&block_scope);
const fields_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
errdefer msg.destroy(sema.gpa);
try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty);
try sema.addDeclaredHereNote(msg, field_ty);
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
}
gop.value_ptr.* = .{ gop.value_ptr.* = .{
.ty = try field_ty.copy(decl_arena_allocator), .ty = try field_ty.copy(decl_arena_allocator),

View File

@ -6,6 +6,8 @@ const expectEqual = std.testing.expectEqual;
const native_endian = builtin.cpu.arch.endian(); const native_endian = builtin.cpu.arch.endian();
test "correct size of packed structs" { test "correct size of packed structs" {
// Stage2 has different packed struct semantics.
if (builtin.zig_backend != .stage1) return error.SkipZigTest;
const T1 = packed struct { one: u8, three: [3]u8 }; const T1 = packed struct { one: u8, three: [3]u8 };
try expectEqual(4, @sizeOf(T1)); try expectEqual(4, @sizeOf(T1));
@ -118,18 +120,6 @@ test "flags in packed structs" {
try expectEqual(32, @bitSizeOf(Flags3)); try expectEqual(32, @bitSizeOf(Flags3));
} }
test "arrays in packed structs" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
const T1 = packed struct { array: [3][3]u8 };
const T2 = packed struct { array: [9]u8 };
try expectEqual(@sizeOf(u72), @sizeOf(T1));
try expectEqual(72, @bitSizeOf(T1));
try expectEqual(@sizeOf(u72), @sizeOf(T2));
try expectEqual(72, @bitSizeOf(T2));
}
test "consistent size of packed structs" { test "consistent size of packed structs" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest;
@ -145,23 +135,15 @@ test "consistent size of packed structs" {
try expectEqual(register_size_bits, @bitSizeOf(TxData2)); try expectEqual(register_size_bits, @bitSizeOf(TxData2));
try expectEqual(register_size_bytes, @sizeOf(TxData2)); try expectEqual(register_size_bytes, @sizeOf(TxData2));
const TxData3 = packed struct { a: u32, b: [3]u8 };
const TxData4 = packed struct { a: u32, b: u24 }; const TxData4 = packed struct { a: u32, b: u24 };
const TxData5 = packed struct { a: [3]u8, b: u32 };
const TxData6 = packed struct { a: u24, b: u32 }; const TxData6 = packed struct { a: u24, b: u32 };
const expectedBitSize = 56; const expectedBitSize = 56;
const expectedByteSize = @sizeOf(u56); const expectedByteSize = @sizeOf(u56);
try expectEqual(expectedBitSize, @bitSizeOf(TxData3));
try expectEqual(expectedByteSize, @sizeOf(TxData3));
try expectEqual(expectedBitSize, @bitSizeOf(TxData4)); try expectEqual(expectedBitSize, @bitSizeOf(TxData4));
try expectEqual(expectedByteSize, @sizeOf(TxData4)); try expectEqual(expectedByteSize, @sizeOf(TxData4));
try expectEqual(expectedBitSize, @bitSizeOf(TxData5));
try expectEqual(expectedByteSize, @sizeOf(TxData5));
try expectEqual(expectedBitSize, @bitSizeOf(TxData6)); try expectEqual(expectedBitSize, @bitSizeOf(TxData6));
try expectEqual(expectedByteSize, @sizeOf(TxData6)); try expectEqual(expectedByteSize, @sizeOf(TxData6));
} }
@ -234,12 +216,6 @@ test "correct sizeOf and offsets in packed structs" {
try expectEqual(@as(u7, 0b1111010), s2.y); try expectEqual(@as(u7, 0b1111010), s2.y);
try expectEqual(@as(u24, 0xd5c71f), s2.z); try expectEqual(@as(u24, 0xd5c71f), s2.z);
} }
const S = packed struct { a: u32, pad: [3]u32, b: u32 };
try expectEqual(16, @offsetOf(S, "b"));
try expectEqual(128, @bitOffsetOf(S, "b"));
try expectEqual(@sizeOf(u160), @sizeOf(S));
} }
test "nested packed structs" { test "nested packed structs" {

View File

@ -105,6 +105,8 @@ test "@offsetOf" {
} }
test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" { test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
// Stage2 has different packed struct semantics.
if (builtin.zig_backend != .stage1) return error.SkipZigTest;
const p3a_len = 3; const p3a_len = 3;
const P3 = packed struct { const P3 = packed struct {
a: [p3a_len]u8, a: [p3a_len]u8,

View File

@ -704,10 +704,8 @@ const FooArray24Bits = packed struct {
}; };
test "aligned array of packed struct" { test "aligned array of packed struct" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO // Stage2 has different packed struct semantics.
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend != .stage1) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
comptime { comptime {
try expect(@sizeOf(FooStructAligned) == 2); try expect(@sizeOf(FooStructAligned) == 2);

View File

@ -0,0 +1,84 @@
export fn entry1() void {
_ = @sizeOf(packed struct {
x: anyerror,
});
}
export fn entry2() void {
_ = @sizeOf(packed struct {
x: [2]u24,
});
}
export fn entry3() void {
_ = @sizeOf(packed struct {
x: anyerror!u32,
});
}
export fn entry4() void {
_ = @sizeOf(packed struct {
x: S,
});
}
export fn entry5() void {
_ = @sizeOf(packed struct {
x: U,
});
}
export fn entry6() void {
_ = @sizeOf(packed struct {
x: ?anyerror,
});
}
export fn entry7() void {
_ = @sizeOf(packed struct {
x: enum { A, B },
});
}
export fn entry8() void {
_ = @sizeOf(packed struct {
x: fn () void,
});
}
export fn entry9() void {
_ = @sizeOf(packed struct {
x: *const fn () void,
});
}
export fn entry10() void {
_ = @sizeOf(packed struct {
x: packed struct { x: i32 },
});
}
export fn entry11() void {
_ = @sizeOf(packed struct {
x: packed union { A: i32, B: u32 },
});
}
const S = struct {
x: i32,
};
const U = extern union {
A: i32,
B: u32,
};
// error
// backend=llvm
// target=native
//
// :3:9: error: packed structs cannot contain fields of type 'anyerror'
// :3:9: note: type has no guaranteed in-memory representation
// :8:9: error: packed structs cannot contain fields of type '[2]u24'
// :8:9: note: type has no guaranteed in-memory representation
// :13:9: error: packed structs cannot contain fields of type 'anyerror!u32'
// :13:9: note: type has no guaranteed in-memory representation
// :18:9: error: packed structs cannot contain fields of type 'tmp.S'
// :18:9: note: only packed structs layout are allowed in packed types
// :56:11: note: struct declared here
// :23:9: error: packed structs cannot contain fields of type 'tmp.U'
// :23:9: note: only packed unions layout are allowed in packed types
// :59:18: note: union declared here
// :28:9: error: packed structs cannot contain fields of type '?anyerror'
// :28:9: note: type has no guaranteed in-memory representation
// :38:9: error: packed structs cannot contain fields of type 'fn() void'
// :38:9: note: type has no guaranteed in-memory representation
// :38:9: note: use '*const ' to make a function pointer type

View File

@ -1,74 +0,0 @@
const A = packed struct {
x: anyerror,
};
const B = packed struct {
x: [2]u24,
};
const C = packed struct {
x: [1]anyerror,
};
const D = packed struct {
x: [1]S,
};
const E = packed struct {
x: [1]U,
};
const F = packed struct {
x: ?anyerror,
};
const G = packed struct {
x: Enum,
};
export fn entry1() void {
var a: A = undefined;
_ = a;
}
export fn entry2() void {
var b: B = undefined;
_ = b;
}
export fn entry3() void {
var r: C = undefined;
_ = r;
}
export fn entry4() void {
var d: D = undefined;
_ = d;
}
export fn entry5() void {
var e: E = undefined;
_ = e;
}
export fn entry6() void {
var f: F = undefined;
_ = f;
}
export fn entry7() void {
var g: G = undefined;
_ = g;
}
const S = struct {
x: i32,
};
const U = struct {
A: i32,
B: u32,
};
const Enum = enum {
A,
B,
};
// error
// backend=stage1
// target=native
// is_test=1
//
// tmp.zig:2:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation
// tmp.zig:5:5: error: array of 'u24' not allowed in packed struct due to padding bits (must be padded from 48 to 64 bits)
// tmp.zig:8:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation
// tmp.zig:11:5: error: non-packed, non-extern struct 'S' not allowed in packed struct; no guaranteed in-memory representation
// tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation
// tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation
// tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation
// tmp.zig:57:14: note: enum declaration does not specify an integer tag type