Commit b757a96d5c
Changed files (7)
src
src/Sema.zig
@@ -5409,6 +5409,19 @@ fn lookupInNamespace(
return null;
}
+fn funcDeclSrc(sema: *Sema, block: *Block, src: LazySrcLoc, func_inst: Air.Inst.Ref) !?Module.SrcLoc {
+ const func_val = (try sema.resolveMaybeUndefVal(block, src, func_inst)) orelse return null;
+ if (func_val.isUndef()) return null;
+ const owner_decl_index = switch (func_val.tag()) {
+ .extern_fn => func_val.castTag(.extern_fn).?.data.owner_decl,
+ .function => func_val.castTag(.function).?.data.owner_decl,
+ .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,
+ else => return null,
+ };
+ const owner_decl = sema.mod.declPtr(owner_decl_index);
+ return owner_decl.srcLoc();
+}
+
fn zirCall(
sema: *Sema,
block: *Block,
@@ -5464,41 +5477,35 @@ fn zirCall(
const func_ty_info = func_ty.fnInfo();
const fn_params_len = func_ty_info.param_types.len;
- if (func_ty_info.is_var_args) {
- assert(func_ty_info.cc == .C);
- if (total_args < fn_params_len) {
- // TODO add error note: declared here
- if (bound_arg_src != null) {
- return sema.fail(
- block,
- call_src,
- "member function expected at least {d} argument(s), found {d}",
- .{ fn_params_len - 1, args_len },
- );
- }
- return sema.fail(
- block,
- func_src,
- "expected at least {d} argument(s), found {d}",
- .{ fn_params_len, args_len },
- );
+ check_args: {
+ if (func_ty_info.is_var_args) {
+ assert(func_ty_info.cc == .C);
+ if (total_args >= fn_params_len) break :check_args;
+ } else if (fn_params_len == total_args) {
+ break :check_args;
}
- } else if (fn_params_len != total_args) {
- // TODO add error note: declared here
- if (bound_arg_src != null) {
- return sema.fail(
+
+ const decl_src = try sema.funcDeclSrc(block, func_src, func);
+ const member_str = if (bound_arg_src != null) "member function " else "";
+ const variadic_str = if (func_ty_info.is_var_args) "at least " else "";
+ const msg = msg: {
+ const msg = try sema.errMsg(
block,
- call_src,
- "member function expected {d} argument(s), found {d}",
- .{ fn_params_len - 1, args_len },
+ func_src,
+ "{s}expected {s}{d} argument(s), found {d}",
+ .{
+ member_str,
+ variadic_str,
+ fn_params_len - @boolToInt(bound_arg_src != null),
+ args_len,
+ },
);
- }
- return sema.fail(
- block,
- call_src,
- "expected {d} argument(s), found {d}",
- .{ fn_params_len, args_len },
- );
+ errdefer msg.destroy(sema.gpa);
+
+ if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{});
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
}
const args_body = sema.code.extra[extra.end..];
@@ -5625,13 +5632,20 @@ fn analyzeCall(
const func_ty_info = func_ty.fnInfo();
const cc = func_ty_info.cc;
if (cc == .Naked) {
- // TODO add error note: declared here
- return sema.fail(
- block,
- func_src,
- "unable to call function with naked calling convention",
- .{},
- );
+ const decl_src = try sema.funcDeclSrc(block, func_src, func);
+ const msg = msg: {
+ const msg = try sema.errMsg(
+ block,
+ func_src,
+ "unable to call function with naked calling convention",
+ .{},
+ );
+ errdefer msg.destroy(sema.gpa);
+
+ if (decl_src) |some| try sema.mod.errNoteNonLazy(some, msg, "function declared here", .{});
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
}
const fn_params_len = func_ty_info.param_types.len;
if (func_ty_info.is_var_args) {
test/cases/compile_errors/stage1/obj/calling_function_with_naked_calling_convention.zig
@@ -1,11 +0,0 @@
-export fn entry() void {
- foo();
-}
-fn foo() callconv(.Naked) void { }
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:5: error: unable to call function with naked calling convention
-// tmp.zig:4:1: note: declared here
test/cases/compile_errors/stage1/obj/wrong_number_of_arguments_for_method_fn_call.zig
@@ -1,14 +0,0 @@
-const Foo = struct {
- fn method(self: *const Foo, a: i32) void {_ = self; _ = a;}
-};
-fn f(foo: *const Foo) void {
-
- foo.method(1, 2);
-}
-export fn entry() usize { return @sizeOf(@TypeOf(f)); }
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:6:15: error: expected 2 argument(s), found 3
test/cases/compile_errors/calling_function_with_naked_calling_convention.zig
@@ -0,0 +1,11 @@
+export fn entry() void {
+ foo();
+}
+fn foo() callconv(.Naked) void { }
+
+// error
+// backend=llvm
+// target=native
+//
+// :2:5: error: unable to call function with naked calling convention
+// :4:1: note: function declared here
test/cases/compile_errors/member_function_arg_mismatch.zig
@@ -11,4 +11,5 @@ pub export fn entry() void {
// backend=stage2
// target=native
//
-// :7:10: error: member function expected 2 argument(s), found 1
+// :7:6: error: member function expected 2 argument(s), found 1
+// :3:5: note: function declared here
test/cases/compile_errors/wrong_number_of_arguments.zig
@@ -7,4 +7,5 @@ fn c(d: i32, e: i32, f: i32) void { _ = d; _ = e; _ = f; }
// backend=stage2
// target=native
//
-// :2:6: error: expected 3 argument(s), found 1
+// :2:5: error: expected 3 argument(s), found 1
+// :4:1: note: function declared here
test/cases/compile_errors/wrong_number_of_arguments_for_method_fn_call.zig
@@ -0,0 +1,15 @@
+const Foo = struct {
+ fn method(self: *const Foo, a: i32) void {_ = self; _ = a;}
+};
+fn f(foo: *const Foo) void {
+
+ foo.method(1, 2);
+}
+export fn entry() usize { return @sizeOf(@TypeOf(&f)); }
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:8: error: member function expected 1 argument(s), found 2
+// :2:5: note: function declared here