Commit: patch 9.2.0376: Vim9: elseif condition compiled in dead branch

2 views
Skip to first unread message

Christian Brabandt

unread,
12:45 PM (6 hours ago) 12:45 PM
to vim...@googlegroups.com
patch 9.2.0376: Vim9: elseif condition compiled in dead branch

Commit: https://github.com/vim/vim/commit/f74a41620ba9a69edfe3ce0b88b42024cb6361bb
Author: Furkan Sahin <furka...@proton.me>
Date: Mon Apr 20 16:22:50 2026 +0000

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 <furka...@proton.me>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 262f47db2..fcb585f02 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 47ea1bac7..272d7dda0 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 db81229ee..5005cf898 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;
Reply all
Reply to author
Forward
0 new messages