Patch 8.2.2652
Problem:    Vim9: can use command modifier without an effect.
Solution:   Give an error for a misplaced command modifier.  Fix error message
            number.
Files:      src/vim9compile.c, src/ex_docmd.c, src/proto/ex_docmd.pro,
            src/ex_eval.c, src/testdir/test_vim9_cmd.vim,
            src/testdir/test_vim9_builtin.vim,
            src/testdir/test_vim9_disassemble.vim


*** ../vim-8.2.2651/src/vim9compile.c   2021-03-25 21:12:09.902618807 +0100
--- src/vim9compile.c   2021-03-25 22:09:16.377074112 +0100
***************
*** 2142,2152 ****
  {
      isn_T     *isn;
  
!     if (cmod->cmod_flags != 0
!           || cmod->cmod_split != 0
!           || cmod->cmod_verbose != 0
!           || cmod->cmod_tab != 0
!           || cmod->cmod_filter_regmatch.regprog != NULL)
      {
        cctx->ctx_has_cmdmod = TRUE;
  
--- 2142,2148 ----
  {
      isn_T     *isn;
  
!     if (has_cmdmod(cmod))
      {
        cctx->ctx_has_cmdmod = TRUE;
  
***************
*** 2172,2193 ****
      return OK;
  }
  
! /*
!  * If an ISN_CMDMOD was just generated drop it.
!  */
!     static void
! drop_cmdmod(cctx_T *cctx)
  {
      garray_T  *instr = &cctx->ctx_instr;
  
-     // Drop any CMDMOD instruction
      if (cctx->ctx_has_cmdmod
            && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
                                                                 == ISN_CMDMOD)
      {
!       --instr->ga_len;
!       cctx->ctx_has_cmdmod = FALSE;
      }
  }
  
  /*
--- 2168,2186 ----
      return OK;
  }
  
!     static int
! misplaced_cmdmod(cctx_T *cctx)
  {
      garray_T  *instr = &cctx->ctx_instr;
  
      if (cctx->ctx_has_cmdmod
            && ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
                                                                 == ISN_CMDMOD)
      {
!       emsg(_(e_misplaced_command_modifier));
!       return TRUE;
      }
+     return FALSE;
  }
  
  /*
***************
*** 7147,7153 ****
      garray_T  *instr = &cctx->ctx_instr;
      isn_T     *isn;
  
!     drop_cmdmod(cctx);
      if (scope == NULL || scope->se_type != IF_SCOPE)
      {
        emsg(_(e_endif_without_if));
--- 7140,7148 ----
      garray_T  *instr = &cctx->ctx_instr;
      isn_T     *isn;
  
!     if (misplaced_cmdmod(cctx))
!       return NULL;
! 
      if (scope == NULL || scope->se_type != IF_SCOPE)
      {
        emsg(_(e_endif_without_if));
***************
*** 7393,7399 ****
      forscope_T        *forscope;
      isn_T     *isn;
  
!     drop_cmdmod(cctx);
  
      if (scope == NULL || scope->se_type != FOR_SCOPE)
      {
--- 7388,7395 ----
      forscope_T        *forscope;
      isn_T     *isn;
  
!     if (misplaced_cmdmod(cctx))
!       return NULL;
  
      if (scope == NULL || scope->se_type != FOR_SCOPE)
      {
***************
*** 7479,7485 ****
      scope_T   *scope = cctx->ctx_scope;
      garray_T  *instr = &cctx->ctx_instr;
  
!     drop_cmdmod(cctx);
      if (scope == NULL || scope->se_type != WHILE_SCOPE)
      {
        emsg(_(e_while));
--- 7475,7482 ----
      scope_T   *scope = cctx->ctx_scope;
      garray_T  *instr = &cctx->ctx_instr;
  
!     if (misplaced_cmdmod(cctx))
!       return NULL;
      if (scope == NULL || scope->se_type != WHILE_SCOPE)
      {
        emsg(_(e_while));
***************
*** 7644,7649 ****
--- 7641,7649 ----
      scope_T   *try_scope;
      scope_T   *scope;
  
+     if (misplaced_cmdmod(cctx))
+       return NULL;
+ 
      // scope that holds the jumps that go to catch/finally/endtry
      try_scope = new_scope(cctx, TRY_SCOPE);
      if (try_scope == NULL)
***************
*** 7684,7689 ****
--- 7684,7692 ----
      char_u    *p;
      isn_T     *isn;
  
+     if (misplaced_cmdmod(cctx))
+       return NULL;
+ 
      // end block scope from :try or :catch
      if (scope != NULL && scope->se_type == BLOCK_SCOPE)
        compile_endblock(cctx);
***************
*** 7796,7801 ****
--- 7799,7807 ----
      isn_T     *isn;
      int               this_instr;
  
+     if (misplaced_cmdmod(cctx))
+       return NULL;
+ 
      // end block scope from :try or :catch
      if (scope != NULL && scope->se_type == BLOCK_SCOPE)
        compile_endblock(cctx);
***************
*** 7854,7859 ****
--- 7860,7868 ----
      garray_T  *instr = &cctx->ctx_instr;
      isn_T     *try_isn;
  
+     if (misplaced_cmdmod(cctx))
+       return NULL;
+ 
      // end block scope from :catch or :finally
      if (scope != NULL && scope->se_type == BLOCK_SCOPE)
        compile_endblock(cctx);
*** ../vim-8.2.2651/src/ex_docmd.c      2021-03-20 14:59:58.508414399 +0100
--- src/ex_docmd.c      2021-03-25 22:01:28.754365727 +0100
***************
*** 2970,2975 ****
--- 2970,3002 ----
  }
  
  /*
+  * Return TRUE if "cmod" has anything set.
+  */
+     int
+ has_cmdmod(cmdmod_T *cmod)
+ {
+     return cmod->cmod_flags != 0
+           || cmod->cmod_split != 0
+           || cmod->cmod_verbose != 0
+           || cmod->cmod_tab != 0
+           || cmod->cmod_filter_regmatch.regprog != NULL;
+ }
+ 
+ /*
+  * If Vim9 script and "cmdmod" has anything set give an error and return TRUE.
+  */
+     int
+ cmdmod_error(void)
+ {
+     if (in_vim9script() && has_cmdmod(&cmdmod))
+     {
+       emsg(_(e_misplaced_command_modifier));
+       return TRUE;
+     }
+     return FALSE;
+ }
+ 
+ /*
   * Apply the command modifiers.  Saves current state in "cmdmod", call
   * undo_cmdmod() later.
   */
*** ../vim-8.2.2651/src/proto/ex_docmd.pro      2021-03-14 13:21:31.785065163 
+0100
--- src/proto/ex_docmd.pro      2021-03-25 22:01:34.286350222 +0100
***************
*** 8,13 ****
--- 8,15 ----
  char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), 
void *cookie);
  char *ex_errmsg(char *msg, char_u *arg);
  int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, 
int skip_only);
+ int has_cmdmod(cmdmod_T *cmod);
+ int cmdmod_error(void);
  void apply_cmdmod(cmdmod_T *cmod);
  void undo_cmdmod(cmdmod_T *cmod);
  int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);
*** ../vim-8.2.2651/src/ex_eval.c       2021-02-26 22:21:19.082675454 +0100
--- src/ex_eval.c       2021-03-25 22:08:59.889119166 +0100
***************
*** 1011,1016 ****
--- 1011,1018 ----
  {
      cstack_T  *cstack = eap->cstack;
  
+     if (cmdmod_error())
+       return;
      did_endif = TRUE;
      if (cstack->cs_idx < 0
            || (cstack->cs_flags[cstack->cs_idx]
***************
*** 1314,1319 ****
--- 1316,1324 ----
      int               csf;
      int               fl;
  
+     if (cmdmod_error())
+       return;
+ 
      if (eap->cmdidx == CMD_endwhile)
      {
        err = e_while;
***************
*** 1539,1544 ****
--- 1544,1552 ----
      int               skip;
      cstack_T  *cstack = eap->cstack;
  
+     if (cmdmod_error())
+       return;
+ 
      if (cstack->cs_idx == CSTACK_LEN - 1)
        eap->errmsg = _("E601: :try nesting too deep");
      else
***************
*** 1617,1622 ****
--- 1625,1633 ----
      cstack_T  *cstack = eap->cstack;
      char_u    *pat;
  
+     if (cmdmod_error())
+       return;
+ 
      if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
      {
        eap->errmsg = _(e_catch);
***************
*** 1777,1782 ****
--- 1788,1796 ----
      int               pending = CSTP_NONE;
      cstack_T  *cstack = eap->cstack;
  
+     if (cmdmod_error())
+       return;
+ 
      if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
        eap->errmsg = _(e_finally);
      else
***************
*** 1906,1911 ****
--- 1920,1928 ----
      void      *rettv = NULL;
      cstack_T  *cstack = eap->cstack;
  
+     if (cmdmod_error())
+       return;
+ 
      if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
        eap->errmsg = _(e_no_endtry);
      else
*** ../vim-8.2.2651/src/testdir/test_vim9_cmd.vim       2021-03-24 
20:08:08.540745895 +0100
--- src/testdir/test_vim9_cmd.vim       2021-03-25 22:09:42.493002797 +0100
***************
*** 797,802 ****
--- 797,851 ----
    bwipe!
  enddef
  
+ def Test_useless_command_modifier()
+   g:maybe = true
+   var lines =<< trim END
+       if g:maybe
+       silent endif
+   END
+   CheckDefAndScriptFailure(lines, 'E1176:', 2)
+ 
+   lines =<< trim END
+       for i in [0]
+       silent endfor
+   END
+   CheckDefAndScriptFailure(lines, 'E1176:', 2)
+ 
+   lines =<< trim END
+       while g:maybe
+       silent endwhile
+   END
+   CheckDefAndScriptFailure(lines, 'E1176:', 2)
+ 
+   lines =<< trim END
+       silent try
+       finally
+       endtry
+   END
+   CheckDefAndScriptFailure(lines, 'E1176:', 1)
+ 
+   lines =<< trim END
+       try
+       silent catch
+       endtry
+   END
+   CheckDefAndScriptFailure(lines, 'E1176:', 2)
+ 
+   lines =<< trim END
+       try
+       silent finally
+       endtry
+   END
+   CheckDefAndScriptFailure(lines, 'E1176:', 2)
+ 
+   lines =<< trim END
+       try
+       finally
+       silent endtry
+   END
+   CheckDefAndScriptFailure(lines, 'E1176:', 3)
+ enddef
+ 
  def Test_eval_command()
    var from = 3
    var to = 5
*** ../vim-8.2.2651/src/testdir/test_vim9_builtin.vim   2021-03-22 
22:21:22.781399262 +0100
--- src/testdir/test_vim9_builtin.vim   2021-03-25 22:12:34.912533393 +0100
***************
*** 247,253 ****
  def Test_exepath()
    CheckDefExecFailure(['echo exepath(true)'], 'E1174:')
    CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:')
!   CheckDefExecFailure(['echo exepath("")'], 'E1142:')
  enddef
  
  def Test_expand()
--- 247,253 ----
  def Test_exepath()
    CheckDefExecFailure(['echo exepath(true)'], 'E1174:')
    CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:')
!   CheckDefExecFailure(['echo exepath("")'], 'E1175:')
  enddef
  
  def Test_expand()
***************
*** 406,418 ****
  def Test_finddir()
    CheckDefExecFailure(['echo finddir(true)'], 'E1174:')
    CheckDefExecFailure(['echo finddir(v:null)'], 'E1174:')
!   CheckDefExecFailure(['echo finddir("")'], 'E1142:')
  enddef
  
  def Test_findfile()
    CheckDefExecFailure(['echo findfile(true)'], 'E1174:')
    CheckDefExecFailure(['echo findfile(v:null)'], 'E1174:')
!   CheckDefExecFailure(['echo findfile("")'], 'E1142:')
  enddef
  
  def Test_flattennew()
--- 406,418 ----
  def Test_finddir()
    CheckDefExecFailure(['echo finddir(true)'], 'E1174:')
    CheckDefExecFailure(['echo finddir(v:null)'], 'E1174:')
!   CheckDefExecFailure(['echo finddir("")'], 'E1175:')
  enddef
  
  def Test_findfile()
    CheckDefExecFailure(['echo findfile(true)'], 'E1174:')
    CheckDefExecFailure(['echo findfile(v:null)'], 'E1174:')
!   CheckDefExecFailure(['echo findfile("")'], 'E1175:')
  enddef
  
  def Test_flattennew()
*** ../vim-8.2.2651/src/testdir/test_vim9_disassemble.vim       2021-03-25 
21:12:09.902618807 +0100
--- src/testdir/test_vim9_disassemble.vim       2021-03-25 22:13:42.944348686 
+0100
***************
*** 1903,1909 ****
  def s:SilentIf()
    silent if 4 == g:five
    silent elseif 4 == g:five
!   silent endif
  enddef
  
  def Test_silent_if()
--- 1903,1909 ----
  def s:SilentIf()
    silent if 4 == g:five
    silent elseif 4 == g:five
!   endif
  enddef
  
  def Test_silent_if()
***************
*** 1924,1937 ****
          '\d\+ COMPAREANY ==\_s*' ..
          '\d\+ CMDMOD_REV\_s*' ..
          '\d\+ JUMP_IF_FALSE -> \d\+\_s*' ..
!         'silent endif\_s*' ..
          '\d\+ RETURN 0',
          res)
  enddef
  
  def s:SilentFor()
    silent for i in [0]
!   silent endfor
  enddef
  
  def Test_silent_for()
--- 1924,1937 ----
          '\d\+ COMPAREANY ==\_s*' ..
          '\d\+ CMDMOD_REV\_s*' ..
          '\d\+ JUMP_IF_FALSE -> \d\+\_s*' ..
!         'endif\_s*' ..
          '\d\+ RETURN 0',
          res)
  enddef
  
  def s:SilentFor()
    silent for i in [0]
!   endfor
  enddef
  
  def Test_silent_for()
***************
*** 1945,1951 ****
          '\d CMDMOD_REV\_s*' ..
          '5 FOR $0 -> 8\_s*' ..
          '\d STORE $1\_s*' ..
!         'silent endfor\_s*' ..
          '\d JUMP -> 5\_s*' ..
          '8 DROP\_s*' ..
          '\d RETURN 0\_s*',
--- 1945,1951 ----
          '\d CMDMOD_REV\_s*' ..
          '5 FOR $0 -> 8\_s*' ..
          '\d STORE $1\_s*' ..
!         'endfor\_s*' ..
          '\d JUMP -> 5\_s*' ..
          '8 DROP\_s*' ..
          '\d RETURN 0\_s*',
***************
*** 1954,1960 ****
  
  def s:SilentWhile()
    silent while g:not
!   silent endwhile
  enddef
  
  def Test_silent_while()
--- 1954,1960 ----
  
  def s:SilentWhile()
    silent while g:not
!   endwhile
  enddef
  
  def Test_silent_while()
***************
*** 1967,1973 ****
          '\d CMDMOD_REV\_s*' ..
          '\d JUMP_IF_FALSE -> 6\_s*' ..
  
!         'silent endwhile\_s*' ..
          '\d JUMP -> 0\_s*' ..
          '6 RETURN 0\_s*',
           res)
--- 1967,1973 ----
          '\d CMDMOD_REV\_s*' ..
          '\d JUMP_IF_FALSE -> 6\_s*' ..
  
!         'endwhile\_s*' ..
          '\d JUMP -> 0\_s*' ..
          '6 RETURN 0\_s*',
           res)
*** ../vim-8.2.2651/src/version.c       2021-03-25 21:12:09.902618807 +0100
--- src/version.c       2021-03-25 21:48:20.000683734 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2652,
  /**/

-- 
How To Keep A Healthy Level Of Insanity:
7. Finish all your sentences with "in accordance with the prophecy".

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202103252116.12PLG4LB155344%40masaka.moolenaar.net.

Raspunde prin e-mail lui