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 <furkan-dev@proton.me>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Furkan Sahin
2026-04-20 16:22:50 +00:00
committed by Christian Brabandt
parent c9d4c1dc43
commit f74a41620b
3 changed files with 70 additions and 0 deletions
+61
View File
@@ -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
+2
View File
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
376,
/**/
375,
/**/
+7
View File
@@ -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;