0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 7.4.2134

Problem:    No error for using function() badly.
Solution:   Check for passing wrong function name. (Ken Takata)
This commit is contained in:
Bram Moolenaar 2016-07-31 14:11:58 +02:00
parent fc1f2015e8
commit b54c3ff317
7 changed files with 25 additions and 10 deletions

View File

@ -7813,7 +7813,7 @@ var_check_func_name(
/* Don't allow hiding a function. When "v" is not NULL we might be /* 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 * assigning another function to the same var, the type is checked
* below. */ * below. */
if (new_var && function_exists(name)) if (new_var && function_exists(name, FALSE))
{ {
EMSG2(_("E705: Variable name conflicts with existing function: %s"), EMSG2(_("E705: Variable name conflicts with existing function: %s"),
name); name);

View File

@ -2845,7 +2845,7 @@ f_exists(typval_T *argvars, typval_T *rettv)
} }
else if (*p == '*') /* internal or user defined function */ else if (*p == '*') /* internal or user defined function */
{ {
n = function_exists(p + 1); n = function_exists(p + 1, FALSE);
} }
else if (*p == ':') else if (*p == ':')
{ {
@ -3577,7 +3577,7 @@ f_function(typval_T *argvars, typval_T *rettv)
EMSG2(_(e_invarg2), s); EMSG2(_(e_invarg2), s);
/* Don't check an autoload name for existence here. */ /* Don't check an autoload name for existence here. */
else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL
&& !function_exists(s)) && !function_exists(s, TRUE))
EMSG2(_("E700: Unknown function: %s"), s); EMSG2(_("E700: Unknown function: %s"), s);
else else
{ {

View File

@ -9,7 +9,7 @@ int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typva
void ex_function(exarg_T *eap); void ex_function(exarg_T *eap);
int eval_fname_script(char_u *p); int eval_fname_script(char_u *p);
int translated_function_exists(char_u *name); 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); char_u *get_expanded_name(char_u *name, int check);
void func_dump_profile(FILE *fd); void func_dump_profile(FILE *fd);
void prof_child_enter(proftime_T *tm); void prof_child_enter(proftime_T *tm);

View File

@ -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(extend(m, ['x']))}, '')", 'E742:')
call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:') call assert_fails("call substitute('xxx', '.', {m -> string(remove(m, 1))}, '')", 'E742:')
endfunc 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

View File

@ -295,7 +295,7 @@ get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
if (ret == FAIL || **arg != '>') if (ret == FAIL || **arg != '>')
goto errret; goto errret;
/* Set up dictionaries for checking local variables and arguments. */ /* Set up a flag for checking local variables and arguments. */
if (evaluate) if (evaluate)
eval_lavars_used = &eval_lavars; eval_lavars_used = &eval_lavars;
@ -1504,6 +1504,7 @@ list_func_head(ufunc_T *fp, int indent)
* TFN_INT: internal function name OK * TFN_INT: internal function name OK
* TFN_QUIET: be quiet * TFN_QUIET: be quiet
* TFN_NO_AUTOLOAD: do not use script autoloading * 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). * Advances "pp" to just after the function name (if no error).
*/ */
static char_u * static char_u *
@ -1618,7 +1619,7 @@ trans_function_name(
if (name == lv.ll_exp_name) if (name == lv.ll_exp_name)
name = NULL; name = NULL;
} }
else else if (!(flags & TFN_NO_DEREF))
{ {
len = (int)(end - *pp); len = (int)(end - *pp);
name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD); name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
@ -1690,7 +1691,7 @@ trans_function_name(
start); start);
goto theend; goto theend;
} }
if (!skip && !(flags & TFN_QUIET)) if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF))
{ {
char_u *cp = vim_strchr(lv.ll_name, ':'); 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. * Return TRUE if a function "name" exists.
* If "no_defef" is TRUE, do not dereference a Funcref.
*/ */
int int
function_exists(char_u *name) function_exists(char_u *name, int no_deref)
{ {
char_u *nm = name; char_u *nm = name;
char_u *p; char_u *p;
int n = FALSE; int n = FALSE;
int flag;
p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD, flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
NULL, NULL); if (no_deref)
flag |= TFN_NO_DEREF;
p = trans_function_name(&nm, FALSE, flag, NULL, NULL);
nm = skipwhite(nm); nm = skipwhite(nm);
/* Only accept "funcname", "funcname ", "funcname (..." and /* Only accept "funcname", "funcname ", "funcname (..." and

View File

@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2134,
/**/ /**/
2133, 2133,
/**/ /**/

View File

@ -2458,6 +2458,7 @@ int vim_main2(int argc, char **argv);
#define TFN_INT 1 /* internal function name OK */ #define TFN_INT 1 /* internal function name OK */
#define TFN_QUIET 2 /* no error messages */ #define TFN_QUIET 2 /* no error messages */
#define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */ #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: */ /* Values for get_lval() flags argument: */
#define GLV_QUIET TFN_QUIET /* no error messages */ #define GLV_QUIET TFN_QUIET /* no error messages */