# HG changeset patch # User Christian Brabandt # Date 1469967305 -7200 # Node ID 6226de5f81379403adc6ada5a85ace71a003a6f0 # Parent f294f224b8fc8a25d2ac6f4a07c9e8298b9bd961 commit https://github.com/vim/vim/commit/b54c3ff3174dbb5dfbfcabdf95200b047beaa644 Author: Bram Moolenaar Date: Sun Jul 31 14:11:58 2016 +0200 patch 7.4.2134 Problem: No error for using function() badly. Solution: Check for passing wrong function name. (Ken Takata) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -7813,7 +7813,7 @@ var_check_func_name( /* Don't allow hiding a function. When "v" is not NULL we might be * assigning another function to the same var, the type is checked * below. */ - if (new_var && function_exists(name)) + if (new_var && function_exists(name, FALSE)) { EMSG2(_("E705: Variable name conflicts with existing function: %s"), name); diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2845,7 +2845,7 @@ f_exists(typval_T *argvars, typval_T *re } else if (*p == '*') /* internal or user defined function */ { - n = function_exists(p + 1); + n = function_exists(p + 1, FALSE); } else if (*p == ':') { @@ -3577,7 +3577,7 @@ f_function(typval_T *argvars, typval_T * EMSG2(_(e_invarg2), s); /* Don't check an autoload name for existence here. */ else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL - && !function_exists(s)) + && !function_exists(s, TRUE)) EMSG2(_("E700: Unknown function: %s"), s); else { diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -9,7 +9,7 @@ int call_func(char_u *funcname, int len, void ex_function(exarg_T *eap); int eval_fname_script(char_u *p); int translated_function_exists(char_u *name); -int function_exists(char_u *name); +int function_exists(char_u *name, int no_deref); char_u *get_expanded_name(char_u *name, int check); void func_dump_profile(FILE *fd); void prof_child_enter(proftime_T *tm); diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -172,3 +172,10 @@ func Test_substitute_expr_arg() call assert_fails("call substitute('xxx', '.', {m -> string(extend(m, ['x']))}, '')", 'E742:') call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:') endfunc + +func Test_function_with_funcref() + let s:f = function('type') + let s:fref = function(s:f) + call assert_equal(v:t_string, s:fref('x')) + call assert_fails("call function('s:f')", 'E700:') +endfunc diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -295,7 +295,7 @@ get_lambda_tv(char_u **arg, typval_T *re if (ret == FAIL || **arg != '>') goto errret; - /* Set up dictionaries for checking local variables and arguments. */ + /* Set up a flag for checking local variables and arguments. */ if (evaluate) eval_lavars_used = &eval_lavars; @@ -1504,6 +1504,7 @@ list_func_head(ufunc_T *fp, int indent) * TFN_INT: internal function name OK * TFN_QUIET: be quiet * TFN_NO_AUTOLOAD: do not use script autoloading + * TFN_NO_DEREF: do not dereference a Funcref * Advances "pp" to just after the function name (if no error). */ static char_u * @@ -1618,7 +1619,7 @@ trans_function_name( if (name == lv.ll_exp_name) name = NULL; } - else + else if (!(flags & TFN_NO_DEREF)) { len = (int)(end - *pp); name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD); @@ -1690,7 +1691,7 @@ trans_function_name( start); goto theend; } - if (!skip && !(flags & TFN_QUIET)) + if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF)) { char_u *cp = vim_strchr(lv.ll_name, ':'); @@ -2381,16 +2382,20 @@ translated_function_exists(char_u *name) /* * Return TRUE if a function "name" exists. + * If "no_defef" is TRUE, do not dereference a Funcref. */ int -function_exists(char_u *name) +function_exists(char_u *name, int no_deref) { char_u *nm = name; char_u *p; int n = FALSE; - - p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD, - NULL, NULL); + int flag; + + flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD; + if (no_deref) + flag |= TFN_NO_DEREF; + p = trans_function_name(&nm, FALSE, flag, NULL, NULL); nm = skipwhite(nm); /* Only accept "funcname", "funcname ", "funcname (..." and diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2134, +/**/ 2133, /**/ 2132, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -2458,6 +2458,7 @@ int vim_main2(int argc, char **argv); #define TFN_INT 1 /* internal function name OK */ #define TFN_QUIET 2 /* no error messages */ #define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */ +#define TFN_NO_DEREF 8 /* do not dereference a Funcref */ /* Values for get_lval() flags argument: */ #define GLV_QUIET TFN_QUIET /* no error messages */