| ... | @@ -6628,7 +6628,7 @@ fn checkCallArgumentCount( | ... | @@ -6628,7 +6628,7 @@ fn checkCallArgumentCount( |
| 6628 | const fn_params_len = func_ty_info.param_types.len; | 6628 | const fn_params_len = func_ty_info.param_types.len; |
| 6629 | const args_len = total_args - @intFromBool(member_fn); | 6629 | const args_len = total_args - @intFromBool(member_fn); |
| 6630 | if (func_ty_info.is_var_args) { | 6630 | if (func_ty_info.is_var_args) { |
| 6631 | assert(func_ty_info.cc == .C); | 6631 | assert(callConvSupportsVarArgs(func_ty_info.cc)); |
| 6632 | if (total_args >= fn_params_len) return func_ty; | 6632 | if (total_args >= fn_params_len) return func_ty; |
| 6633 | } else if (fn_params_len == total_args) { | 6633 | } else if (fn_params_len == total_args) { |
| 6634 | return func_ty; | 6634 | return func_ty; |
| ... | @@ -8917,6 +8917,41 @@ fn handleExternLibName( | ... | @@ -8917,6 +8917,41 @@ fn handleExternLibName( |
| 8917 | return sema.gpa.dupeZ(u8, lib_name); | 8917 | return sema.gpa.dupeZ(u8, lib_name); |
| 8918 | } | 8918 | } |
| 8919 | | 8919 | |
| | 8920 | /// These are calling conventions that are confirmed to work with variadic functions. |
| | 8921 | /// Any calling conventions not included here are either not yet verified to work with variadic |
| | 8922 | /// functions or there are no more other calling conventions that support variadic functions. |
| | 8923 | const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention{ |
| | 8924 | .C, |
| | 8925 | }; |
| | 8926 | fn callConvSupportsVarArgs(cc: std.builtin.CallingConvention) bool { |
| | 8927 | return for (calling_conventions_supporting_var_args) |supported_cc| { |
| | 8928 | if (cc == supported_cc) return true; |
| | 8929 | } else false; |
| | 8930 | } |
| | 8931 | fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.builtin.CallingConvention) CompileError!void { |
| | 8932 | const CallingConventionsSupportingVarArgsList = struct { |
| | 8933 | pub fn format(_: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| | 8934 | _ = fmt; |
| | 8935 | _ = options; |
| | 8936 | for (calling_conventions_supporting_var_args, 0..) |cc_inner, i| { |
| | 8937 | if (i != 0) |
| | 8938 | try writer.writeAll(", "); |
| | 8939 | try writer.print("'.{s}'", .{@tagName(cc_inner)}); |
| | 8940 | } |
| | 8941 | } |
| | 8942 | }; |
| | 8943 | |
| | 8944 | if (!callConvSupportsVarArgs(cc)) { |
| | 8945 | const msg = msg: { |
| | 8946 | const msg = try sema.errMsg(block, src, "variadic function does not support '.{s}' calling convention", .{@tagName(cc)}); |
| | 8947 | errdefer msg.destroy(sema.gpa); |
| | 8948 | try sema.errNote(block, src, msg, "supported calling conventions: {}", .{CallingConventionsSupportingVarArgsList{}}); |
| | 8949 | break :msg msg; |
| | 8950 | }; |
| | 8951 | return sema.failWithOwnedErrorMsg(msg); |
| | 8952 | } |
| | 8953 | } |
| | 8954 | |
| 8920 | const FuncLinkSection = union(enum) { | 8955 | const FuncLinkSection = union(enum) { |
| 8921 | generic, | 8956 | generic, |
| 8922 | default, | 8957 | default, |
| ... | @@ -8963,9 +8998,7 @@ fn funcCommon( | ... | @@ -8963,9 +8998,7 @@ fn funcCommon( |
| 8963 | if (is_generic) { | 8998 | if (is_generic) { |
| 8964 | return sema.fail(block, func_src, "generic function cannot be variadic", .{}); | 8999 | return sema.fail(block, func_src, "generic function cannot be variadic", .{}); |
| 8965 | } | 9000 | } |
| 8966 | if (cc.? != .C) { | 9001 | try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?); |
| 8967 | return sema.fail(block, cc_src, "variadic function must have 'C' calling convention", .{}); | | |
| 8968 | } | | |
| 8969 | } | 9002 | } |
| 8970 | | 9003 | |
| 8971 | var destroy_fn_on_error = false; | 9004 | var destroy_fn_on_error = false; |
| ... | @@ -20325,8 +20358,8 @@ fn zirReify( | ... | @@ -20325,8 +20358,8 @@ fn zirReify( |
| 20325 | | 20358 | |
| 20326 | const is_var_args = is_var_args_val.toBool(); | 20359 | const is_var_args = is_var_args_val.toBool(); |
| 20327 | const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val); | 20360 | const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val); |
| 20328 | if (is_var_args and cc != .C) { | 20361 | if (is_var_args) { |
| 20329 | return sema.fail(block, src, "varargs functions must have C calling convention", .{}); | 20362 | try sema.checkCallConvSupportsVarArgs(block, src, cc); |
| 20330 | } | 20363 | } |
| 20331 | | 20364 | |
| 20332 | const alignment = alignment: { | 20365 | const alignment = alignment: { |