Patch 8.2.4071
Problem:    Vim9: no detection of return in try/endtry. (Dominique Pellé)
Solution:   Check if any of the blocks inside try/endtry did not end in
            return.
Files:      src/vim9.h, src/vim9compile.c, src/vim9cmds.c,
            src/testdir/test_vim9_script.vim


*** ../vim-8.2.4070/src/vim9.h  2022-01-03 12:27:59.355039941 +0000
--- src/vim9.h  2022-01-12 15:59:01.409943723 +0000
***************
*** 594,599 ****
--- 594,601 ----
      endlabel_T        *ts_end_label;      // jump to :finally or :endtry
      int               ts_catch_label;     // instruction idx of last CATCH
      int               ts_caught_all;      // "catch" without argument 
encountered
+     int               ts_has_finally;     // "finally" encountered
+     int               ts_no_return;       // one of the blocks did not end in 
return
  } tryscope_T;
  
  typedef enum {
*** ../vim-8.2.4070/src/vim9compile.c   2022-01-12 11:46:36.314615880 +0000
--- src/vim9compile.c   2022-01-12 16:06:00.544331815 +0000
***************
*** 3041,3047 ****
                    break;
            case CMD_endtry:
                    line = compile_endtry(p, &cctx);
-                   cctx.ctx_had_return = FALSE;
                    break;
            case CMD_throw:
                    line = compile_throw(p, &cctx);
--- 3041,3046 ----
*** ../vim-8.2.4070/src/vim9cmds.c      2022-01-06 21:38:07.822094822 +0000
--- src/vim9cmds.c      2022-01-12 16:03:43.108852149 +0000
***************
*** 1343,1348 ****
--- 1343,1350 ----
        emsg(_(e_catch_unreachable_after_catch_all));
        return NULL;
      }
+     if (!cctx->ctx_had_return)
+       scope->se_u.se_try.ts_no_return = TRUE;
  
      if (cctx->ctx_skip != SKIP_YES)
      {
***************
*** 1498,1503 ****
--- 1500,1506 ----
            isn->isn_arg.jump.jump_where = this_instr;
            scope->se_u.se_try.ts_catch_label = 0;
        }
+       scope->se_u.se_try.ts_has_finally = TRUE;
        if (generate_instr(cctx, ISN_FINALLY) == NULL)
            return NULL;
      }
***************
*** 1567,1572 ****
--- 1570,1583 ----
        }
      }
  
+     // If there is a finally clause that ends in return then we will return.
+     // If one of the blocks didn't end in "return" or we did not catch all
+     // exceptions reset the had_return flag.
+     if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
+           && (scope->se_u.se_try.ts_no_return
+               || !scope->se_u.se_try.ts_caught_all))
+       cctx->ctx_had_return = FALSE;
+ 
      compile_endblock(cctx);
  
      if (cctx->ctx_skip != SKIP_YES)
*** ../vim-8.2.4070/src/testdir/test_vim9_script.vim    2022-01-10 
21:29:53.380429159 +0000
--- src/testdir/test_vim9_script.vim    2022-01-12 16:15:39.562178890 +0000
***************
*** 667,673 ****
      finally
        return 6
      endtry
-     return -1
    enddef
    assert_equal(6, ReturnInFinally())
  
--- 667,672 ----
***************
*** 708,713 ****
--- 707,770 ----
    CheckDefAndScriptSuccess(lines)
  enddef
  
+ def Test_try_ends_in_return()
+   var lines =<< trim END
+       vim9script
+       def Foo(): string
+         try
+           return 'foo'
+         catch
+           return 'caught'
+         endtry
+       enddef
+       assert_equal('foo', Foo())
+   END
+   CheckScriptSuccess(lines)
+ 
+   lines =<< trim END
+       vim9script
+       def Foo(): string
+         try
+           return 'foo'
+         catch
+           return 'caught'
+         endtry
+         echo 'notreached'
+       enddef
+       assert_equal('foo', Foo())
+   END
+   CheckScriptFailure(lines, 'E1095:')
+ 
+   lines =<< trim END
+       vim9script
+       def Foo(): string
+         try
+           return 'foo'
+         catch /x/
+           return 'caught'
+         endtry
+       enddef
+       assert_equal('foo', Foo())
+   END
+   CheckScriptFailure(lines, 'E1027:')
+ 
+   lines =<< trim END
+       vim9script
+       def Foo(): string
+         try
+           echo 'foo'
+         catch
+           echo 'caught'
+         finally
+           return 'done'
+         endtry
+       enddef
+       assert_equal('done', Foo())
+   END
+   CheckScriptSuccess(lines)
+ 
+ enddef
+ 
  def Test_try_in_catch()
    var lines =<< trim END
        vim9script
*** ../vim-8.2.4070/src/version.c       2022-01-12 15:24:36.641292770 +0000
--- src/version.c       2022-01-12 15:52:28.623463378 +0000
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     4071,
  /**/

-- 
DINGO:   You must spank her well and after you have spanked her you
         may deal with her as you like and then ... spank me.
AMAZING: And spank me!
STUNNER: And me.
LOVELY:  And me.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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/20220112162004.429AB1C05F1%40moolenaar.net.

Raspunde prin e-mail lui