Patch 9.0.0419

8 views
Skip to first unread message

Bram Moolenaar

unread,
Sep 8, 2022, 2:53:58 PM9/8/22
to vim...@googlegroups.com

Patch 9.0.0419
Problem: The :defer command does not check the function argument count and
types.
Solution: Check the function arguments when adding a deferred function.
Files: src/userfunc.c, src/vim9instr.c, src/proto/vim9instr.pro,
src/vim9cmds.c, src/testdir/test_user_func.vim


*** ../vim-9.0.0418/src/userfunc.c 2022-09-07 21:30:40.139379052 +0100
--- src/userfunc.c 2022-09-08 18:11:09.503285696 +0100
***************
*** 5608,5613 ****
--- 5608,5614 ----
ex_defer_inner(
char_u *name,
char_u **arg,
+ type_T *type,
partial_T *partial,
evalarg_T *evalarg)
{
***************
*** 5640,5645 ****
--- 5641,5684 ----
r = get_func_arguments(arg, evalarg, FALSE,
argvars + partial_argc, &argcount);
argcount += partial_argc;
+
+ if (r == OK)
+ {
+ if (type != NULL)
+ {
+ // Check that the arguments are OK for the types of the funcref.
+ r = check_argument_types(type, argvars, argcount, NULL, name);
+ }
+ else if (builtin_function(name, -1))
+ {
+ int idx = find_internal_func(name);
+
+ if (idx < 0)
+ {
+ emsg_funcname(e_unknown_function_str, name);
+ r = FAIL;
+ }
+ else if (check_internal_func(idx, argcount) == -1)
+ r = FAIL;
+ }
+ else
+ {
+ ufunc_T *ufunc = find_func(name, FALSE);
+
+ // we tolerate an unknown function here, it might be defined later
+ if (ufunc != NULL)
+ {
+ int error = check_user_func_argcount(ufunc, argcount);
+
+ if (error != FCERR_UNKNOWN)
+ {
+ user_func_error(error, name, NULL);
+ r = FAIL;
+ }
+ }
+ }
+ }
+
if (r == FAIL)
{
while (--argcount >= 0)
***************
*** 5839,5845 ****
if (eap->cmdidx == CMD_defer)
{
arg = startarg;
! failed = ex_defer_inner(name, &arg, partial, &evalarg) == FAIL;
}
else
{
--- 5878,5884 ----
if (eap->cmdidx == CMD_defer)
{
arg = startarg;
! failed = ex_defer_inner(name, &arg, type, partial, &evalarg) == FAIL;
}
else
{
*** ../vim-9.0.0418/src/vim9instr.c 2022-09-04 12:47:15.414692249 +0100
--- src/vim9instr.c 2022-09-08 19:39:51.440072875 +0100
***************
*** 1329,1361 ****
return OK;
}

-
/*
! * Generate an ISN_BCALL instruction.
! * "method_call" is TRUE for "value->method()"
! * Return FAIL if the number of arguments is wrong.
*/
int
! generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
{
- isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
! int argoff;
! type2_T *typep;
! type2_T *argtypes = NULL;
! type2_T shuffled_argtypes[MAX_FUNC_ARGS];
! type2_T *maptype = NULL;
! type_T *type;
! type_T *decl_type;

- RETURN_OK_IF_SKIP(cctx);
- argoff = check_internal_func(func_idx, argcount);
if (argoff < 0)
return FAIL;

if (method_call && argoff > 1)
{
! if ((isn = generate_instr(cctx, ISN_SHUFFLE)) == NULL)
return FAIL;
isn->isn_arg.shuffle.shfl_item = argcount;
isn->isn_arg.shuffle.shfl_up = argoff - 1;
--- 1329,1359 ----
return OK;
}

/*
! * Check "argount" arguments and their types on the type stack.
! * Give an error and return FAIL if something is wrong.
! * When "method_call" is NULL no code is generated.
*/
int
! check_internal_func_args(
! cctx_T *cctx,
! int func_idx,
! int argcount,
! int method_call,
! type2_T **argtypes,
! type2_T *shuffled_argtypes)
{
garray_T *stack = &cctx->ctx_type_stack;
! int argoff = check_internal_func(func_idx, argcount);

if (argoff < 0)
return FAIL;

if (method_call && argoff > 1)
{
! isn_T *isn = generate_instr(cctx, ISN_SHUFFLE);
!
! if (isn == NULL)
return FAIL;
isn->isn_arg.shuffle.shfl_item = argcount;
isn->isn_arg.shuffle.shfl_up = argoff - 1;
***************
*** 1363,1379 ****

if (argcount > 0)
{
// Check the types of the arguments.
- typep = ((type2_T *)stack->ga_data) + stack->ga_len - argcount;
if (method_call && argoff > 1)
{
int i;

for (i = 0; i < argcount; ++i)
shuffled_argtypes[i] = (i < argoff - 1)
! ? typep[i + 1]
! : (i == argoff - 1) ? typep[0] : typep[i];
! argtypes = shuffled_argtypes;
}
else
{
--- 1361,1378 ----

if (argcount > 0)
{
+ type2_T *typep = ((type2_T *)stack->ga_data) + stack->ga_len - argcount;
+
// Check the types of the arguments.
if (method_call && argoff > 1)
{
int i;

for (i = 0; i < argcount; ++i)
shuffled_argtypes[i] = (i < argoff - 1)
! ? typep[i + 1]
! : (i == argoff - 1) ? typep[0] : typep[i];
! *argtypes = shuffled_argtypes;
}
else
{
***************
*** 1381,1394 ****

for (i = 0; i < argcount; ++i)
shuffled_argtypes[i] = typep[i];
! argtypes = shuffled_argtypes;
}
! if (internal_func_check_arg_types(argtypes, func_idx, argcount,
cctx) == FAIL)
return FAIL;
- if (internal_func_is_map(func_idx))
- maptype = argtypes;
}

if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
return FAIL;
--- 1380,1418 ----

for (i = 0; i < argcount; ++i)
shuffled_argtypes[i] = typep[i];
! *argtypes = shuffled_argtypes;
}
! if (internal_func_check_arg_types(*argtypes, func_idx, argcount,
cctx) == FAIL)
return FAIL;
}
+ return OK;
+ }
+
+ /*
+ * Generate an ISN_BCALL instruction.
+ * "method_call" is TRUE for "value->method()"
+ * Return FAIL if the number of arguments is wrong.
+ */
+ int
+ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
+ {
+ isn_T *isn;
+ garray_T *stack = &cctx->ctx_type_stack;
+ type2_T *argtypes = NULL;
+ type2_T shuffled_argtypes[MAX_FUNC_ARGS];
+ type2_T *maptype = NULL;
+ type_T *type;
+ type_T *decl_type;
+
+ RETURN_OK_IF_SKIP(cctx);
+
+ if (check_internal_func_args(cctx, func_idx, argcount, method_call,
+ &argtypes, shuffled_argtypes) == FAIL)
+ return FAIL;
+
+ if (internal_func_is_map(func_idx))
+ maptype = argtypes;

if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
return FAIL;
***************
*** 1578,1583 ****
--- 1602,1662 ----
}

/*
+ * Check the arguments of function "type" against the types on the stack.
+ * Returns OK or FAIL;
+ */
+ int
+ check_func_args_from_type(
+ cctx_T *cctx,
+ type_T *type,
+ int argcount,
+ int at_top,
+ char_u *name)
+ {
+ if (type->tt_argcount != -1)
+ {
+ int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
+
+ if (argcount < type->tt_min_argcount - varargs)
+ {
+ emsg_funcname(e_not_enough_arguments_for_function_str, name);
+ return FAIL;
+ }
+ if (!varargs && argcount > type->tt_argcount)
+ {
+ emsg_funcname(e_too_many_arguments_for_function_str, name);
+ return FAIL;
+ }
+ if (type->tt_args != NULL)
+ {
+ int i;
+
+ for (i = 0; i < argcount; ++i)
+ {
+ int offset = -argcount + i - (at_top ? 0 : 1);
+ type_T *actual = get_type_on_stack(cctx, -1 - offset);
+ type_T *expected;
+
+ if (varargs && i >= type->tt_argcount - 1)
+ expected = type->tt_args[type->tt_argcount - 1]->tt_member;
+ else if (i >= type->tt_min_argcount
+ && actual->tt_type == VAR_SPECIAL)
+ expected = &t_any;
+ else
+ expected = type->tt_args[i];
+ if (need_type(actual, expected, offset, i + 1,
+ cctx, TRUE, FALSE) == FAIL)
+ {
+ arg_type_mismatch(expected, actual, i + 1);
+ return FAIL;
+ }
+ }
+ }
+ }
+
+ return OK;
+ }
+ /*
* Generate an ISN_PCALL instruction.
* "type" is the type of the FuncRef.
*/
***************
*** 1598,1644 ****
ret_type = &t_any;
else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
{
! if (type->tt_argcount != -1)
! {
! int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
!
! if (argcount < type->tt_min_argcount - varargs)
! {
! emsg_funcname(e_not_enough_arguments_for_function_str, name);
! return FAIL;
! }
! if (!varargs && argcount > type->tt_argcount)
! {
! emsg_funcname(e_too_many_arguments_for_function_str, name);
! return FAIL;
! }
! if (type->tt_args != NULL)
! {
! int i;

- for (i = 0; i < argcount; ++i)
- {
- int offset = -argcount + i - (at_top ? 0 : 1);
- type_T *actual = get_type_on_stack(cctx, -1 - offset);
- type_T *expected;
-
- if (varargs && i >= type->tt_argcount - 1)
- expected = type->tt_args[
- type->tt_argcount - 1]->tt_member;
- else if (i >= type->tt_min_argcount
- && actual->tt_type == VAR_SPECIAL)
- expected = &t_any;
- else
- expected = type->tt_args[i];
- if (need_type(actual, expected, offset, i + 1,
- cctx, TRUE, FALSE) == FAIL)
- {
- arg_type_mismatch(expected, actual, i + 1);
- return FAIL;
- }
- }
- }
- }
ret_type = type->tt_member;
if (ret_type == &t_unknown)
// return type not known yet, use a runtime check
--- 1677,1685 ----
ret_type = &t_any;
else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
{
! if (check_func_args_from_type(cctx, type, argcount, at_top, name) == FAIL)
! return FAIL;

ret_type = type->tt_member;
if (ret_type == &t_unknown)
// return type not known yet, use a runtime check
*** ../vim-9.0.0418/src/proto/vim9instr.pro 2022-09-03 21:35:50.184158219 +0100
--- src/proto/vim9instr.pro 2022-09-08 19:32:25.669422042 +0100
***************
*** 46,56 ****
--- 46,59 ----
int generate_JUMP_IF_ARG_SET(cctx_T *cctx, int arg_off);
int generate_FOR(cctx_T *cctx, int loop_idx);
int generate_TRYCONT(cctx_T *cctx, int levels, int where);
+ int check_internal_func_args(cctx_T *cctx, int func_idx, int argcount, int method_call, type2_T **argtypes, type2_T *shuffled_argtypes);
int generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call);
int generate_LISTAPPEND(cctx_T *cctx);
int generate_BLOBAPPEND(cctx_T *cctx);
+ int check_args_on_stack(cctx_T *cctx, ufunc_T *ufunc, int argcount);
int generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount);
int generate_UCALL(cctx_T *cctx, char_u *name, int argcount);
+ int check_func_args_from_type(cctx_T *cctx, type_T *type, int argcount, int at_top, char_u *name);
int generate_PCALL(cctx_T *cctx, int argcount, char_u *name, type_T *type, int at_top);
int generate_DEFER(cctx_T *cctx, int var_idx, int argcount);
int generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len);
*** ../vim-9.0.0418/src/vim9cmds.c 2022-09-04 18:08:00.327693560 +0100
--- src/vim9cmds.c 2022-09-08 19:35:10.052887004 +0100
***************
*** 1706,1738 ****
}

/*
- * Get the local variable index for deferred function calls.
- * Reserve it when not done already.
- * Returns zero for failure.
- */
- int
- get_defer_var_idx(cctx_T *cctx)
- {
- dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
- + cctx->ctx_ufunc->uf_dfunc_idx;
- if (dfunc->df_defer_var_idx == 0)
- {
- lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
- TRUE, &t_list_any);
- if (lvar == NULL)
- return 0;
- dfunc->df_defer_var_idx = lvar->lv_idx + 1;
- }
- return dfunc->df_defer_var_idx;
- }
-
- /*
* Compile "defer func(arg)".
*/
char_u *
compile_defer(char_u *arg_start, cctx_T *cctx)
{
! char_u *p;
char_u *arg = arg_start;
int argcount = 0;
int defer_var_idx;
--- 1706,1717 ----
}

/*
* Compile "defer func(arg)".
*/
char_u *
compile_defer(char_u *arg_start, cctx_T *cctx)
{
! char_u *paren;
char_u *arg = arg_start;
int argcount = 0;
int defer_var_idx;
***************
*** 1741,1753 ****

// Get a funcref for the function name.
// TODO: better way to find the "(".
! p = vim_strchr(arg, '(');
! if (p == NULL)
{
semsg(_(e_missing_parenthesis_str), arg);
return NULL;
}
! *p = NUL;
func_idx = find_internal_func(arg);
if (func_idx >= 0)
// TODO: better type
--- 1720,1732 ----

// Get a funcref for the function name.
// TODO: better way to find the "(".
! paren = vim_strchr(arg, '(');
! if (paren == NULL)
{
semsg(_(e_missing_parenthesis_str), arg);
return NULL;
}
! *paren = NUL;
func_idx = find_internal_func(arg);
if (func_idx >= 0)
// TODO: better type
***************
*** 1755,1761 ****
&t_func_any, FALSE);
else if (compile_expr0(&arg, cctx) == FAIL)
return NULL;
! *p = '(';

// check for function type
type = get_type_on_stack(cctx, 0);
--- 1734,1740 ----
&t_func_any, FALSE);
else if (compile_expr0(&arg, cctx) == FAIL)
return NULL;
! *paren = '(';

// check for function type
type = get_type_on_stack(cctx, 0);
***************
*** 1766,1776 ****
}

// compile the arguments
! arg = skipwhite(p + 1);
if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
return NULL;

! // TODO: check argument count with "type"

defer_var_idx = get_defer_var_idx(cctx);
if (defer_var_idx == 0)
--- 1745,1766 ----
}

// compile the arguments
! arg = skipwhite(paren + 1);
if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
return NULL;

! if (func_idx >= 0)
! {
! type2_T *argtypes = NULL;
! type2_T shuffled_argtypes[MAX_FUNC_ARGS];
!
! if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
! &argtypes, shuffled_argtypes) == FAIL)
! return NULL;
! }
! else if (check_func_args_from_type(cctx, type, argcount, TRUE,
! arg_start) == FAIL)
! return NULL;

defer_var_idx = get_defer_var_idx(cctx);
if (defer_var_idx == 0)
*** ../vim-9.0.0418/src/testdir/test_user_func.vim 2022-09-07 17:28:05.849865176 +0100
--- src/testdir/test_user_func.vim 2022-09-08 19:43:53.927437408 +0100
***************
*** 5,10 ****
--- 5,11 ----

source check.vim
source shared.vim
+ import './vim9.vim' as v9

func Table(title, ...)
let ret = a:title
***************
*** 619,625 ****
DeferLevelOne()
END
call writefile(lines, 'XdeferQuitall', 'D')
! let res = system(GetVimCommandClean() .. ' -X -S XdeferQuitall')
call assert_equal(0, v:shell_error)
call assert_false(filereadable('XQuitallOne'))
call assert_false(filereadable('XQuitallTwo'))
--- 620,626 ----
DeferLevelOne()
END
call writefile(lines, 'XdeferQuitall', 'D')
! let res = system(GetVimCommand() .. ' -X -S XdeferQuitall')
call assert_equal(0, v:shell_error)
call assert_false(filereadable('XQuitallOne'))
call assert_false(filereadable('XQuitallTwo'))
***************
*** 641,647 ****
call Test_defer_in_funcref()
END
call writefile(lines, 'XdeferQuitallExpr', 'D')
! let res = system(GetVimCommandClean() .. ' -X -S XdeferQuitallExpr')
call assert_equal(0, v:shell_error)
call assert_false(filereadable('Xentry0'))
call assert_false(filereadable('Xentry1'))
--- 642,648 ----
call Test_defer_in_funcref()
END
call writefile(lines, 'XdeferQuitallExpr', 'D')
! let res = system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
call assert_equal(0, v:shell_error)
call assert_false(filereadable('Xentry0'))
call assert_false(filereadable('Xentry1'))
***************
*** 695,699 ****
--- 696,755 ----
assert_false(filereadable('Xentry2'))
enddef

+ func Test_defer_wrong_arguments()
+ call assert_fails('defer delete()', 'E119:')
+ call assert_fails('defer FuncIndex(1)', 'E119:')
+ call assert_fails('defer delete(1, 2, 3)', 'E118:')
+ call assert_fails('defer FuncIndex(1, 2, 3)', 'E118:')
+
+ let lines =<< trim END
+ def DeferFunc0()
+ defer delete()
+ enddef
+ defcompile
+ END
+ call v9.CheckScriptFailure(lines, 'E119:')
+ let lines =<< trim END
+ def DeferFunc3()
+ defer delete(1, 2, 3)
+ enddef
+ defcompile
+ END
+ call v9.CheckScriptFailure(lines, 'E118:')
+ let lines =<< trim END
+ def DeferFunc2()
+ defer delete(1, 2)
+ enddef
+ defcompile
+ END
+ call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
+
+ def g:FuncOneArg(arg: string)
+ echo arg
+ enddef
+
+ let lines =<< trim END
+ def DeferUserFunc0()
+ defer g:FuncOneArg()
+ enddef
+ defcompile
+ END
+ call v9.CheckScriptFailure(lines, 'E119:')
+ let lines =<< trim END
+ def DeferUserFunc2()
+ defer g:FuncOneArg(1, 2)
+ enddef
+ defcompile
+ END
+ call v9.CheckScriptFailure(lines, 'E118:')
+ let lines =<< trim END
+ def DeferUserFunc1()
+ defer g:FuncOneArg(1)
+ enddef
+ defcompile
+ END
+ call v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
+ endfunc
+

" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-9.0.0418/src/version.c 2022-09-08 16:39:16.912140162 +0100
--- src/version.c 2022-09-08 19:49:53.546558746 +0100
***************
*** 705,706 ****
--- 705,708 ----
{ /* Add new patch number below this line */
+ /**/
+ 419,
/**/

--
I am also told that there is a logical proof out there somewhere
that demonstrates that there is no task which duct tape cannot handle.
-- Paul Brannan

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

John Marriott

unread,
Sep 8, 2022, 3:13:55 PM9/8/22
to vim...@googlegroups.com
On 09-Sept-2022 04:53, Bram Moolenaar wrote:
> Patch 9.0.0419
> Problem: The :defer command does not check the function argument count and
> types.
> Solution: Check the function arguments when adding a deferred function.
> Files: src/userfunc.c, src/vim9instr.c, src/proto/vim9instr.pro,
> src/vim9cmds.c, src/testdir/test_user_func.vim
>
After this patch mingw64 (gcc 12.2.0) spits out this linker error:
<snip>
gcc -I. -Iproto -DWIN32 -DWINVER=0x0603 -D_WIN32_WINNT=0x0603
-DHAVE_PATHDEF -DFEAT_NORMAL -DHAVE_STDINT_H -D__USE_MINGW_ANSI_STDIO
-pipe -march=native -Wall -O3 -fomit-frame-pointer -freg-struct-return
-fpie -fPIE -DFEAT_GUI_MSWIN -DFEAT_CLIPBOARD -Wl,-nxcompat,-dynamicbase
-municode -s -mwindows -o gvim.exe gobjnative/alloc.o
gobjnative/arabic.o gobjnative/arglist.o gobjnative/autocmd.o
gobjnative/beval.o gobjnative/blob.o gobjnative/blowfish.o
gobjnative/buffer.o gobjnative/bufwrite.o gobjnative/change.o
gobjnative/charset.o gobjnative/cindent.o gobjnative/clientserver.o
gobjnative/clipboard.o gobjnative/cmdexpand.o gobjnative/cmdhist.o
gobjnative/crypt.o gobjnative/crypt_zip.o gobjnative/debugger.o
gobjnative/dict.o gobjnative/diff.o gobjnative/digraph.o
gobjnative/drawline.o gobjnative/drawscreen.o gobjnative/edit.o
gobjnative/eval.o gobjnative/evalbuffer.o gobjnative/evalfunc.o
gobjnative/evalvars.o gobjnative/evalwindow.o gobjnative/ex_cmds.o
gobjnative/ex_cmds2.o gobjnative/ex_docmd.o gobjnative/ex_eval.o
gobjnative/ex_getln.o gobjnative/fileio.o gobjnative/filepath.o
gobjnative/findfile.o gobjnative/float.o gobjnative/fold.o
gobjnative/getchar.o gobjnative/gui_xim.o gobjnative/hardcopy.o
gobjnative/hashtab.o gobjnative/help.o gobjnative/highlight.o
gobjnative/if_cscope.o gobjnative/indent.o gobjnative/insexpand.o
gobjnative/json.o gobjnative/list.o gobjnative/locale.o
gobjnative/main.o gobjnative/map.o gobjnative/mark.o gobjnative/match.o
gobjnative/memfile.o gobjnative/memline.o gobjnative/menu.o
gobjnative/message.o gobjnative/misc1.o gobjnative/misc2.o
gobjnative/mouse.o gobjnative/move.o gobjnative/mbyte.o
gobjnative/normal.o gobjnative/ops.o gobjnative/option.o
gobjnative/optionstr.o gobjnative/os_mswin.o gobjnative/os_win32.o
gobjnative/pathdef.o gobjnative/popupmenu.o gobjnative/popupwin.o
gobjnative/profiler.o gobjnative/quickfix.o gobjnative/regexp.o
gobjnative/register.o gobjnative/scriptfile.o gobjnative/screen.o
gobjnative/search.o gobjnative/session.o gobjnative/sha256.o
gobjnative/sign.o gobjnative/spell.o gobjnative/spellfile.o
gobjnative/spellsuggest.o gobjnative/strings.o gobjnative/syntax.o
gobjnative/tag.o gobjnative/term.o gobjnative/testing.o
gobjnative/textformat.o gobjnative/textobject.o gobjnative/textprop.o
gobjnative/time.o gobjnative/typval.o gobjnative/ui.o gobjnative/undo.o
gobjnative/usercmd.o gobjnative/userfunc.o gobjnative/version.o
gobjnative/vim9cmds.o gobjnative/vim9compile.o gobjnative/vim9execute.o
gobjnative/vim9expr.o gobjnative/vim9instr.o gobjnative/vim9script.o
gobjnative/vim9type.o gobjnative/viminfo.o gobjnative/winclip.o
gobjnative/window.o gobjnative/os_w32exe.o gobjnative/vimres.o
gobjnative/xdiffi.o gobjnative/xemit.o gobjnative/xprepare.o
gobjnative/xutils.o gobjnative/xhistogram.o gobjnative/xpatience.o
gobjnative/gui.o gobjnative/gui_w32.o gobjnative/gui_beval.o -lkernel32
-luser32 -lgdi32 -ladvapi32 -lcomdlg32 -lcomctl32 -lnetapi32 -lversion
-lole32 -luuid
d:/users/john/documents/software/mingw/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
gobjnative/vim9cmds.o:vim9cmds.c:(.text+0x2628): undefined reference to
`get_defer_var_idx'
d:/users/john/documents/software/mingw/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
gobjnative/vim9expr.o:vim9expr.c:(.text+0x5a9d): undefined reference to
`get_defer_var_idx'
collect2.exe: error: ld returned 1 exit status
make: *** [Make_cyg_ming.mak:1137: gvim.exe] Error 1
</snip>

This patch removed the function but not all of the calls.

Also, it looks like the contents of patch 9.0.0418 are the same as 9.0.0419.

Cheers
John

Bram Moolenaar

unread,
Sep 8, 2022, 3:57:55 PM9/8/22
to vim...@googlegroups.com, John Marriott

> On 09-Sept-2022 04:53, Bram Moolenaar wrote:
> > Patch 9.0.0419
> > Problem: The :defer command does not check the function argument count and
> > types.
> > Solution: Check the function arguments when adding a deferred function.
> > Files: src/userfunc.c, src/vim9instr.c, src/proto/vim9instr.pro,
> > src/vim9cmds.c, src/testdir/test_user_func.vim
> >
> After this patch mingw64 (gcc 12.2.0) spits out this linker error:
> <snip>
> gcc -I. -Iproto -DWIN32 -DWINVER=0x0603 -D_WIN32_WINNT=0x0603
> -DHAVE_PATHDEF -DFEAT_NORMAL -DHAVE_STDINT_H -D__USE_MINGW_ANSI_STDIO
> -pipe -march=native -Wall -O3 -fomit-frame-pointer -freg-struct-return
> -fpie -fPIE -DFEAT_GUI_MSWIN -DFEAT_CLIPBOARD -Wl,-nxcompat,-dynamicbase
> -municode -s -mwindows -o gvim.exe gobjnative/alloc.o
> gobjnative/arabic.o gobjnative/arglist.o gobjnative/autocmd.o

[...]

> d:/users/john/documents/software/mingw/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
> gobjnative/vim9cmds.o:vim9cmds.c:(.text+0x2628): undefined reference to
> `get_defer_var_idx'
> d:/users/john/documents/software/mingw/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
> gobjnative/vim9expr.o:vim9expr.c:(.text+0x5a9d): undefined reference to
> `get_defer_var_idx'
> collect2.exe: error: ld returned 1 exit status
> make: *** [Make_cyg_ming.mak:1137: gvim.exe] Error 1
> </snip>
>
> This patch removed the function but not all of the calls.

Weird, that function should not have been removed. And it wasn't in my
main directory and a shadow directory (all tests passed locally). But
it delete in the diff and in the git repo. Can't explain it.

> Also, it looks like the contents of patch 9.0.0418 are the same as 9.0.0419.

Wrong diff in the email... I'll reply.

--
"Space is big. Really big. You just won't believe how vastly hugely mind-
bogglingly big it is. I mean, you may think it's a long way down the
road to the chemist, but that's just peanuts to space."
-- Douglas Adams, "The Hitchhiker's Guide to the Galaxy"
Reply all
Reply to author
Forward
0 new messages