]> granicus.if.org Git - vim/commitdiff
patch 7.4.2134 v7.4.2134
authorBram Moolenaar <Bram@vim.org>
Sun, 31 Jul 2016 12:11:58 +0000 (14:11 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 31 Jul 2016 12:11:58 +0000 (14:11 +0200)
Problem:    No error for using function() badly.
Solution:   Check for passing wrong function name. (Ken Takata)

src/eval.c
src/evalfunc.c
src/proto/userfunc.pro
src/testdir/test_expr.vim
src/userfunc.c
src/version.c
src/vim.h

index 956f05cb1fb4ad319a1f3b65761ad805bf5cb1bb..cf2c771438957a225669b7e70a45982ecab9228b 100644 (file)
@@ -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);
index 9905d0ba7406d66e996b760016919c8777df7f51..13864ea3a73334619fbc6a0cc2f9a66492e18d43 100644 (file)
@@ -2845,7 +2845,7 @@ f_exists(typval_T *argvars, typval_T *rettv)
     }
     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 *rettv)
        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
     {
index 42c5883d01db22ff534cba46f7f073804130721c..bd3960447833bb89b5ba3efdac1618a364d5d3ca 100644 (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);
 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);
index 8db4d8e5f35fb9cd1ab56b596f6dc439e50244b9..d8abc275237c2df0cde6460051247408a635fe56 100644 (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(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
index 0c6c613e3e4b8e9c8606c7a755fb6fde98b82d17..3c6401f7d7b26b4ccd7000ff69fc7061cf6d2f4b 100644 (file)
@@ -295,7 +295,7 @@ get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
     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;
+    int            flag;
 
-    p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD,
-                           NULL, NULL);
+    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
index 5808cbc32f447dd82aceed930dbe51fbfbd49793..8ef6dec48ae30a74688cb4454e7090279c40335c 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2134,
 /**/
     2133,
 /**/
index 756098271191290343e8b59e2453fc4503def58e..34a8650c4900c698ad51d7f1897c8150d3b327a7 100644 (file)
--- 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 */