]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.4071: Vim9: no detection of return in try/endtry v8.2.4071
authorBram Moolenaar <Bram@vim.org>
Wed, 12 Jan 2022 16:18:18 +0000 (16:18 +0000)
committerBram Moolenaar <Bram@vim.org>
Wed, 12 Jan 2022 16:18:18 +0000 (16:18 +0000)
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.

src/testdir/test_vim9_script.vim
src/version.c
src/vim9.h
src/vim9cmds.c
src/vim9compile.c

index 04890bc4286f580298fd9b44d73bf7bfff481d17..8bf2e9ef19eb9b135bea2fb075d6eb1576b52ece 100644 (file)
@@ -667,7 +667,6 @@ def Test_try_catch_throw()
     finally
       return 6
     endtry
-    return -1
   enddef
   assert_equal(6, ReturnInFinally())
 
@@ -708,6 +707,64 @@ def Test_try_catch_throw()
   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
index 8c77e2efb0728dab66b1ec5ca97ce47a61a887ab..2a1b4ae5e223fc8646a4e66369b3162937aee5d1 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4071,
 /**/
     4070,
 /**/
index 2ae3f42088cc875bd1fbb38d568b7e4d1926b917..912af1f5d513ef8a9868cbb9926785ccf259e620 100644 (file)
@@ -594,6 +594,8 @@ typedef struct {
     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 {
index 3372ad42d3bb0f51c95305d1406b7d9267202f27..5beeab82e82c9fbb7abfda60528bd35eae198bb2 100644 (file)
@@ -1343,6 +1343,8 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
        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,6 +1500,7 @@ compile_finally(char_u *arg, cctx_T *cctx)
            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,6 +1570,14 @@ compile_endtry(char_u *arg, cctx_T *cctx)
        }
     }
 
+    // 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)
index 90cb2b4ffa45308f4dbdb3732c14427179d42ba4..7e4f99fb434a8c5ce850299dd363bf41bb2f4e3e 100644 (file)
@@ -3041,7 +3041,6 @@ compile_def_function(
                    break;
            case CMD_endtry:
                    line = compile_endtry(p, &cctx);
-                   cctx.ctx_had_return = FALSE;
                    break;
            case CMD_throw:
                    line = compile_throw(p, &cctx);