mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -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:
committed by
Christian Brabandt
parent
b0206e9fb5
commit
ab9a8947d7
@@ -550,6 +550,47 @@ def Test_not_missing_return()
|
|||||||
v9.CheckScriptSuccess(lines)
|
v9.CheckScriptSuccess(lines)
|
||||||
enddef
|
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()
|
def Test_return_bool()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
976,
|
||||||
/**/
|
/**/
|
||||||
975,
|
975,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -602,7 +602,9 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
unwind_locals(cctx, scope->se_local_count, TRUE);
|
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_had_return = FALSE;
|
||||||
|
|
||||||
if (cctx->ctx_skip == SKIP_NOT)
|
if (cctx->ctx_skip == SKIP_NOT)
|
||||||
@@ -749,7 +751,9 @@ compile_else(char_u *arg, cctx_T *cctx)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
unwind_locals(cctx, scope->se_local_count, TRUE);
|
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_had_return = FALSE;
|
||||||
scope->se_u.se_if.is_seen_else = TRUE;
|
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;
|
ifscope = &scope->se_u.se_if;
|
||||||
unwind_locals(cctx, scope->se_local_count, TRUE);
|
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;
|
ifscope->is_had_return = FALSE;
|
||||||
|
|
||||||
if (scope->se_u.se_if.is_if_label >= 0)
|
if (scope->se_u.se_if.is_if_label >= 0)
|
||||||
|
@@ -4407,7 +4407,16 @@ compile_def_function_body(
|
|||||||
cctx->ctx_had_return ? "return" : "throw");
|
cctx->ctx_had_return ? "return" : "throw");
|
||||||
return FAIL;
|
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);
|
p = skipwhite(p);
|
||||||
if (ea.cmdidx != CMD_SIZE
|
if (ea.cmdidx != CMD_SIZE
|
||||||
@@ -4474,13 +4483,16 @@ compile_def_function_body(
|
|||||||
case CMD_elseif:
|
case CMD_elseif:
|
||||||
line = compile_elseif(p, cctx);
|
line = compile_elseif(p, cctx);
|
||||||
cctx->ctx_had_return = FALSE;
|
cctx->ctx_had_return = FALSE;
|
||||||
|
cctx->ctx_had_throw = FALSE;
|
||||||
break;
|
break;
|
||||||
case CMD_else:
|
case CMD_else:
|
||||||
line = compile_else(p, cctx);
|
line = compile_else(p, cctx);
|
||||||
cctx->ctx_had_return = FALSE;
|
cctx->ctx_had_return = FALSE;
|
||||||
|
cctx->ctx_had_throw = FALSE;
|
||||||
break;
|
break;
|
||||||
case CMD_endif:
|
case CMD_endif:
|
||||||
line = compile_endif(p, cctx);
|
line = compile_endif(p, cctx);
|
||||||
|
cctx->ctx_had_throw = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_while:
|
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
|
* statement, then generate a default return instruction. For an object
|
||||||
* constructor, return the object.
|
* constructor, return the object.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user