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
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 976,
/**/
975,
/**/
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)
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;
}
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)
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
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:
}
/*
- * 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.
*/