0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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 <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yegappan Lakshmanan 2024-12-30 09:56:34 +01:00 committed by Christian Brabandt
parent b0206e9fb5
commit ab9a8947d7
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
4 changed files with 66 additions and 5 deletions

View File

@ -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

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
976,
/**/
975,
/**/

View File

@ -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)

View File

@ -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.
*/