summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2023-05-14 22:05:15 +0100
committerBram Moolenaar <Bram@vim.org>2023-05-14 22:05:15 +0100
commita2c0028fdf8dcf0408e27be730ac0e691ef9559b (patch)
tree46f3b527e0d22d73b68685f4499654f9d5205018
parent9d383f30bbd06552ad0bf343b2c03c6a0d1f6df2 (diff)
downloadvim-git-a2c0028fdf8dcf0408e27be730ac0e691ef9559b.tar.gz
patch 9.0.1558: wrong error for unreachable code after :throwv9.0.1558
Problem: Wrong error for unreachable code after :throw. Solution: Adjust the error message.
-rw-r--r--src/errors.h4
-rw-r--r--src/testdir/test_vim9_script.vim26
-rw-r--r--src/version.c2
-rw-r--r--src/vim9.h1
-rw-r--r--src/vim9compile.c12
5 files changed, 39 insertions, 6 deletions
diff --git a/src/errors.h b/src/errors.h
index 12f187afb..88dad4b75 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -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[]
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index d6be8cb69..338167e7b 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index cf91da553..689b1a2c7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1558,
+/**/
1557,
/**/
1556,
diff --git a/src/vim9.h b/src/vim9.h
index 48751ce43..cf24c8d0e 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -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
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 03a6e2c27..265f84661 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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;