diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 4bbdd38869..2638744dd7 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -1880,7 +1880,7 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) { } // Sync this with get_llvm_cc in codegen.cpp -static Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_node, CallingConvention cc) { +Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_node, CallingConvention cc) { Error ret = ErrorNone; const char *allowed_platforms = nullptr; switch (cc) { @@ -2065,8 +2065,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc fn_entry->align_bytes = fn_type_id.alignment; } - if ((err = emit_error_unless_callconv_allowed_for_target(g, proto_node->data.fn_proto.callconv_expr, cc))) - return g->builtin_types.entry_invalid; + if (proto_node->data.fn_proto.callconv_expr != nullptr) { + if ((err = emit_error_unless_callconv_allowed_for_target(g, proto_node->data.fn_proto.callconv_expr, cc))) + return g->builtin_types.entry_invalid; + } if (fn_proto->return_anytype_token != nullptr) { if (!calling_convention_allows_zig_types(fn_type_id.cc)) { diff --git a/src/stage1/analyze.hpp b/src/stage1/analyze.hpp index cde5b516b8..cea48b893c 100644 --- a/src/stage1/analyze.hpp +++ b/src/stage1/analyze.hpp @@ -46,6 +46,7 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c ZigType *get_test_fn_type(CodeGen *g); ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type); bool handle_is_ptr(CodeGen *g, ZigType *type_entry); +Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_node, CallingConvention cc); bool type_has_bits(CodeGen *g, ZigType *type_entry); Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 8f42b8fbbd..923b3f7a7e 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -32796,6 +32796,11 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La FnTypeId fn_type_id = {0}; init_fn_type_id(&fn_type_id, proto_node, lazy_fn_type->cc, proto_node->data.fn_proto.params.length); + if (proto_node->data.fn_proto.callconv_expr != nullptr) { + if ((err = emit_error_unless_callconv_allowed_for_target(ira->codegen, proto_node->data.fn_proto.callconv_expr, lazy_fn_type->cc))) + return nullptr; + } + for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); assert(param_node->type == NodeTypeParamDecl); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 0c003d8db1..3e6875698f 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -94,6 +94,26 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { }; break :x tc; }); + cases.addCase(x: { + var tc = cases.create("callconv(.Stdcall, .Fastcall, .Thiscall) on unsupported platform", + \\const F1 = fn () callconv(.Stdcall) void; + \\const F2 = fn () callconv(.Fastcall) void; + \\const F3 = fn () callconv(.Thiscall) void; + \\export fn entry1() void { var a: F1 = undefined; } + \\export fn entry2() void { var a: F2 = undefined; } + \\export fn entry3() void { var a: F3 = undefined; } + , &[_][]const u8{ + "tmp.zig:1:27: error: callconv 'Stdcall' is only available on x86, not x86_64", + "tmp.zig:2:27: error: callconv 'Fastcall' is only available on x86, not x86_64", + "tmp.zig:3:27: error: callconv 'Thiscall' is only available on x86, not x86_64", + }); + tc.target = std.zig.CrossTarget{ + .cpu_arch = .x86_64, + .os_tag = .linux, + .abi = .none, + }; + break :x tc; + }); cases.addCase(x: { var tc = cases.create("callconv(.Stdcall, .Fastcall, .Thiscall) on unsupported platform",