Skip to content

Commit ab9a894

Browse files
yegappanchrisbra
authored andcommitted
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>
1 parent b0206e9 commit ab9a894

4 files changed

Lines changed: 66 additions & 5 deletions

File tree

src/testdir/test_vim9_func.vim

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,47 @@ def Test_not_missing_return()
550550
v9.CheckScriptSuccess(lines)
551551
enddef
552552

553+
" Test for an if-else block ending in a throw statement
554+
def Test_if_else_with_throw()
555+
var lines =<< trim END
556+
def Ifelse_Throw1(): number
557+
if false
558+
return 1
559+
else
560+
throw 'Error'
561+
endif
562+
enddef
563+
defcompile
564+
END
565+
v9.CheckScriptSuccess(lines)
566+
567+
lines =<< trim END
568+
def Ifelse_Throw2(): number
569+
if true
570+
throw 'Error'
571+
else
572+
return 2
573+
endif
574+
enddef
575+
defcompile
576+
END
577+
v9.CheckScriptSuccess(lines)
578+
579+
lines =<< trim END
580+
def Ifelse_Throw3(): number
581+
if true
582+
return 1
583+
elseif false
584+
throw 'Error'
585+
else
586+
return 3
587+
endif
588+
enddef
589+
defcompile
590+
END
591+
v9.CheckScriptSuccess(lines)
592+
enddef
593+
553594
def Test_return_bool()
554595
var lines =<< trim END
555596
vim9script

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
976,
707709
/**/
708710
975,
709711
/**/

src/vim9cmds.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,9 @@ compile_elseif(char_u *arg, cctx_T *cctx)
602602
return NULL;
603603
}
604604
unwind_locals(cctx, scope->se_local_count, TRUE);
605-
if (!cctx->ctx_had_return)
605+
if (!cctx->ctx_had_return && !cctx->ctx_had_throw)
606+
// the previous if block didn't end in a "return" or a "throw"
607+
// statement.
606608
scope->se_u.se_if.is_had_return = FALSE;
607609

608610
if (cctx->ctx_skip == SKIP_NOT)
@@ -749,7 +751,9 @@ compile_else(char_u *arg, cctx_T *cctx)
749751
return NULL;
750752
}
751753
unwind_locals(cctx, scope->se_local_count, TRUE);
752-
if (!cctx->ctx_had_return)
754+
if (!cctx->ctx_had_return && !cctx->ctx_had_throw)
755+
// the previous if block didn't end in a "return" or a "throw"
756+
// statement.
753757
scope->se_u.se_if.is_had_return = FALSE;
754758
scope->se_u.se_if.is_seen_else = TRUE;
755759

@@ -821,7 +825,9 @@ compile_endif(char_u *arg, cctx_T *cctx)
821825
}
822826
ifscope = &scope->se_u.se_if;
823827
unwind_locals(cctx, scope->se_local_count, TRUE);
824-
if (!cctx->ctx_had_return)
828+
if (!cctx->ctx_had_return && !cctx->ctx_had_throw)
829+
// the previous if block didn't end in a "return" or a "throw"
830+
// statement.
825831
ifscope->is_had_return = FALSE;
826832

827833
if (scope->se_u.se_if.is_if_label >= 0)

src/vim9compile.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4407,7 +4407,16 @@ compile_def_function_body(
44074407
cctx->ctx_had_return ? "return" : "throw");
44084408
return FAIL;
44094409
}
4410-
cctx->ctx_had_throw = FALSE;
4410+
4411+
// When processing the end of an if-else block, don't clear the
4412+
// "ctx_had_throw" flag. If an if-else block ends in a "throw"
4413+
// statement, then it is considered to end in a "return" statement.
4414+
// The "ctx_had_throw" is cleared immediately after processing the
4415+
// if-else block ending statement.
4416+
// Otherwise, clear the "had_throw" flag.
4417+
if (ea.cmdidx != CMD_else && ea.cmdidx != CMD_elseif
4418+
&& ea.cmdidx != CMD_endif)
4419+
cctx->ctx_had_throw = FALSE;
44114420

44124421
p = skipwhite(p);
44134422
if (ea.cmdidx != CMD_SIZE
@@ -4474,13 +4483,16 @@ compile_def_function_body(
44744483
case CMD_elseif:
44754484
line = compile_elseif(p, cctx);
44764485
cctx->ctx_had_return = FALSE;
4486+
cctx->ctx_had_throw = FALSE;
44774487
break;
44784488
case CMD_else:
44794489
line = compile_else(p, cctx);
44804490
cctx->ctx_had_return = FALSE;
4491+
cctx->ctx_had_throw = FALSE;
44814492
break;
44824493
case CMD_endif:
44834494
line = compile_endif(p, cctx);
4495+
cctx->ctx_had_throw = FALSE;
44844496
break;
44854497

44864498
case CMD_while:
@@ -4695,7 +4707,7 @@ compile_dfunc_scope_end_missing(cctx_T *cctx)
46954707
}
46964708

46974709
/*
4698-
* When compiling a def function, if it doesn not have an explicit return
4710+
* When compiling a def function, if it doesn't have an explicit return
46994711
* statement, then generate a default return instruction. For an object
47004712
* constructor, return the object.
47014713
*/

0 commit comments

Comments
 (0)