parent
974d69ea3d
commit
d0a1901cb0
@ -3593,33 +3593,27 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
TypeTableEntry *expected_type, AstNode *node, FnTableEntry *fn_table_entry, TypeTableEntry *struct_type)
|
TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type, TypeTableEntry *struct_type)
|
||||||
{
|
{
|
||||||
assert(node->type == NodeTypeFnCallExpr);
|
assert(node->type == NodeTypeFnCallExpr);
|
||||||
|
|
||||||
node->data.fn_call_expr.fn_entry = fn_table_entry;
|
|
||||||
assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
|
|
||||||
AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto;
|
|
||||||
|
|
||||||
// count parameters
|
// count parameters
|
||||||
int expected_param_count = fn_proto->params.length;
|
int src_param_count = fn_type->data.fn.src_param_count;
|
||||||
int actual_param_count = node->data.fn_call_expr.params.length;
|
int actual_param_count = node->data.fn_call_expr.params.length;
|
||||||
|
|
||||||
if (struct_type) {
|
if (struct_type) {
|
||||||
actual_param_count += 1;
|
actual_param_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn_proto->is_var_args) {
|
if (fn_type->data.fn.is_var_args) {
|
||||||
if (actual_param_count < expected_param_count) {
|
if (actual_param_count < src_param_count) {
|
||||||
add_node_error(g, node,
|
add_node_error(g, node,
|
||||||
buf_sprintf("expected at least %d arguments, got %d",
|
buf_sprintf("expected at least %d arguments, got %d", src_param_count, actual_param_count));
|
||||||
expected_param_count, actual_param_count));
|
|
||||||
}
|
}
|
||||||
} else if (expected_param_count != actual_param_count) {
|
} else if (src_param_count != actual_param_count) {
|
||||||
add_node_error(g, node,
|
add_node_error(g, node,
|
||||||
buf_sprintf("expected %d arguments, got %d",
|
buf_sprintf("expected %d arguments, got %d", src_param_count, actual_param_count));
|
||||||
expected_param_count, actual_param_count));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// analyze each parameter. in the case of a method, we already analyzed the
|
// analyze each parameter. in the case of a method, we already analyzed the
|
||||||
@ -3629,19 +3623,13 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
|
|||||||
// determine the expected type for each parameter
|
// determine the expected type for each parameter
|
||||||
TypeTableEntry *expected_param_type = nullptr;
|
TypeTableEntry *expected_param_type = nullptr;
|
||||||
int fn_proto_i = i + (struct_type ? 1 : 0);
|
int fn_proto_i = i + (struct_type ? 1 : 0);
|
||||||
if (fn_proto_i < fn_proto->params.length) {
|
if (fn_proto_i < src_param_count) {
|
||||||
AstNode *param_decl_node = fn_proto->params.at(fn_proto_i);
|
expected_param_type = fn_type->data.fn.param_types[fn_proto_i];
|
||||||
assert(param_decl_node->type == NodeTypeParamDecl);
|
|
||||||
AstNode *param_type_node = param_decl_node->data.param_decl.type;
|
|
||||||
TypeTableEntry *param_type_entry = get_resolved_expr(param_type_node)->type_entry;
|
|
||||||
if (param_type_entry) {
|
|
||||||
expected_param_type = unwrapped_node_type(param_type_node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
analyze_expression(g, import, context, expected_param_type, child);
|
analyze_expression(g, import, context, expected_param_type, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeTableEntry *return_type = unwrapped_node_type(fn_proto->return_type);
|
TypeTableEntry *return_type = fn_type->data.fn.src_return_type;
|
||||||
|
|
||||||
if (return_type->id == TypeTableEntryIdInvalid) {
|
if (return_type->id == TypeTableEntryIdInvalid) {
|
||||||
return return_type;
|
return return_type;
|
||||||
@ -3654,6 +3642,17 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
|
|||||||
return return_type;
|
return return_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
|
TypeTableEntry *expected_type, AstNode *node, FnTableEntry *fn_table_entry, TypeTableEntry *struct_type)
|
||||||
|
{
|
||||||
|
assert(node->type == NodeTypeFnCallExpr);
|
||||||
|
|
||||||
|
node->data.fn_call_expr.fn_entry = fn_table_entry;
|
||||||
|
|
||||||
|
return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
TypeTableEntry *expected_type, AstNode *node)
|
TypeTableEntry *expected_type, AstNode *node)
|
||||||
{
|
{
|
||||||
@ -3761,7 +3760,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
|
|||||||
|
|
||||||
// function pointer
|
// function pointer
|
||||||
if (invoke_type_entry->id == TypeTableEntryIdFn) {
|
if (invoke_type_entry->id == TypeTableEntryIdFn) {
|
||||||
return invoke_type_entry->data.fn.src_return_type;
|
return analyze_fn_call_ptr(g, import, context, expected_type, node, invoke_type_entry, nullptr);
|
||||||
} else {
|
} else {
|
||||||
add_node_error(g, fn_ref_expr,
|
add_node_error(g, fn_ref_expr,
|
||||||
buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
|
buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
|
||||||
|
@ -1823,6 +1823,29 @@ const x : u8 = 300;
|
|||||||
const x = 2 == 2.0;
|
const x = 2 == 2.0;
|
||||||
)SOURCE", 1, ".tmp_source.zig:2:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'");
|
)SOURCE", 1, ".tmp_source.zig:2:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'");
|
||||||
|
|
||||||
|
add_compile_fail_case("missing function call param", R"SOURCE(
|
||||||
|
struct Foo {
|
||||||
|
a: i32,
|
||||||
|
b: i32,
|
||||||
|
|
||||||
|
fn member_a(foo: Foo) -> i32 {
|
||||||
|
return foo.a;
|
||||||
|
}
|
||||||
|
fn member_b(foo: Foo) -> i32 {
|
||||||
|
return foo.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const member_fn_type = @typeof(Foo.member_a);
|
||||||
|
const members = []member_fn_type {
|
||||||
|
Foo.member_a,
|
||||||
|
Foo.member_b,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn f(foo: Foo, index: i32) {
|
||||||
|
const result = members[index]();
|
||||||
|
}
|
||||||
|
)SOURCE", 1, ".tmp_source.zig:21:34: error: expected 1 arguments, got 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
x
Reference in New Issue
Block a user