static bool method_application(pass_opt_t* opt, ast_t* ast, bool partial) { AST_GET_CHILDREN(ast, positional, namedargs, question, lhs); if(!method_check_type_params(opt, &lhs)) return false; ast_t* type = ast_type(lhs); if(is_typecheck_error(type)) return false; AST_GET_CHILDREN(type, cap, typeparams, params, result); if(!extend_positional_args(opt, params, positional)) return false; if(!apply_named_args(opt, params, positional, namedargs)) return false; if(!check_arg_types(opt, params, positional, partial)) return false; switch(ast_id(lhs)) { case TK_FUNREF: case TK_FUNAPP: if(ast_id(ast_child(type)) != TK_AT) { if(!check_receiver_cap(opt, ast, NULL)) return false; if(!check_nonsendable_recover(opt, ast)) return false; } else { ast_t* receiver = ast_child(lhs); // Dig through function qualification. if((ast_id(receiver) == TK_FUNREF) || (ast_id(receiver) == TK_FUNAPP) || (ast_id(receiver) == TK_FUNCHAIN)) receiver = ast_child(receiver); ast_t* recv_type = ast_type(receiver); if(!is_known(recv_type) && (ast_id(receiver) == TK_TYPEREF)) { ast_error(opt->check.errors, lhs, "a bare method cannot be called on " "an abstract type reference"); return false; } } break; default: {} } return true; }
static bool method_application(pass_opt_t* opt, ast_t* ast, bool partial) { AST_GET_CHILDREN(ast, positional, namedargs, lhs); if(!check_type_params(opt, &lhs)) return false; ast_t* type = ast_type(lhs); if(is_typecheck_error(type)) return false; AST_GET_CHILDREN(type, cap, typeparams, params, result); if(!extend_positional_args(opt, params, positional)) return false; if(!apply_named_args(opt, params, positional, namedargs)) return false; if(!check_arg_types(opt, params, positional, partial)) return false; switch(ast_id(lhs)) { case TK_FUNREF: case TK_FUNAPP: if(!check_receiver_cap(opt, ast, NULL)) return false; if(!check_nonsendable_recover(opt, ast)) return false; break; default: {} } return true; }
static bool method_application(pass_opt_t* opt, ast_t* ast, bool partial) { // TODO: use args to decide unbound type parameters AST_GET_CHILDREN(ast, positional, namedargs, lhs); if(!check_type_params(&lhs)) return false; ast_t* type = ast_type(lhs); if(is_typecheck_error(type)) return false; AST_GET_CHILDREN(type, cap, typeparams, params, result); if(!extend_positional_args(params, positional)) return false; if(!apply_named_args(params, positional, namedargs)) return false; bool incomplete = is_this_incomplete(&opt->check, ast); if(!check_arg_types(opt, params, positional, incomplete, partial)) return false; switch(ast_id(lhs)) { case TK_FUNREF: case TK_FUNAPP: if(!check_receiver_cap(ast, incomplete)) return false; break; default: {} } return true; }
void fold_expr_funcall(expr *e, symtable *stab) { type *func_ty; funcargs *args_from_decl; char *sp = NULL; unsigned count_decl; check_implicit_funcall(e, stab, &sp); FOLD_EXPR(e->expr, stab); func_ty = e->expr->tree_type; if(!type_is_callable(func_ty)){ warn_at_print_error(&e->expr->where, "%s-expression (type '%s') not callable", expr_str_friendly(e->expr, 0), type_to_str(func_ty)); fold_had_error = 1; e->tree_type = type_nav_btype(cc1_type_nav, type_int); return; } e->tree_type = type_func_call(func_ty, &args_from_decl); /* func count comparison, only if the func has arg-decls, or the func is f(void) */ UCC_ASSERT(args_from_decl, "no funcargs for decl %s", sp); count_decl = dynarray_count(args_from_decl->arglist); if(check_arg_counts(args_from_decl, count_decl, e->funcargs, e, sp)) return; if(e->funcargs){ check_arg_voidness_and_nonnulls( e, stab, args_from_decl, count_decl, e->funcargs, sp); } if(!FUNCARGS_EMPTY_NOVOID(args_from_decl)) check_arg_types(args_from_decl, e->funcargs, stab, sp, &e->where); if(e->funcargs) default_promote_args(e->funcargs, count_decl, stab); if(type_is_s_or_u(e->tree_type)){ /* handled transparently by the backend */ e->f_islval = expr_is_lval_struct; cc1_warn_at(&e->expr->where, aggregate_return, "called function returns aggregate (%s)", type_to_str(e->tree_type)); } /* attr */ { type *fnty = e->expr->tree_type; /* look through decays */ if(expr_kind(e->expr, cast) && expr_cast_is_lval2rval(e->expr)) fnty = expr_cast_child(e->expr)->tree_type; format_check_call(fnty, e->funcargs, args_from_decl->variadic); sentinel_check( &e->where, e, e->funcargs, args_from_decl->variadic, count_decl, stab); } /* check the subexp tree type to get the funcall attributes */ if(func_or_builtin_attr_present(e, attr_warn_unused)) e->freestanding = 0; /* needs use */ if(sp && !cc1_fopt.freestanding) check_standard_funcs(sp, e->funcargs); }