Commit 8ac711596d

LemonBoy <thatlemon@gmail.com>
2020-12-08 18:38:50
stage1: Validate the specified cc for lazy fn types
Closes #7337
1 parent 8f646da
Changed files (4)
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)) {
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);
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);
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",