From: Furkan Sahin Date: Mon, 20 Apr 2026 16:22:50 +0000 (+0000) Subject: patch 9.2.0376: Vim9: elseif condition compiled in dead branch X-Git-Tag: v9.2.0376^0 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=f74a41620ba9a69edfe3ce0b88b42024cb6361bb;p=thirdparty%2Fvim.git patch 9.2.0376: Vim9: elseif condition compiled in dead branch Problem: When an `if` condition is constant true, the `else` block is skipped during compilation. However, any `elseif` condition within that skipped block was still compiled. This caused errors when the condition referenced variables only declared in the skipped block or when it checked for missing features (like `has('clipboard')`) (Coacher) Solution: In compile_elseif(), when scope->se_skip_save is already SKIP_YES, skip compiling the elseif condition expression using skip_expr_cctx() (Furkan Sahin) fixes: #19160 closes: #20021 Signed-off-by: Furkan Sahin Signed-off-by: Christian Brabandt --- diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 262f47db2f..fcb585f026 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -5933,4 +5933,65 @@ def Test_g_variable_shadow_multi_context() unlet g:F enddef +" Test that dead elseif conditions are skipped without errors inside a :def function +def Test_skip_elseif_dead_branch() + var lines =<< trim END + vim9script + def CompileTest() + if true + echo 'ok' + else + var x = 0 + if x > 0 + echo 'pos' + elseif x < 0 + echo 'neg' + endif + endif + enddef + CompileTest() + END + v9.CheckScriptSuccess(lines) +enddef + +" Another variation: using has() in a dead branch that would fail if compiled +def Test_skip_elseif_with_has_in_dead_branch() + var lines =<< trim END + vim9script + def HasTest() + if true + echo 'ok' + else + var x = 0 + if x > 0 + echo 'pos' + elseif has('clipboard') + echo 'neg' + endif + endif + enddef + HasTest() + END + v9.CheckScriptSuccess(lines) +enddef + +def Test_if_false_elseif_true_still_takes_elseif() + var lines =<< trim END + vim9script + var result = '' + def F() + if false + result = 'A' + elseif true + result = 'B' + else + result = 'C' + endif + enddef + F() + assert_equal('B', result) + END + v9.CheckScriptSuccess(lines) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 47ea1bac76..272d7dda07 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 376, /**/ 375, /**/ diff --git a/src/vim9cmds.c b/src/vim9cmds.c index db81229eed..5005cf898a 100644 --- a/src/vim9cmds.c +++ b/src/vim9cmds.c @@ -623,6 +623,13 @@ compile_elseif(char_u *arg, cctx_T *cctx) return p; } + if (scope->se_skip_save == SKIP_YES) + { + // Enclosing outer block is dead, skip this elseif + skip_expr_cctx(&p, cctx); + return p; + } + if (cctx->ctx_skip == SKIP_UNKNOWN) { int moved_cmdmod = FALSE;