summaryrefslogtreecommitdiffstats
path: root/src/vim9compile.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-04-07 22:05:08 +0200
committerBram Moolenaar <Bram@vim.org>2020-04-07 22:05:08 +0200
commit0b76b42d0a09fb6f1ed79cfc153da4edd6154c89 (patch)
tree7a0391c64b3acc7bed6873aebe36afe54455a1ec /src/vim9compile.c
parentec5929d0fe7e90f953fa5b019486c0c4e5826d92 (diff)
patch 8.2.0528: Vim9: function arguments insufficiently testedv8.2.0528
Problem: Vim9: function arguments insufficiently tested. Solution: Check types. Add more tests. Fix function with varargs only.
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r--src/vim9compile.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 18fbdd36ed..fb0adb3b42 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -130,6 +130,8 @@ static int compile_expr1(char_u **arg, cctx_T *cctx);
static int compile_expr2(char_u **arg, cctx_T *cctx);
static int compile_expr3(char_u **arg, cctx_T *cctx);
static void delete_def_function_contents(dfunc_T *dfunc);
+static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
+static int check_type(type_T *expected, type_T *actual, int give_msg);
/*
* Lookup variable "name" in the local scope and return the index.
@@ -1240,6 +1242,32 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
return FAIL;
}
+ if (ufunc->uf_dfunc_idx >= 0)
+ {
+ int i;
+
+ for (i = 0; i < argcount; ++i)
+ {
+ type_T *expected;
+ type_T *actual;
+
+ if (i < regular_args)
+ {
+ if (ufunc->uf_arg_types == NULL)
+ continue;
+ expected = ufunc->uf_arg_types[i];
+ }
+ else
+ expected = ufunc->uf_va_type->tt_member;
+ actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
+ if (check_type(expected, actual, FALSE) == FAIL)
+ {
+ arg_type_mismatch(expected, actual, i + 1);
+ return FAIL;
+ }
+ }
+ }
+
// Turn varargs into a list.
if (ufunc->uf_va_name != NULL)
{
@@ -2403,6 +2431,18 @@ type_mismatch(type_T *expected, type_T *actual)
vim_free(tofree2);
}
+ static void
+arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
+{
+ char *tofree1, *tofree2;
+
+ semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
+ argidx,
+ type_name(expected, &tofree1), type_name(actual, &tofree2));
+ vim_free(tofree1);
+ vim_free(tofree2);
+}
+
/*
* Check if the expected and actual types match.
*/