diff src/vim9compile.c @ 19944:3055cd26e139 v8.2.0528

patch 8.2.0528: Vim9: function arguments insufficiently tested Commit: https://github.com/vim/vim/commit/0b76b42d0a09fb6f1ed79cfc153da4edd6154c89 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Apr 7 22:05:08 2020 +0200 patch 8.2.0528: Vim9: function arguments insufficiently tested Problem: Vim9: function arguments insufficiently tested. Solution: Check types. Add more tests. Fix function with varargs only.
author Bram Moolenaar <Bram@vim.org>
date Tue, 07 Apr 2020 22:15:05 +0200
parents b471038ec3ea
children 8466e62a2481
line wrap: on
line diff
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -130,6 +130,8 @@ static int compile_expr1(char_u **arg,  
 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 *ufu
 	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 *
     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.
  */