patch 9.0.1557: test failures for unreachable code

Problem:    Test failures for unreachable code.
Solution:   Add a test override to ignore unreachable code.
diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt
index 26f1a8f..97faea0 100644
--- a/runtime/doc/testing.txt
+++ b/runtime/doc/testing.txt
@@ -369,6 +369,7 @@
 			     string is detected
 		ui_delay     time in msec to use in ui_delay(); overrules a
 			     wait time of up to 3 seconds for messages
+		unreachable  no error for code after `:throw` and `:return`
 		uptime	     overrules sysinfo.uptime
 		vterm_title  setting the window title by a job running in a
 			     terminal window
@@ -378,13 +379,18 @@
 		"starting" is to be used when a test should behave like
 		startup was done.  Since the tests are run by sourcing a
 		script the "starting" variable is non-zero. This is usually a
-		good thing (tests run faster), but sometimes changes behavior
-		in a way that the test doesn't work properly.
+		good thing (tests run faster), but sometimes this changes
+		behavior in a way that the test doesn't work properly.
 		When using: >
 			call test_override('starting', 1)
 <		The value of "starting" is saved.  It is restored by: >
 			call test_override('starting', 0)
 
+<		To make sure the flag is reset later using `:defer` can be
+		useful: >
+			call test_override('unreachable', 1)
+			defer call test_override('unreachable', 0)
+
 <		Can also be used as a |method|: >
 			GetOverrideVal()-> test_override('starting')
 
diff --git a/src/globals.h b/src/globals.h
index 3e8b753..69b4343 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1914,6 +1914,7 @@
 EXTERN long override_sysinfo_uptime INIT(= -1);
 EXTERN int  override_autoload INIT(= FALSE);
 EXTERN int  ml_get_alloc_lines INIT(= FALSE);
+EXTERN int  ignore_unreachable_code_for_testing INIT(= FALSE);
 
 EXTERN int  in_free_unref_items INIT(= FALSE);
 #endif
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 3541aa7..d6be8cb 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -490,7 +490,7 @@
   try # comment
     add(l, '1')
     throw 'wrong'
-    add(l, '2')
+    add(l, '2')  # "unreachable code"
   catch # comment
     add(l, v:exception)
   finally # comment
@@ -503,7 +503,7 @@
     try
       add(l, '1')
       throw 'wrong'
-      add(l, '2')
+      add(l, '2')  # "unreachable code"
     catch /right/
       add(l, v:exception)
     endtry
@@ -754,7 +754,7 @@
     var ret = 5
     try
       throw 'getout'
-      return -1
+      return -1 # "unreachable code"
     catch /getout/
       # ret is evaluated here
       return ret
@@ -1082,7 +1082,12 @@
 def DeletedFunc(): list<any>
   return ['delete me']
 enddef
-defcompile
+defcompile DeletedFunc
+
+call test_override('unreachable', 1)
+defcompile Test_try_catch_throw
+call test_override('unreachable', 0)
+
 delfunc DeletedFunc
 
 def s:ThrowFromDef()
@@ -1128,7 +1133,7 @@
   try
     l->add('1')
     throw 'bad'
-    l->add('x')
+    l->add('x')  # "unreachable code"
   catch /bad/
     l->add('2')
     try
@@ -1168,6 +1173,10 @@
   assert_equal(['1', '2', '3', '4'], l)
 enddef
 
+call test_override('unreachable', 1)
+defcompile Test_try_catch_nested
+call test_override('unreachable', 0)
+
 def s:TryOne(): number
   try
     return 0
diff --git a/src/testing.c b/src/testing.c
index dfa9c60..fd55927 100644
--- a/src/testing.c
+++ b/src/testing.c
@@ -1039,6 +1039,8 @@
 	no_wait_return = val;
     else if (STRCMP(name, (char_u *)"ui_delay") == 0)
 	ui_delay_for_testing = val;
+    else if (STRCMP(name, (char_u *)"unreachable") == 0)
+	ignore_unreachable_code_for_testing = val;
     else if (STRCMP(name, (char_u *)"term_props") == 0)
 	reset_term_props_on_termresponse = val;
     else if (STRCMP(name, (char_u *)"vterm_title") == 0)
diff --git a/src/version.c b/src/version.c
index c0c1ca0..cf91da5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1557,
+/**/
     1556,
 /**/
     1555,
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index bc01cd8..c3c900a 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -1578,7 +1578,8 @@
 	return NULL;
     }
 
-    if (scope->se_u.se_try.ts_caught_all)
+    if (scope->se_u.se_try.ts_caught_all
+				       && !ignore_unreachable_code_for_testing)
     {
 	emsg(_(e_catch_unreachable_after_catch_all));
 	return NULL;
diff --git a/src/vim9compile.c b/src/vim9compile.c
index b894c6f..03a6e2c 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -3493,7 +3493,8 @@
 		&& ea.cmdidx != CMD_endwhile
 		&& ea.cmdidx != CMD_catch
 		&& ea.cmdidx != CMD_finally
-		&& ea.cmdidx != CMD_endtry)
+		&& ea.cmdidx != CMD_endtry
+		&& !ignore_unreachable_code_for_testing)
 	{
 	    emsg(_(e_unreachable_code_after_return));
 	    goto erret;