Skip to content

Commit 7f6ec51

Browse files
authored
Merge pull request #20084 from Vexu/missing-errors
Add missing errors to `@ptrFromInt` and Signal calling convention validation
2 parents db75a87 + 15791b8 commit 7f6ec51

File tree

3 files changed

+64
-22
lines changed

3 files changed

+64
-22
lines changed

src/Sema.zig

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9714,18 +9714,18 @@ fn funcCommon(
97149714
{
97159715
return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
97169716
}
9717-
9718-
if (cc_resolved == .Interrupt) switch (target.cpu.arch) {
9719-
.x86, .x86_64 => {
9717+
switch (cc_resolved) {
9718+
.Interrupt => if (target.cpu.arch.isX86()) {
97209719
const err_code_size = target.ptrBitWidth();
97219720
switch (i) {
9722-
0 => if (param_ty.zigTypeTag(mod) != .Pointer) return sema.fail(block, param_src, "parameter must be a pointer type", .{}),
9723-
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}),
9724-
else => return sema.fail(block, param_src, "Interrupt calling convention supports up to 2 parameters, found {d}", .{i + 1}),
9721+
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", .{}),
9722+
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}),
9723+
else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}),
97259724
}
9726-
},
9727-
else => return sema.fail(block, param_src, "parameters are not allowed with Interrupt calling convention", .{}),
9728-
};
9725+
} else return sema.fail(block, param_src, "parameters are not allowed with 'Interrupt' calling convention", .{}),
9726+
.Signal => return sema.fail(block, param_src, "parameters are not allowed with 'Signal' calling convention", .{}),
9727+
else => {},
9728+
}
97299729
}
97309730

97319731
var ret_ty_requires_comptime = false;
@@ -10031,6 +10031,16 @@ fn finishFunc(
1003110031
return sema.failWithOwnedErrorMsg(block, msg);
1003210032
}
1003310033

10034+
switch (cc_resolved) {
10035+
.Interrupt, .Signal => if (return_type.zigTypeTag(mod) != .Void and return_type.zigTypeTag(mod) != .NoReturn) {
10036+
return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});
10037+
},
10038+
.Inline => if (is_noinline) {
10039+
return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
10040+
},
10041+
else => {},
10042+
}
10043+
1003410044
const arch = target.cpu.arch;
1003510045
if (@as(?[]const u8, switch (cc_resolved) {
1003610046
.Unspecified, .C, .Naked, .Async, .Inline => null,
@@ -10074,20 +10084,7 @@ fn finishFunc(
1007410084
});
1007510085
}
1007610086

10077-
if (cc_resolved == .Interrupt and return_type.zigTypeTag(mod) != .Void) {
10078-
return sema.fail(
10079-
block,
10080-
cc_src,
10081-
"non-void return type '{}' not allowed in function with calling convention 'Interrupt'",
10082-
.{return_type.fmt(mod)},
10083-
);
10084-
}
10085-
10086-
if (cc_resolved == .Inline and is_noinline) {
10087-
return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
10088-
}
1008910087
if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
10090-
1009110088
if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
1009210089
// Make sure that StackTrace's fields are resolved so that the backend can
1009310090
// lower this fn type.
@@ -22722,7 +22719,16 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2272222719
.storage = .{ .elems = new_elems },
2272322720
} }));
2272422721
}
22722+
if (try sema.typeRequiresComptime(ptr_ty)) {
22723+
return sema.failWithOwnedErrorMsg(block, msg: {
22724+
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)});
22725+
errdefer msg.destroy(sema.gpa);
2272522726

22727+
const src_decl = mod.declPtr(block.src_decl);
22728+
try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), ptr_ty);
22729+
break :msg msg;
22730+
});
22731+
}
2272622732
try sema.requireRuntimeBlock(block, src, operand_src);
2272722733
if (!is_vector) {
2272822734
if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export fn interrupt_param1(_: u32) callconv(.Interrupt) void {}
2+
export fn interrupt_param2(_: *anyopaque, _: u32) callconv(.Interrupt) void {}
3+
export fn interrupt_param3(_: *anyopaque, _: u64, _: u32) callconv(.Interrupt) void {}
4+
export fn interrupt_ret(_: *anyopaque, _: u64) callconv(.Interrupt) u32 {
5+
return 0;
6+
}
7+
8+
export fn signal_param(_: u32) callconv(.Signal) void {}
9+
export fn signal_ret() callconv(.Signal) noreturn {}
10+
11+
// error
12+
// backend=stage2
13+
// target=x86_64-linux
14+
//
15+
// :1:28: error: first parameter of function with 'Interrupt' calling convention must be a pointer type
16+
// :2:43: error: second parameter of function with 'Interrupt' calling convention must be a 64-bit integer
17+
// :3:51: error: 'Interrupt' calling convention supports up to 2 parameters, found 3
18+
// :4:69: error: function with calling convention 'Interrupt' must return 'void' or 'noreturn'
19+
// :8:24: error: parameters are not allowed with 'Signal' calling convention
20+
// :9:34: error: callconv 'Signal' is only available on AVR, not x86_64
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const GuSettings = struct {
2+
fin: ?fn (c_int) callconv(.C) void,
3+
};
4+
pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void {
5+
const settings: ?*GuSettings = @as(?*GuSettings, @ptrFromInt(@intFromPtr(arg)));
6+
if (settings.?.fin != null) {
7+
settings.?.fin.?(id & 0xffff);
8+
}
9+
}
10+
11+
// error
12+
// target=native
13+
//
14+
// :5:54: error: pointer to comptime-only type '?*tmp.GuSettings' must be comptime-known, but operand is runtime-known
15+
// :2:10: note: struct requires comptime because of this field
16+
// :2:10: note: use '*const fn (c_int) callconv(.C) void' for a function pointer type

0 commit comments

Comments
 (0)