authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-06-03 14:20:21+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-06-06 10:45:10-07:00
log46a28175b3ed3d763b76c6f2632879ab3bf87f76
tree0af69eaafc34d5706cf5bddec9713e709c6a5a88
parent59dd7a0fbd5c06b89eea965b5fbc3f25e3eb21db

Merge pull request #20084 from Vexu/missing-errors

Add missing errors to `@ptrFromInt` and Signal calling convention validation

3 files changed, 64 insertions(+), 22 deletions(-)

src/Sema.zig+28-22
......@@ -9700,18 +9700,18 @@ fn funcCommon(
97009700 {
97019701 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
97029702 }
9703
9704 if (cc_resolved == .Interrupt) switch (target.cpu.arch) {
9705 .x86, .x86_64 => {
9703 switch (cc_resolved) {
9704 .Interrupt => if (target.cpu.arch.isX86()) {
97069705 const err_code_size = target.ptrBitWidth();
97079706 switch (i) {
9708 0 => if (param_ty.zigTypeTag(mod) != .Pointer) return sema.fail(block, param_src, "parameter must be a pointer type", .{}),
9709 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}),
9710 else => return sema.fail(block, param_src, "Interrupt calling convention supports up to 2 parameters, found {d}", .{i + 1}),
9707 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", .{}),
9708 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}),
9709 else => return sema.fail(block, param_src, "'Interrupt' calling convention supports up to 2 parameters, found {d}", .{i + 1}),
97119710 }
9712 },
9713 else => return sema.fail(block, param_src, "parameters are not allowed with Interrupt calling convention", .{}),
9714 };
9711 } else return sema.fail(block, param_src, "parameters are not allowed with 'Interrupt' calling convention", .{}),
9712 .Signal => return sema.fail(block, param_src, "parameters are not allowed with 'Signal' calling convention", .{}),
9713 else => {},
9714 }
97159715 }
97169716
97179717 var ret_ty_requires_comptime = false;
......@@ -10017,6 +10017,16 @@ fn finishFunc(
1001710017 return sema.failWithOwnedErrorMsg(block, msg);
1001810018 }
1001910019
10020 switch (cc_resolved) {
10021 .Interrupt, .Signal => if (return_type.zigTypeTag(mod) != .Void and return_type.zigTypeTag(mod) != .NoReturn) {
10022 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});
10023 },
10024 .Inline => if (is_noinline) {
10025 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
10026 },
10027 else => {},
10028 }
10029
1002010030 const arch = target.cpu.arch;
1002110031 if (@as(?[]const u8, switch (cc_resolved) {
1002210032 .Unspecified, .C, .Naked, .Async, .Inline => null,
......@@ -10060,20 +10070,7 @@ fn finishFunc(
1006010070 });
1006110071 }
1006210072
10063 if (cc_resolved == .Interrupt and return_type.zigTypeTag(mod) != .Void) {
10064 return sema.fail(
10065 block,
10066 cc_src,
10067 "non-void return type '{}' not allowed in function with calling convention 'Interrupt'",
10068 .{return_type.fmt(mod)},
10069 );
10070 }
10071
10072 if (cc_resolved == .Inline and is_noinline) {
10073 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
10074 }
1007510073 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
10076
1007710074 if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
1007810075 // Make sure that StackTrace's fields are resolved so that the backend can
1007910076 // lower this fn type.
......@@ -22707,7 +22704,16 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2270722704 .storage = .{ .elems = new_elems },
2270822705 } }));
2270922706 }
22707 if (try sema.typeRequiresComptime(ptr_ty)) {
22708 return sema.failWithOwnedErrorMsg(block, msg: {
22709 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)});
22710 errdefer msg.destroy(sema.gpa);
2271022711
22712 const src_decl = mod.declPtr(block.src_decl);
22713 try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), ptr_ty);
22714 break :msg msg;
22715 });
22716 }
2271122717 try sema.requireRuntimeBlock(block, src, operand_src);
2271222718 if (!is_vector) {
2271322719 if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) {
test/cases/compile_errors/invalid_func_for_callconv.zig created+20
......@@ -0,0 +1,20 @@
1export fn interrupt_param1(_: u32) callconv(.Interrupt) void {}
2export fn interrupt_param2(_: *anyopaque, _: u32) callconv(.Interrupt) void {}
3export fn interrupt_param3(_: *anyopaque, _: u64, _: u32) callconv(.Interrupt) void {}
4export fn interrupt_ret(_: *anyopaque, _: u64) callconv(.Interrupt) u32 {
5 return 0;
6}
7
8export fn signal_param(_: u32) callconv(.Signal) void {}
9export 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
test/cases/compile_errors/runtime_@ptrFromInt_to_comptime_only_type.zig created+16
......@@ -0,0 +1,16 @@
1const GuSettings = struct {
2 fin: ?fn (c_int) callconv(.C) void,
3};
4pub 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