patch 9.1.0976: Vim9: missing return statement with throw

Commit: 
https://github.com/vim/vim/commit/ab9a8947d73c09981b966d3994f0a9298b8b5674
Author: Yegappan Lakshmanan <yegap...@yahoo.com>
Date:   Mon Dec 30 09:56:34 2024 +0100

    patch 9.1.0976: Vim9: missing return statement with throw
    
    Problem:  Vim9: missing return statement with throw
              (atitcreate)
    Solution: Treat a throw statement at the end of an if-else block as a
              return statement (Yegappan Lakshmanan)
    
    fixes: #16312
    closes: #16338
    
    Signed-off-by: Yegappan Lakshmanan <yegap...@yahoo.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 030ff833e..79bb9d821 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -550,6 +550,47 @@ def Test_not_missing_return()
   v9.CheckScriptSuccess(lines)
 enddef
 
+" Test for an if-else block ending in a throw statement
+def Test_if_else_with_throw()
+  var lines =<< trim END
+      def Ifelse_Throw1(): number
+        if false
+          return 1
+        else
+          throw 'Error'
+        endif
+      enddef
+      defcompile
+  END
+  v9.CheckScriptSuccess(lines)
+
+  lines =<< trim END
+      def Ifelse_Throw2(): number
+        if true
+          throw 'Error'
+        else
+          return 2
+        endif
+      enddef
+      defcompile
+  END
+  v9.CheckScriptSuccess(lines)
+
+  lines =<< trim END
+      def Ifelse_Throw3(): number
+        if true
+          return 1
+        elseif false
+          throw 'Error'
+        else
+          return 3
+        endif
+      enddef
+      defcompile
+  END
+  v9.CheckScriptSuccess(lines)
+enddef
+
 def Test_return_bool()
   var lines =<< trim END
       vim9script
diff --git a/src/version.c b/src/version.c
index ca353c28c..d4fd17e6c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    976,
 /**/
     975,
 /**/
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index c7fa60aa4..f8ebfb128 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -602,7 +602,9 @@ compile_elseif(char_u *arg, cctx_T *cctx)
        return NULL;
     }
     unwind_locals(cctx, scope->se_local_count, TRUE);
-    if (!cctx->ctx_had_return)
+    if (!cctx->ctx_had_return && !cctx->ctx_had_throw)
+       // the previous if block didn't end in a "return" or a "throw"
+       // statement.
        scope->se_u.se_if.is_had_return = FALSE;
 
     if (cctx->ctx_skip == SKIP_NOT)
@@ -749,7 +751,9 @@ compile_else(char_u *arg, cctx_T *cctx)
        return NULL;
     }
     unwind_locals(cctx, scope->se_local_count, TRUE);
-    if (!cctx->ctx_had_return)
+    if (!cctx->ctx_had_return && !cctx->ctx_had_throw)
+       // the previous if block didn't end in a "return" or a "throw"
+       // statement.
        scope->se_u.se_if.is_had_return = FALSE;
     scope->se_u.se_if.is_seen_else = TRUE;
 
@@ -821,7 +825,9 @@ compile_endif(char_u *arg, cctx_T *cctx)
     }
     ifscope = &scope->se_u.se_if;
     unwind_locals(cctx, scope->se_local_count, TRUE);
-    if (!cctx->ctx_had_return)
+    if (!cctx->ctx_had_return && !cctx->ctx_had_throw)
+       // the previous if block didn't end in a "return" or a "throw"
+       // statement.
        ifscope->is_had_return = FALSE;
 
     if (scope->se_u.se_if.is_if_label >= 0)
diff --git a/src/vim9compile.c b/src/vim9compile.c
index c8a50cf4c..a2dd77a44 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -4407,7 +4407,16 @@ compile_def_function_body(
                                     cctx->ctx_had_return ? "return" : "throw");
            return FAIL;
        }
-       cctx->ctx_had_throw = FALSE;
+
+       // When processing the end of an if-else block, don't clear the
+       // "ctx_had_throw" flag.  If an if-else block ends in a "throw"
+       // statement, then it is considered to end in a "return" statement.
+       // The "ctx_had_throw" is cleared immediately after processing the
+       // if-else block ending statement.
+       // Otherwise, clear the "had_throw" flag.
+       if (ea.cmdidx != CMD_else && ea.cmdidx != CMD_elseif
+                                               && ea.cmdidx != CMD_endif)
+           cctx->ctx_had_throw = FALSE;
 
        p = skipwhite(p);
        if (ea.cmdidx != CMD_SIZE
@@ -4474,13 +4483,16 @@ compile_def_function_body(
            case CMD_elseif:
                    line = compile_elseif(p, cctx);
                    cctx->ctx_had_return = FALSE;
+                   cctx->ctx_had_throw = FALSE;
                    break;
            case CMD_else:
                    line = compile_else(p, cctx);
                    cctx->ctx_had_return = FALSE;
+                   cctx->ctx_had_throw = FALSE;
                    break;
            case CMD_endif:
                    line = compile_endif(p, cctx);
+                   cctx->ctx_had_throw = FALSE;
                    break;
 
            case CMD_while:
@@ -4695,7 +4707,7 @@ compile_dfunc_scope_end_missing(cctx_T *cctx)
 }
 
 /*
- * When compiling a def function, if it doesn not have an explicit return
+ * When compiling a def function, if it doesn't have an explicit return
  * statement, then generate a default return instruction.  For an object
  * constructor, return the object.
  */

-- 
-- 
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 vim_dev+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1tSBdA-00DPZ4-JI%40256bit.org.

Raspunde prin e-mail lui