# HG changeset patch # User Bram Moolenaar # Date 1629053104 -7200 # Node ID 27cb2e79ccdeac5d4602c3bc95df925d5cb7cde9 # Parent 4b6c030bda5ca49acbe58f9aad4cc3c237c59f68 patch 8.2.3353: Vim9: type of argument for negate not checked at compile time Commit: https://github.com/vim/vim/commit/cd6b4f300189b4920f7ee7f0204338e91210674b Author: Bram Moolenaar Date: Sun Aug 15 20:36:28 2021 +0200 patch 8.2.3353: Vim9: type of argument for negate not checked at compile time Problem: Vim9: type of argument for negate not checked at compile time. Solution: Add a compile time check. diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1680,25 +1680,27 @@ def Test_disassemble_any_slice() enddef def NegateNumber(): number - var nr = 9 - var plus = +nr - var res = -nr - return res + g:nr = 9 + var plus = +g:nr + var minus = -g:nr + return minus enddef def Test_disassemble_negate_number() var instr = execute('disassemble NegateNumber') assert_match('NegateNumber\_s*' .. - 'var nr = 9\_s*' .. - '\d STORE 9 in $0\_s*' .. - 'var plus = +nr\_s*' .. - '\d LOAD $0\_s*' .. - '\d CHECKNR\_s*' .. - '\d STORE $1\_s*' .. - 'var res = -nr\_s*' .. - '\d LOAD $0\_s*' .. + 'g:nr = 9\_s*' .. + '\d PUSHNR 9\_s*' .. + '\d STOREG g:nr\_s*' .. + 'var plus = +g:nr\_s*' .. + '\d LOADG g:nr\_s*' .. + '\d CHECKTYPE number stack\[-1\]\_s*' .. + '\d STORE $0\_s*' .. + 'var minus = -g:nr\_s*' .. + '\d LOADG g:nr\_s*' .. + '\d CHECKTYPE number stack\[-1\]\_s*' .. '\d NEGATENR\_s*' .. - '\d STORE $2\_s*', + '\d STORE $1\_s*', instr) assert_equal(-9, NegateNumber()) enddef diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -3123,6 +3123,17 @@ def Test_expr7_not() CheckDefAndScriptSuccess(lines) enddef +let g:anumber = 42 + +def Test_expr7_negate() + var lines =<< trim END + var nr = 1 + assert_equal(-1, -nr) + assert_equal(-42, -g:anumber) + END + CheckDefAndScriptSuccess(lines) +enddef + func Test_expr7_fails() call CheckDefFailure(["var x = (12"], "E1097:", 3) call CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2) @@ -3130,8 +3141,8 @@ func Test_expr7_fails() call CheckDefAndScriptFailure(["var x = -'xx'"], "E1030:", 1) call CheckDefAndScriptFailure(["var x = +'xx'"], "E1030:", 1) call CheckDefAndScriptFailure(["var x = -0z12"], "E974:", 1) - call CheckDefExecAndScriptFailure2(["var x = -[8]"], "E39:", 'E745:', 1) - call CheckDefExecAndScriptFailure2(["var x = -{a: 1}"], "E39:", 'E728:', 1) + call CheckDefExecAndScriptFailure2(["var x = -[8]"], "E1012:", 'E745:', 1) + call CheckDefExecAndScriptFailure2(["var x = -{a: 1}"], "E1012:", 'E728:', 1) call CheckDefAndScriptFailure(["var x = @"], "E1002:", 1) call CheckDefAndScriptFailure(["var x = @<"], "E354:", 1) @@ -3154,10 +3165,10 @@ func Test_expr7_fails() call CheckDefAndScriptFailure2(["echo l:somevar"], 'E1075:', 'E121:', 1) call CheckDefAndScriptFailure2(["echo x:somevar"], 'E1075:', 'E121:', 1) - call CheckDefExecAndScriptFailure(["var x = +g:astring"], 'E1030:', 1) - call CheckDefExecAndScriptFailure(["var x = +g:ablob"], 'E974:', 1) - call CheckDefExecAndScriptFailure(["var x = +g:alist"], 'E745:', 1) - call CheckDefExecAndScriptFailure(["var x = +g:adict"], 'E728:', 1) + call CheckDefExecAndScriptFailure2(["var x = +g:astring"], 'E1012:', 'E1030:', 1) + call CheckDefExecAndScriptFailure2(["var x = +g:ablob"], 'E1012:', 'E974:', 1) + call CheckDefExecAndScriptFailure2(["var x = +g:alist"], 'E1012:', 'E745:', 1) + call CheckDefExecAndScriptFailure2(["var x = +g:adict"], 'E1012:', 'E728:', 1) call CheckDefAndScriptFailure2(["var x = ''", "var y = x.memb"], 'E1229: Expected dictionary for using key "memb", but got string', 'E488:', 2) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -469,21 +469,21 @@ def Test_try_catch_throw() try n = -g:astring - catch /E39:/ + catch /E1012:/ n = 233 endtry assert_equal(233, n) try n = +g:astring - catch /E1030:/ + catch /E1012:/ n = 244 endtry assert_equal(244, n) try n = +g:alist - catch /E745:/ + catch /E1012:/ n = 255 endtry assert_equal(255, n) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3353, +/**/ 3352, /**/ 3351, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4210,10 +4210,15 @@ compile_leader(cctx_T *cctx, int numeric --p; if (*p == '-' || *p == '+') { - int negate = *p == '-'; - isn_T *isn; - - // TODO: check type + int negate = *p == '-'; + isn_T *isn; + garray_T *stack = &cctx->ctx_type_stack; + type_T *type; + + type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; + if (need_type(type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL) + return FAIL; + while (p > start && (p[-1] == '-' || p[-1] == '+')) { --p; @@ -4222,11 +4227,11 @@ compile_leader(cctx_T *cctx, int numeric } // only '-' has an effect, for '+' we only check the type if (negate) + { isn = generate_instr(cctx, ISN_NEGATENR); - else - isn = generate_instr(cctx, ISN_CHECKNR); - if (isn == NULL) - return FAIL; + if (isn == NULL) + return FAIL; + } } else if (numeric_only) { @@ -5809,7 +5814,6 @@ compile_nested_function(exarg_T *eap, cc goto theend; r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); } - // TODO: warning for trailing text? theend: vim_free(lambda_name); @@ -5852,7 +5856,6 @@ generate_loadvar( switch (dest) { case dest_option: - // TODO: check the option exists generate_LOAD(cctx, ISN_LOADOPT, 0, name, type); break; case dest_global: