]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1558: wrong error for unreachable code after :throw v9.0.1558
authorBram Moolenaar <Bram@vim.org>
Sun, 14 May 2023 21:05:15 +0000 (22:05 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 14 May 2023 21:05:15 +0000 (22:05 +0100)
Problem:    Wrong error for unreachable code after :throw.
Solution:   Adjust the error message.

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

index 12f187afbd2c614972bedc2f55e7611c27be02a1..88dad4b75ec196dd493fbc43de4471f04cf47900 100644 (file)
@@ -2809,8 +2809,8 @@ EXTERN char e_expected_nr_items_but_got_nr[]
        INIT(= N_("E1093: Expected %d items but got %d"));
 EXTERN char e_import_can_only_be_used_in_script[]
        INIT(= N_("E1094: Import can only be used in a script"));
-EXTERN char e_unreachable_code_after_return[]
-       INIT(= N_("E1095: Unreachable code after :return"));
+EXTERN char e_unreachable_code_after_str[]
+       INIT(= N_("E1095: Unreachable code after :%s"));
 EXTERN char e_returning_value_in_function_without_return_type[]
        INIT(= N_("E1096: Returning a value in a function without a return type"));
 EXTERN char e_line_incomplete[]
index d6be8cb693cae80c06a4a2368a9aa25d93e7f7ae..338167e7b2b8eef3e019807919d1d5788399505b 100644 (file)
@@ -812,6 +812,30 @@ def Test_try_catch_throw()
   v9.CheckDefAndScriptSuccess(lines)
 enddef
 
+def Test_unreachable_after()
+  var lines =<< trim END
+      try
+        throw 'Error'
+        echo 'not reached'
+      catch /Error/
+      endtry
+  END
+  v9.CheckDefFailure(lines, 'E1095: Unreachable code after :throw')
+
+  lines =<< trim END
+      def SomeFunc(): number
+        try
+          return 3
+          echo 'not reached'
+        catch /Error/
+        endtry
+        return 4
+      enddef
+      defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E1095: Unreachable code after :return')
+enddef
+
 def Test_throw_in_nested_try()
   var lines =<< trim END
       vim9script
@@ -1079,6 +1103,8 @@ def Test_nocatch_throw_silenced()
   source XthrowSilenced
 enddef
 
+" g:DeletedFunc() is found when compiling Test_try_catch_throw() and then
+" deleted, this should give a runtime error.
 def DeletedFunc(): list<any>
   return ['delete me']
 enddef
index cf91da553617d06c23d22fd561f17822098690c4..689b1a2c75b5ce6af53211716ab58e235a8a7626 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1558,
 /**/
     1557,
 /**/
index 48751ce43257869df27e44083ec5adf4e6e63c10..cf24c8d0eabd0d9efa725ad1b17a5d974b4e5f92 100644 (file)
@@ -842,6 +842,7 @@ struct cctx_S {
     skip_T     ctx_skip;
     scope_T    *ctx_scope;         // current scope, NULL at toplevel
     int                ctx_had_return;     // last seen statement was "return"
+    int                ctx_had_throw;      // last seen statement was "throw"
 
     cctx_T     *ctx_outer;         // outer scope for lambda or nested
                                    // function
index 03a6e2c275a1ceee8c415a9fa18477a16e4eedac..265f846618b1ad144ff8ae77f3008accc7666de3 100644 (file)
@@ -3485,7 +3485,7 @@ compile_def_function(
            }
        }
 
-       if (cctx.ctx_had_return
+       if ((cctx.ctx_had_return || cctx.ctx_had_throw)
                && ea.cmdidx != CMD_elseif
                && ea.cmdidx != CMD_else
                && ea.cmdidx != CMD_endif
@@ -3496,9 +3496,11 @@ compile_def_function(
                && ea.cmdidx != CMD_endtry
                && !ignore_unreachable_code_for_testing)
        {
-           emsg(_(e_unreachable_code_after_return));
+           semsg(_(e_unreachable_code_after_str),
+                                    cctx.ctx_had_return ? "return" : "throw");
            goto erret;
        }
+       cctx.ctx_had_throw = FALSE;
 
        p = skipwhite(p);
        if (ea.cmdidx != CMD_SIZE
@@ -3612,7 +3614,7 @@ compile_def_function(
                    break;
            case CMD_throw:
                    line = compile_throw(p, &cctx);
-                   cctx.ctx_had_return = TRUE;
+                   cctx.ctx_had_throw = TRUE;
                    break;
 
            case CMD_eval:
@@ -3765,7 +3767,9 @@ nextline:
        goto erret;
     }
 
-    if (!cctx.ctx_had_return)
+    // TODO: if a function ends in "throw" but there was a return elsewhere we
+    // should not assume the return type is "void".
+    if (!cctx.ctx_had_return && !cctx.ctx_had_throw)
     {
        if (ufunc->uf_ret_type->tt_type == VAR_UNKNOWN)
            ufunc->uf_ret_type = &t_void;