stage1: Validate the specified cc for lazy fn types

Closes #7337
This commit is contained in:
LemonBoy 2020-12-08 18:38:50 +01:00 committed by Andrew Kelley
parent 8f646daed6
commit 8ac711596d
4 changed files with 31 additions and 3 deletions

View File

@ -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)) {

View File

@ -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);

View File

@ -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);

View File

@ -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",