Sema: do not allow comptime-only pointer fields in packed structs

This commit is contained in:
mlugg
2023-11-10 01:38:41 +00:00
committed by Matthew Lugg
parent e9b3fcaa43
commit 3f10b3ee1e
2 changed files with 22 additions and 8 deletions

View File

@@ -20923,7 +20923,7 @@ fn zirReify(
break :msg msg;
};
return sema.failWithOwnedErrorMsg(block, msg);
} else if (layout == .Packed and !(validatePackedType(field_ty, mod))) {
} else if (layout == .Packed and !try sema.validatePackedType(field_ty)) {
const msg = msg: {
const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
errdefer msg.destroy(gpa);
@@ -21290,7 +21290,7 @@ fn reifyStruct(
break :msg msg;
};
return sema.failWithOwnedErrorMsg(block, msg);
} else if (layout == .Packed and !(validatePackedType(field_ty, mod))) {
} else if (layout == .Packed and !try sema.validatePackedType(field_ty)) {
const msg = msg: {
const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
errdefer msg.destroy(gpa);
@@ -25663,8 +25663,9 @@ fn explainWhyTypeIsNotExtern(
}
/// Returns true if `ty` is allowed in packed types.
/// Does *NOT* require `ty` to be resolved in any way.
fn validatePackedType(ty: Type, mod: *Module) bool {
/// Does not require `ty` to be resolved in any way, but may resolve whether it is comptime-only.
fn validatePackedType(sema: *Sema, ty: Type) !bool {
const mod = sema.mod;
switch (ty.zigTypeTag(mod)) {
.Type,
.ComptimeFloat,
@@ -25689,7 +25690,7 @@ fn validatePackedType(ty: Type, mod: *Module) bool {
.Vector,
.Enum,
=> return true,
.Pointer => return !ty.isSlice(mod),
.Pointer => return !ty.isSlice(mod) and !try sema.typeRequiresComptime(ty),
.Struct, .Union => return ty.containerLayout(mod) == .Packed,
}
}
@@ -25724,7 +25725,12 @@ fn explainWhyTypeIsNotPacked(
.Optional,
.Array,
=> try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}),
.Pointer => try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{}),
.Pointer => if (ty.isSlice(mod)) {
try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{});
} else {
try mod.errNoteNonLazy(src_loc, msg, "comptime-only pointer has no guaranteed in-memory representation", .{});
try sema.explainWhyTypeIsComptime(msg, src_loc, ty);
},
.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", .{});
@@ -35890,7 +35896,7 @@ fn semaStructFields(
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
},
.Packed => if (!validatePackedType(field_ty, mod)) {
.Packed => if (!try sema.validatePackedType(field_ty)) {
const msg = msg: {
const ty_src = mod.fieldSrcLoc(decl_index, .{
.index = field_i,
@@ -36443,7 +36449,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
break :msg msg;
};
return sema.failWithOwnedErrorMsg(&block_scope, msg);
} else if (layout == .Packed and !validatePackedType(field_ty, mod)) {
} else if (layout == .Packed and !try sema.validatePackedType(field_ty)) {
const msg = msg: {
const ty_src = mod.fieldSrcLoc(union_type.decl, .{
.index = field_i,

View File

@@ -65,6 +65,11 @@ export fn entry12() void {
x: packed struct { a: []u8 },
});
}
export fn entry13() void {
_ = @sizeOf(packed struct {
x: *type,
});
}
// error
// backend=llvm
@@ -89,3 +94,6 @@ export fn entry12() void {
// :38:12: note: use '*const ' to make a function pointer type
// :65:31: error: packed structs cannot contain fields of type '[]u8'
// :65:31: note: slices have no guaranteed in-memory representation
// :70:12: error: packed structs cannot contain fields of type '*type'
// :70:12: note: comptime-only pointer has no guaranteed in-memory representation
// :70:12: note: types are not available at runtime