| ... | ... | @@ -6628,7 +6628,7 @@ fn checkCallArgumentCount( |
| 6628 | 6628 | const fn_params_len = func_ty_info.param_types.len; |
| 6629 | 6629 | const args_len = total_args - @intFromBool(member_fn); |
| 6630 | 6630 | if (func_ty_info.is_var_args) { |
| 6631 | | assert(func_ty_info.cc == .C); |
| 6631 | assert(callConvSupportsVarArgs(func_ty_info.cc)); |
| 6632 | 6632 | if (total_args >= fn_params_len) return func_ty; |
| 6633 | 6633 | } else if (fn_params_len == total_args) { |
| 6634 | 6634 | return func_ty; |
| ... | ... | @@ -8917,6 +8917,41 @@ fn handleExternLibName( |
| 8917 | 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 | 8955 | const FuncLinkSection = union(enum) { |
| 8921 | 8956 | generic, |
| 8922 | 8957 | default, |
| ... | ... | @@ -8963,9 +8998,7 @@ fn funcCommon( |
| 8963 | 8998 | if (is_generic) { |
| 8964 | 8999 | return sema.fail(block, func_src, "generic function cannot be variadic", .{}); |
| 8965 | 9000 | } |
| 8966 | | if (cc.? != .C) { |
| 8967 | | return sema.fail(block, cc_src, "variadic function must have 'C' calling convention", .{}); |
| 8968 | | } |
| 9001 | try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?); |
| 8969 | 9002 | } |
| 8970 | 9003 | |
| 8971 | 9004 | var destroy_fn_on_error = false; |
| ... | ... | @@ -20325,8 +20358,8 @@ fn zirReify( |
| 20325 | 20358 | |
| 20326 | 20359 | const is_var_args = is_var_args_val.toBool(); |
| 20327 | 20360 | const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val); |
| 20328 | | if (is_var_args and cc != .C) { |
| 20329 | | return sema.fail(block, src, "varargs functions must have C calling convention", .{}); |
| 20361 | if (is_var_args) { |
| 20362 | try sema.checkCallConvSupportsVarArgs(block, src, cc); |
| 20330 | 20363 | } |
| 20331 | 20364 | |
| 20332 | 20365 | const alignment = alignment: { |