authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-28 21:03:10+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-01 23:59:40+03:00
loge47706f34454c46dd00fe10fdf9252657117a00d
treeef7ab64fbe9d3123004b3fe94781bfcabc8325fa
parentf1768b40b2468d63355c8cf83d3614ae23a54317

Sema: validate packed struct field types


6 files changed, 217 insertions(+), 133 deletions(-)

src/Sema.zig+127-29
...@@ -5049,13 +5049,13 @@ pub fn analyzeExport(...@@ -5049,13 +5049,13 @@ pub fn analyzeExport(
5049 try mod.ensureDeclAnalyzed(exported_decl_index);5049 try mod.ensureDeclAnalyzed(exported_decl_index);
5050 const exported_decl = mod.declPtr(exported_decl_index);5050 const exported_decl = mod.declPtr(exported_decl_index);
50515051
5052 if (!(try sema.validateExternType(exported_decl.ty, .other))) {5052 if (!sema.validateExternType(exported_decl.ty, .other)) {
5053 const msg = msg: {5053 const msg = msg: {
5054 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});5054 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
5055 errdefer msg.destroy(sema.gpa);5055 errdefer msg.destroy(sema.gpa);
50565056
5057 const src_decl = sema.mod.declPtr(block.src_decl);5057 const src_decl = sema.mod.declPtr(block.src_decl);
5058 try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);5058 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
50595059
5060 try sema.addDeclaredHereNote(msg, exported_decl.ty);5060 try sema.addDeclaredHereNote(msg, exported_decl.ty);
5061 break :msg msg;5061 break :msg msg;
...@@ -7634,7 +7634,7 @@ fn funcCommon(...@@ -7634,7 +7634,7 @@ fn funcCommon(
7634 };7634 };
7635 return sema.failWithOwnedErrorMsg(block, msg);7635 return sema.failWithOwnedErrorMsg(block, msg);
7636 }7636 }
7637 if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(return_type, .ret_ty))) {7637 if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) {
7638 const msg = msg: {7638 const msg = msg: {
7639 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{7639 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
7640 return_type.fmt(sema.mod), @tagName(cc_workaround),7640 return_type.fmt(sema.mod), @tagName(cc_workaround),
...@@ -7642,7 +7642,7 @@ fn funcCommon(...@@ -7642,7 +7642,7 @@ fn funcCommon(
7642 errdefer msg.destroy(sema.gpa);7642 errdefer msg.destroy(sema.gpa);
76437643
7644 const src_decl = sema.mod.declPtr(block.src_decl);7644 const src_decl = sema.mod.declPtr(block.src_decl);
7645 try sema.explainWhyTypeIsNotExtern(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);7645 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
76467646
7647 try sema.addDeclaredHereNote(msg, return_type);7647 try sema.addDeclaredHereNote(msg, return_type);
7648 break :msg msg;7648 break :msg msg;
...@@ -7830,7 +7830,7 @@ fn analyzeParameter(...@@ -7830,7 +7830,7 @@ fn analyzeParameter(
7830 };7830 };
7831 return sema.failWithOwnedErrorMsg(block, msg);7831 return sema.failWithOwnedErrorMsg(block, msg);
7832 }7832 }
7833 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty))) {7833 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) {
7834 const msg = msg: {7834 const msg = msg: {
7835 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{7835 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
7836 param.ty.fmt(sema.mod), @tagName(cc),7836 param.ty.fmt(sema.mod), @tagName(cc),
...@@ -7838,7 +7838,7 @@ fn analyzeParameter(...@@ -7838,7 +7838,7 @@ fn analyzeParameter(
7838 errdefer msg.destroy(sema.gpa);7838 errdefer msg.destroy(sema.gpa);
78397839
7840 const src_decl = sema.mod.declPtr(block.src_decl);7840 const src_decl = sema.mod.declPtr(block.src_decl);
7841 try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);7841 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
78427842
7843 try sema.addDeclaredHereNote(msg, param.ty);7843 try sema.addDeclaredHereNote(msg, param.ty);
7844 break :msg msg;7844 break :msg msg;
...@@ -14866,13 +14866,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -14866,13 +14866,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
14866 } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {14866 } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
14867 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});14867 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
14868 } else if (inst_data.size == .C) {14868 } else if (inst_data.size == .C) {
14869 if (!(try sema.validateExternType(elem_ty, .other))) {14869 if (!sema.validateExternType(elem_ty, .other)) {
14870 const msg = msg: {14870 const msg = msg: {
14871 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});14871 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
14872 errdefer msg.destroy(sema.gpa);14872 errdefer msg.destroy(sema.gpa);
1487314873
14874 const src_decl = sema.mod.declPtr(block.src_decl);14874 const src_decl = sema.mod.declPtr(block.src_decl);
14875 try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);14875 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
1487614876
14877 try sema.addDeclaredHereNote(msg, elem_ty);14877 try sema.addDeclaredHereNote(msg, elem_ty);
14878 break :msg msg;14878 break :msg msg;
...@@ -15950,13 +15950,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -15950,13 +15950,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
15950 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {15950 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {
15951 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});15951 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
15952 } else if (ptr_size == .C) {15952 } else if (ptr_size == .C) {
15953 if (!(try sema.validateExternType(elem_ty, .other))) {15953 if (!sema.validateExternType(elem_ty, .other)) {
15954 const msg = msg: {15954 const msg = msg: {
15955 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});15955 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
15956 errdefer msg.destroy(sema.gpa);15956 errdefer msg.destroy(sema.gpa);
1595715957
15958 const src_decl = sema.mod.declPtr(block.src_decl);15958 const src_decl = sema.mod.declPtr(block.src_decl);
15959 try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other);15959 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other);
1596015960
15961 try sema.addDeclaredHereNote(msg, elem_ty);15961 try sema.addDeclaredHereNote(msg, elem_ty);
15962 break :msg msg;15962 break :msg msg;
...@@ -19736,7 +19736,7 @@ const ExternPosition = enum {...@@ -19736,7 +19736,7 @@ const ExternPosition = enum {
1973619736
19737/// Returns true if `ty` is allowed in extern types.19737/// Returns true if `ty` is allowed in extern types.
19738/// Does *NOT* require `ty` to be resolved in any way.19738/// Does *NOT* require `ty` to be resolved in any way.
19739fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileError!bool {19739fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {
19740 switch (ty.zigTypeTag()) {19740 switch (ty.zigTypeTag()) {
19741 .Type,19741 .Type,
19742 .ComptimeFloat,19742 .ComptimeFloat,
...@@ -19781,8 +19781,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr...@@ -19781,8 +19781,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr
1978119781
19782fn explainWhyTypeIsNotExtern(19782fn explainWhyTypeIsNotExtern(
19783 sema: *Sema,19783 sema: *Sema,
19784 block: *Block,
19785 src: LazySrcLoc,
19786 msg: *Module.ErrorMsg,19784 msg: *Module.ErrorMsg,
19787 src_loc: Module.SrcLoc,19785 src_loc: Module.SrcLoc,
19788 ty: Type,19786 ty: Type,
...@@ -19826,7 +19824,7 @@ fn explainWhyTypeIsNotExtern(...@@ -19826,7 +19824,7 @@ fn explainWhyTypeIsNotExtern(
19826 var buf: Type.Payload.Bits = undefined;19824 var buf: Type.Payload.Bits = undefined;
19827 const tag_ty = ty.intTagType(&buf);19825 const tag_ty = ty.intTagType(&buf);
19828 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});19826 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
19829 try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, tag_ty, position);19827 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
19830 },19828 },
19831 .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),19829 .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),
19832 .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),19830 .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),
...@@ -19836,13 +19834,87 @@ fn explainWhyTypeIsNotExtern(...@@ -19836,13 +19834,87 @@ fn explainWhyTypeIsNotExtern(
19836 } else if (position == .param_ty) {19834 } else if (position == .param_ty) {
19837 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});19835 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
19838 }19836 }
19839 try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position);19837 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position);
19840 },19838 },
19841 .Vector => try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position),19839 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position),
19842 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),19840 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
19843 }19841 }
19844}19842}
1984519843
19844/// Returns true if `ty` is allowed in packed types.
19845/// Does *NOT* require `ty` to be resolved in any way.
19846fn validatePackedType(ty: Type) bool {
19847 switch (ty.zigTypeTag()) {
19848 .Type,
19849 .ComptimeFloat,
19850 .ComptimeInt,
19851 .EnumLiteral,
19852 .Undefined,
19853 .Null,
19854 .ErrorUnion,
19855 .ErrorSet,
19856 .BoundFn,
19857 .Frame,
19858 .NoReturn,
19859 .Opaque,
19860 .AnyFrame,
19861 .Fn,
19862 .Array,
19863 .Optional,
19864 => return false,
19865 .Void,
19866 .Bool,
19867 .Float,
19868 .Pointer,
19869 .Int,
19870 .Vector,
19871 .Enum,
19872 => return true,
19873 .Struct, .Union => return ty.containerLayout() == .Packed,
19874 }
19875}
19876
19877fn explainWhyTypeIsNotPacked(
19878 sema: *Sema,
19879 msg: *Module.ErrorMsg,
19880 src_loc: Module.SrcLoc,
19881 ty: Type,
19882) CompileError!void {
19883 const mod = sema.mod;
19884 switch (ty.zigTypeTag()) {
19885 .Void,
19886 .Bool,
19887 .Float,
19888 .Pointer,
19889 .Int,
19890 .Vector,
19891 .Enum,
19892 => return,
19893 .Type,
19894 .ComptimeFloat,
19895 .ComptimeInt,
19896 .EnumLiteral,
19897 .Undefined,
19898 .Null,
19899 .BoundFn,
19900 .Frame,
19901 .NoReturn,
19902 .Opaque,
19903 .ErrorUnion,
19904 .ErrorSet,
19905 .AnyFrame,
19906 .Optional,
19907 .Array,
19908 => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}),
19909 .Fn => {
19910 try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
19911 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
19912 },
19913 .Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}),
19914 .Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}),
19915 }
19916}
19917
19846pub const PanicId = enum {19918pub const PanicId = enum {
19847 unreach,19919 unreach,
19848 unwrap_null,19920 unwrap_null,
...@@ -26919,28 +26991,41 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -26919,28 +26991,41 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
26919 const field = &struct_obj.fields.values()[i];26991 const field = &struct_obj.fields.values()[i];
26920 field.ty = try field_ty.copy(decl_arena_allocator);26992 field.ty = try field_ty.copy(decl_arena_allocator);
2692126993
26922 if (struct_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) {26994 if (field_ty.zigTypeTag() == .Opaque) {
26995 const msg = msg: {
26996 const tree = try sema.getAstTree(&block_scope);
26997 const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26998 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
26999 errdefer msg.destroy(sema.gpa);
27000
27001 try sema.addDeclaredHereNote(msg, field_ty);
27002 break :msg msg;
27003 };
27004 return sema.failWithOwnedErrorMsg(&block_scope, msg);
27005 }
27006 if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) {
26923 const msg = msg: {27007 const msg = msg: {
26924 const tree = try sema.getAstTree(&block_scope);27008 const tree = try sema.getAstTree(&block_scope);
26925 const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);27009 const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26926 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});27010 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
26927 errdefer msg.destroy(sema.gpa);27011 errdefer msg.destroy(sema.gpa);
2692827012
26929 try sema.explainWhyTypeIsNotExtern(&block_scope, fields_src, msg, fields_src.toSrcLoc(decl), field.ty, .other);27013 try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other);
2693027014
26931 try sema.addDeclaredHereNote(msg, field.ty);27015 try sema.addDeclaredHereNote(msg, field.ty);
26932 break :msg msg;27016 break :msg msg;
26933 };27017 };
26934 return sema.failWithOwnedErrorMsg(&block_scope, msg);27018 return sema.failWithOwnedErrorMsg(&block_scope, msg);
26935 }27019 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
26936 if (field_ty.zigTypeTag() == .Opaque) {
26937 const msg = msg: {27020 const msg = msg: {
26938 const tree = try sema.getAstTree(&block_scope);27021 const tree = try sema.getAstTree(&block_scope);
26939 const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);27022 const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
26940 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});27023 const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
26941 errdefer msg.destroy(sema.gpa);27024 errdefer msg.destroy(sema.gpa);
2694227025
26943 try sema.addDeclaredHereNote(msg, field_ty);27026 try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty);
27027
27028 try sema.addDeclaredHereNote(msg, field.ty);
26944 break :msg msg;27029 break :msg msg;
26945 };27030 };
26946 return sema.failWithOwnedErrorMsg(&block_scope, msg);27031 return sema.failWithOwnedErrorMsg(&block_scope, msg);
...@@ -27243,27 +27328,40 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -27243,27 +27328,40 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
27243 }27328 }
27244 }27329 }
2724527330
27246 if (union_obj.layout == .Extern and !(try sema.validateExternType(field_ty, .union_field))) {27331 if (field_ty.zigTypeTag() == .Opaque) {
27247 const msg = msg: {27332 const msg = msg: {
27248 const tree = try sema.getAstTree(&block_scope);27333 const tree = try sema.getAstTree(&block_scope);
27249 const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);27334 const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
27250 const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});27335 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
27251 errdefer msg.destroy(sema.gpa);27336 errdefer msg.destroy(sema.gpa);
2725227337
27253 try sema.explainWhyTypeIsNotExtern(&block_scope, field_src, msg, field_src.toSrcLoc(decl), field_ty, .union_field);
27254
27255 try sema.addDeclaredHereNote(msg, field_ty);27338 try sema.addDeclaredHereNote(msg, field_ty);
27256 break :msg msg;27339 break :msg msg;
27257 };27340 };
27258 return sema.failWithOwnedErrorMsg(&block_scope, msg);27341 return sema.failWithOwnedErrorMsg(&block_scope, msg);
27259 }27342 }
27260 if (field_ty.zigTypeTag() == .Opaque) {27343 if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) {
27261 const msg = msg: {27344 const msg = msg: {
27262 const tree = try sema.getAstTree(&block_scope);27345 const tree = try sema.getAstTree(&block_scope);
27263 const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);27346 const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
27264 const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});27347 const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
27265 errdefer msg.destroy(sema.gpa);27348 errdefer msg.destroy(sema.gpa);
2726627349
27350 try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field);
27351
27352 try sema.addDeclaredHereNote(msg, field_ty);
27353 break :msg msg;
27354 };
27355 return sema.failWithOwnedErrorMsg(&block_scope, msg);
27356 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
27357 const msg = msg: {
27358 const tree = try sema.getAstTree(&block_scope);
27359 const fields_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
27360 const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
27361 errdefer msg.destroy(sema.gpa);
27362
27363 try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty);
27364
27267 try sema.addDeclaredHereNote(msg, field_ty);27365 try sema.addDeclaredHereNote(msg, field_ty);
27268 break :msg msg;27366 break :msg msg;
27269 };27367 };
test/behavior/packed-struct.zig+2-26
...@@ -6,6 +6,8 @@ const expectEqual = std.testing.expectEqual;...@@ -6,6 +6,8 @@ const expectEqual = std.testing.expectEqual;
6const native_endian = builtin.cpu.arch.endian();6const native_endian = builtin.cpu.arch.endian();
77
8test "correct size of packed structs" {8test "correct size of packed structs" {
9 // Stage2 has different packed struct semantics.
10 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
9 const T1 = packed struct { one: u8, three: [3]u8 };11 const T1 = packed struct { one: u8, three: [3]u8 };
1012
11 try expectEqual(4, @sizeOf(T1));13 try expectEqual(4, @sizeOf(T1));
...@@ -118,18 +120,6 @@ test "flags in packed structs" {...@@ -118,18 +120,6 @@ test "flags in packed structs" {
118 try expectEqual(32, @bitSizeOf(Flags3));120 try expectEqual(32, @bitSizeOf(Flags3));
119}121}
120122
121test "arrays in packed structs" {
122 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
123
124 const T1 = packed struct { array: [3][3]u8 };
125 const T2 = packed struct { array: [9]u8 };
126
127 try expectEqual(@sizeOf(u72), @sizeOf(T1));
128 try expectEqual(72, @bitSizeOf(T1));
129 try expectEqual(@sizeOf(u72), @sizeOf(T2));
130 try expectEqual(72, @bitSizeOf(T2));
131}
132
133test "consistent size of packed structs" {123test "consistent size of packed structs" {
134 if (builtin.zig_backend == .stage1) return error.SkipZigTest;124 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
135125
...@@ -145,23 +135,15 @@ test "consistent size of packed structs" {...@@ -145,23 +135,15 @@ test "consistent size of packed structs" {
145 try expectEqual(register_size_bits, @bitSizeOf(TxData2));135 try expectEqual(register_size_bits, @bitSizeOf(TxData2));
146 try expectEqual(register_size_bytes, @sizeOf(TxData2));136 try expectEqual(register_size_bytes, @sizeOf(TxData2));
147137
148 const TxData3 = packed struct { a: u32, b: [3]u8 };
149 const TxData4 = packed struct { a: u32, b: u24 };138 const TxData4 = packed struct { a: u32, b: u24 };
150 const TxData5 = packed struct { a: [3]u8, b: u32 };
151 const TxData6 = packed struct { a: u24, b: u32 };139 const TxData6 = packed struct { a: u24, b: u32 };
152140
153 const expectedBitSize = 56;141 const expectedBitSize = 56;
154 const expectedByteSize = @sizeOf(u56);142 const expectedByteSize = @sizeOf(u56);
155143
156 try expectEqual(expectedBitSize, @bitSizeOf(TxData3));
157 try expectEqual(expectedByteSize, @sizeOf(TxData3));
158
159 try expectEqual(expectedBitSize, @bitSizeOf(TxData4));144 try expectEqual(expectedBitSize, @bitSizeOf(TxData4));
160 try expectEqual(expectedByteSize, @sizeOf(TxData4));145 try expectEqual(expectedByteSize, @sizeOf(TxData4));
161146
162 try expectEqual(expectedBitSize, @bitSizeOf(TxData5));
163 try expectEqual(expectedByteSize, @sizeOf(TxData5));
164
165 try expectEqual(expectedBitSize, @bitSizeOf(TxData6));147 try expectEqual(expectedBitSize, @bitSizeOf(TxData6));
166 try expectEqual(expectedByteSize, @sizeOf(TxData6));148 try expectEqual(expectedByteSize, @sizeOf(TxData6));
167}149}
...@@ -234,12 +216,6 @@ test "correct sizeOf and offsets in packed structs" {...@@ -234,12 +216,6 @@ test "correct sizeOf and offsets in packed structs" {
234 try expectEqual(@as(u7, 0b1111010), s2.y);216 try expectEqual(@as(u7, 0b1111010), s2.y);
235 try expectEqual(@as(u24, 0xd5c71f), s2.z);217 try expectEqual(@as(u24, 0xd5c71f), s2.z);
236 }218 }
237
238 const S = packed struct { a: u32, pad: [3]u32, b: u32 };
239
240 try expectEqual(16, @offsetOf(S, "b"));
241 try expectEqual(128, @bitOffsetOf(S, "b"));
242 try expectEqual(@sizeOf(u160), @sizeOf(S));
243}219}
244220
245test "nested packed structs" {221test "nested packed structs" {
test/behavior/sizeof_and_typeof.zig+2
...@@ -105,6 +105,8 @@ test "@offsetOf" {...@@ -105,6 +105,8 @@ test "@offsetOf" {
105}105}
106106
107test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {107test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
108 // Stage2 has different packed struct semantics.
109 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
108 const p3a_len = 3;110 const p3a_len = 3;
109 const P3 = packed struct {111 const P3 = packed struct {
110 a: [p3a_len]u8,112 a: [p3a_len]u8,
test/behavior/struct.zig+2-4
...@@ -704,10 +704,8 @@ const FooArray24Bits = packed struct {...@@ -704,10 +704,8 @@ const FooArray24Bits = packed struct {
704};704};
705705
706test "aligned array of packed struct" {706test "aligned array of packed struct" {
707 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO707 // Stage2 has different packed struct semantics.
708 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO708 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
709 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
710 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
711709
712 comptime {710 comptime {
713 try expect(@sizeOf(FooStructAligned) == 2);711 try expect(@sizeOf(FooStructAligned) == 2);
test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig created+84
...@@ -0,0 +1,84 @@
1export fn entry1() void {
2 _ = @sizeOf(packed struct {
3 x: anyerror,
4 });
5}
6export fn entry2() void {
7 _ = @sizeOf(packed struct {
8 x: [2]u24,
9 });
10}
11export fn entry3() void {
12 _ = @sizeOf(packed struct {
13 x: anyerror!u32,
14 });
15}
16export fn entry4() void {
17 _ = @sizeOf(packed struct {
18 x: S,
19 });
20}
21export fn entry5() void {
22 _ = @sizeOf(packed struct {
23 x: U,
24 });
25}
26export fn entry6() void {
27 _ = @sizeOf(packed struct {
28 x: ?anyerror,
29 });
30}
31export fn entry7() void {
32 _ = @sizeOf(packed struct {
33 x: enum { A, B },
34 });
35}
36export fn entry8() void {
37 _ = @sizeOf(packed struct {
38 x: fn () void,
39 });
40}
41export fn entry9() void {
42 _ = @sizeOf(packed struct {
43 x: *const fn () void,
44 });
45}
46export fn entry10() void {
47 _ = @sizeOf(packed struct {
48 x: packed struct { x: i32 },
49 });
50}
51export fn entry11() void {
52 _ = @sizeOf(packed struct {
53 x: packed union { A: i32, B: u32 },
54 });
55}
56const S = struct {
57 x: i32,
58};
59const U = extern union {
60 A: i32,
61 B: u32,
62};
63
64// error
65// backend=llvm
66// target=native
67//
68// :3:9: error: packed structs cannot contain fields of type 'anyerror'
69// :3:9: note: type has no guaranteed in-memory representation
70// :8:9: error: packed structs cannot contain fields of type '[2]u24'
71// :8:9: note: type has no guaranteed in-memory representation
72// :13:9: error: packed structs cannot contain fields of type 'anyerror!u32'
73// :13:9: note: type has no guaranteed in-memory representation
74// :18:9: error: packed structs cannot contain fields of type 'tmp.S'
75// :18:9: note: only packed structs layout are allowed in packed types
76// :56:11: note: struct declared here
77// :23:9: error: packed structs cannot contain fields of type 'tmp.U'
78// :23:9: note: only packed unions layout are allowed in packed types
79// :59:18: note: union declared here
80// :28:9: error: packed structs cannot contain fields of type '?anyerror'
81// :28:9: note: type has no guaranteed in-memory representation
82// :38:9: error: packed structs cannot contain fields of type 'fn() void'
83// :38:9: note: type has no guaranteed in-memory representation
84// :38:9: note: use '*const ' to make a function pointer type
test/cases/compile_errors/stage1/test/packed_struct_with_fields_of_not_allowed_types.zig deleted-74
...@@ -1,74 +0,0 @@
1const A = packed struct {
2 x: anyerror,
3};
4const B = packed struct {
5 x: [2]u24,
6};
7const C = packed struct {
8 x: [1]anyerror,
9};
10const D = packed struct {
11 x: [1]S,
12};
13const E = packed struct {
14 x: [1]U,
15};
16const F = packed struct {
17 x: ?anyerror,
18};
19const G = packed struct {
20 x: Enum,
21};
22export fn entry1() void {
23 var a: A = undefined;
24 _ = a;
25}
26export fn entry2() void {
27 var b: B = undefined;
28 _ = b;
29}
30export fn entry3() void {
31 var r: C = undefined;
32 _ = r;
33}
34export fn entry4() void {
35 var d: D = undefined;
36 _ = d;
37}
38export fn entry5() void {
39 var e: E = undefined;
40 _ = e;
41}
42export fn entry6() void {
43 var f: F = undefined;
44 _ = f;
45}
46export fn entry7() void {
47 var g: G = undefined;
48 _ = g;
49}
50const S = struct {
51 x: i32,
52};
53const U = struct {
54 A: i32,
55 B: u32,
56};
57const Enum = enum {
58 A,
59 B,
60};
61
62// error
63// backend=stage1
64// target=native
65// is_test=1
66//
67// tmp.zig:2:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation
68// 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)
69// tmp.zig:8:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation
70// tmp.zig:11:5: error: non-packed, non-extern struct 'S' not allowed in packed struct; no guaranteed in-memory representation
71// tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation
72// tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation
73// tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation
74// tmp.zig:57:14: note: enum declaration does not specify an integer tag type