Merge pull request #20084 from Vexu/missing-errors

Add missing errors to `@ptrFromInt` and Signal calling convention validation
This commit is contained in:
Veikka Tuominen 2024-06-03 14:20:21 +03:00 committed by Andrew Kelley
parent 59dd7a0fbd
commit 46a28175b3
3 changed files with 64 additions and 22 deletions

View File

@ -9700,18 +9700,18 @@ fn funcCommon(
{ {
return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
} }
switch (cc_resolved) {
if (cc_resolved == .Interrupt) switch (target.cpu.arch) { .Interrupt => if (target.cpu.arch.isX86()) {
.x86, .x86_64 => {
const err_code_size = target.ptrBitWidth(); const err_code_size = target.ptrBitWidth();
switch (i) { switch (i) {
0 => if (param_ty.zigTypeTag(mod) != .Pointer) return sema.fail(block, param_src, "parameter must be a pointer type", .{}), 0 => if (param_ty.zigTypeTag(mod) != .Pointer) return sema.fail(block, param_src, "first parameter of function with 'Interrupt' calling convention must be a pointer type", .{}),
1 => if (param_ty.bitSize(mod) != err_code_size) return sema.fail(block, param_src, "parameter must be a {d}-bit integer", .{err_code_size}), 1 => if (param_ty.bitSize(mod) != err_code_size) return sema.fail(block, param_src, "second parameter of function with 'Interrupt' calling convention must be a {d}-bit integer", .{err_code_size}),
else => return sema.fail(block, param_src, "Interrupt calling convention supports up to 2 parameters, found {d}", .{i + 1}), else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}),
}
} else return sema.fail(block, param_src, "parameters are not allowed with 'Interrupt' calling convention", .{}),
.Signal => return sema.fail(block, param_src, "parameters are not allowed with 'Signal' calling convention", .{}),
else => {},
} }
},
else => return sema.fail(block, param_src, "parameters are not allowed with Interrupt calling convention", .{}),
};
} }
var ret_ty_requires_comptime = false; var ret_ty_requires_comptime = false;
@ -10017,6 +10017,16 @@ fn finishFunc(
return sema.failWithOwnedErrorMsg(block, msg); return sema.failWithOwnedErrorMsg(block, msg);
} }
switch (cc_resolved) {
.Interrupt, .Signal => if (return_type.zigTypeTag(mod) != .Void and return_type.zigTypeTag(mod) != .NoReturn) {
return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});
},
.Inline => if (is_noinline) {
return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
},
else => {},
}
const arch = target.cpu.arch; const arch = target.cpu.arch;
if (@as(?[]const u8, switch (cc_resolved) { if (@as(?[]const u8, switch (cc_resolved) {
.Unspecified, .C, .Naked, .Async, .Inline => null, .Unspecified, .C, .Naked, .Async, .Inline => null,
@ -10060,20 +10070,7 @@ fn finishFunc(
}); });
} }
if (cc_resolved == .Interrupt and return_type.zigTypeTag(mod) != .Void) {
return sema.fail(
block,
cc_src,
"non-void return type '{}' not allowed in function with calling convention 'Interrupt'",
.{return_type.fmt(mod)},
);
}
if (cc_resolved == .Inline and is_noinline) {
return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
}
if (is_generic and sema.no_partial_func_ty) return error.GenericPoison; if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) { if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
// Make sure that StackTrace's fields are resolved so that the backend can // Make sure that StackTrace's fields are resolved so that the backend can
// lower this fn type. // lower this fn type.
@ -22707,7 +22704,16 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
.storage = .{ .elems = new_elems }, .storage = .{ .elems = new_elems },
} })); } }));
} }
if (try sema.typeRequiresComptime(ptr_ty)) {
return sema.failWithOwnedErrorMsg(block, msg: {
const msg = try sema.errMsg(block, src, "pointer to comptime-only type '{}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(mod)});
errdefer msg.destroy(sema.gpa);
const src_decl = mod.declPtr(block.src_decl);
try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), ptr_ty);
break :msg msg;
});
}
try sema.requireRuntimeBlock(block, src, operand_src); try sema.requireRuntimeBlock(block, src, operand_src);
if (!is_vector) { if (!is_vector) {
if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) { if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) {

View File

@ -0,0 +1,20 @@
export fn interrupt_param1(_: u32) callconv(.Interrupt) void {}
export fn interrupt_param2(_: *anyopaque, _: u32) callconv(.Interrupt) void {}
export fn interrupt_param3(_: *anyopaque, _: u64, _: u32) callconv(.Interrupt) void {}
export fn interrupt_ret(_: *anyopaque, _: u64) callconv(.Interrupt) u32 {
return 0;
}
export fn signal_param(_: u32) callconv(.Signal) void {}
export fn signal_ret() callconv(.Signal) noreturn {}
// error
// backend=stage2
// target=x86_64-linux
//
// :1:28: error: first parameter of function with 'Interrupt' calling convention must be a pointer type
// :2:43: error: second parameter of function with 'Interrupt' calling convention must be a 64-bit integer
// :3:51: error: 'Interrupt' calling convention supports up to 2 parameters, found 3
// :4:69: error: function with calling convention 'Interrupt' must return 'void' or 'noreturn'
// :8:24: error: parameters are not allowed with 'Signal' calling convention
// :9:34: error: callconv 'Signal' is only available on AVR, not x86_64

View File

@ -0,0 +1,16 @@
const GuSettings = struct {
fin: ?fn (c_int) callconv(.C) void,
};
pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {
const settings: ?*GuSettings = @as(?*GuSettings, @ptrFromInt(@intFromPtr(arg)));
if (settings.?.fin != null) {
settings.?.fin.?(id & 0xffff);
}
}
// error
// target=native
//
// :5:54: error: pointer to comptime-only type '?*tmp.GuSettings' must be comptime-known, but operand is runtime-known
// :2:10: note: struct requires comptime because of this field
// :2:10: note: use '*const fn (c_int) callconv(.C) void' for a function pointer type