Skip to content

Commit fa98441

Browse files
committed
patch 8.2.2652: Vim9: can use command modifier without an effect
Problem: Vim9: can use command modifier without an effect. Solution: Give an error for a misplaced command modifier. Fix error message number.
1 parent a91a713 commit fa98441

8 files changed

Lines changed: 131 additions & 25 deletions

File tree

src/ex_docmd.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2969,6 +2969,33 @@ parse_command_modifiers(
29692969
return OK;
29702970
}
29712971

2972+
/*
2973+
* Return TRUE if "cmod" has anything set.
2974+
*/
2975+
int
2976+
has_cmdmod(cmdmod_T *cmod)
2977+
{
2978+
return cmod->cmod_flags != 0
2979+
|| cmod->cmod_split != 0
2980+
|| cmod->cmod_verbose != 0
2981+
|| cmod->cmod_tab != 0
2982+
|| cmod->cmod_filter_regmatch.regprog != NULL;
2983+
}
2984+
2985+
/*
2986+
* If Vim9 script and "cmdmod" has anything set give an error and return TRUE.
2987+
*/
2988+
int
2989+
cmdmod_error(void)
2990+
{
2991+
if (in_vim9script() && has_cmdmod(&cmdmod))
2992+
{
2993+
emsg(_(e_misplaced_command_modifier));
2994+
return TRUE;
2995+
}
2996+
return FALSE;
2997+
}
2998+
29722999
/*
29733000
* Apply the command modifiers. Saves current state in "cmdmod", call
29743001
* undo_cmdmod() later.

src/ex_eval.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,8 @@ ex_endif(exarg_T *eap)
10111011
{
10121012
cstack_T *cstack = eap->cstack;
10131013

1014+
if (cmdmod_error())
1015+
return;
10141016
did_endif = TRUE;
10151017
if (cstack->cs_idx < 0
10161018
|| (cstack->cs_flags[cstack->cs_idx]
@@ -1314,6 +1316,9 @@ ex_endwhile(exarg_T *eap)
13141316
int csf;
13151317
int fl;
13161318

1319+
if (cmdmod_error())
1320+
return;
1321+
13171322
if (eap->cmdidx == CMD_endwhile)
13181323
{
13191324
err = e_while;
@@ -1539,6 +1544,9 @@ ex_try(exarg_T *eap)
15391544
int skip;
15401545
cstack_T *cstack = eap->cstack;
15411546

1547+
if (cmdmod_error())
1548+
return;
1549+
15421550
if (cstack->cs_idx == CSTACK_LEN - 1)
15431551
eap->errmsg = _("E601: :try nesting too deep");
15441552
else
@@ -1617,6 +1625,9 @@ ex_catch(exarg_T *eap)
16171625
cstack_T *cstack = eap->cstack;
16181626
char_u *pat;
16191627

1628+
if (cmdmod_error())
1629+
return;
1630+
16201631
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
16211632
{
16221633
eap->errmsg = _(e_catch);
@@ -1777,6 +1788,9 @@ ex_finally(exarg_T *eap)
17771788
int pending = CSTP_NONE;
17781789
cstack_T *cstack = eap->cstack;
17791790

1791+
if (cmdmod_error())
1792+
return;
1793+
17801794
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
17811795
eap->errmsg = _(e_finally);
17821796
else
@@ -1906,6 +1920,9 @@ ex_endtry(exarg_T *eap)
19061920
void *rettv = NULL;
19071921
cstack_T *cstack = eap->cstack;
19081922

1923+
if (cmdmod_error())
1924+
return;
1925+
19091926
if (cstack->cs_trylevel <= 0 || cstack->cs_idx < 0)
19101927
eap->errmsg = _(e_no_endtry);
19111928
else

src/proto/ex_docmd.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), void
88
char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
99
char *ex_errmsg(char *msg, char_u *arg);
1010
int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, int skip_only);
11+
int has_cmdmod(cmdmod_T *cmod);
12+
int cmdmod_error(void);
1113
void apply_cmdmod(cmdmod_T *cmod);
1214
void undo_cmdmod(cmdmod_T *cmod);
1315
int parse_cmd_address(exarg_T *eap, char **errormsg, int silent);

src/testdir/test_vim9_builtin.vim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ enddef
247247
def Test_exepath()
248248
CheckDefExecFailure(['echo exepath(true)'], 'E1174:')
249249
CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:')
250-
CheckDefExecFailure(['echo exepath("")'], 'E1142:')
250+
CheckDefExecFailure(['echo exepath("")'], 'E1175:')
251251
enddef
252252

253253
def Test_expand()
@@ -406,13 +406,13 @@ enddef
406406
def Test_finddir()
407407
CheckDefExecFailure(['echo finddir(true)'], 'E1174:')
408408
CheckDefExecFailure(['echo finddir(v:null)'], 'E1174:')
409-
CheckDefExecFailure(['echo finddir("")'], 'E1142:')
409+
CheckDefExecFailure(['echo finddir("")'], 'E1175:')
410410
enddef
411411

412412
def Test_findfile()
413413
CheckDefExecFailure(['echo findfile(true)'], 'E1174:')
414414
CheckDefExecFailure(['echo findfile(v:null)'], 'E1174:')
415-
CheckDefExecFailure(['echo findfile("")'], 'E1142:')
415+
CheckDefExecFailure(['echo findfile("")'], 'E1175:')
416416
enddef
417417

418418
def Test_flattennew()

src/testdir/test_vim9_cmd.vim

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,55 @@ def Test_silent_pattern()
797797
bwipe!
798798
enddef
799799

800+
def Test_useless_command_modifier()
801+
g:maybe = true
802+
var lines =<< trim END
803+
if g:maybe
804+
silent endif
805+
END
806+
CheckDefAndScriptFailure(lines, 'E1176:', 2)
807+
808+
lines =<< trim END
809+
for i in [0]
810+
silent endfor
811+
END
812+
CheckDefAndScriptFailure(lines, 'E1176:', 2)
813+
814+
lines =<< trim END
815+
while g:maybe
816+
silent endwhile
817+
END
818+
CheckDefAndScriptFailure(lines, 'E1176:', 2)
819+
820+
lines =<< trim END
821+
silent try
822+
finally
823+
endtry
824+
END
825+
CheckDefAndScriptFailure(lines, 'E1176:', 1)
826+
827+
lines =<< trim END
828+
try
829+
silent catch
830+
endtry
831+
END
832+
CheckDefAndScriptFailure(lines, 'E1176:', 2)
833+
834+
lines =<< trim END
835+
try
836+
silent finally
837+
endtry
838+
END
839+
CheckDefAndScriptFailure(lines, 'E1176:', 2)
840+
841+
lines =<< trim END
842+
try
843+
finally
844+
silent endtry
845+
END
846+
CheckDefAndScriptFailure(lines, 'E1176:', 3)
847+
enddef
848+
800849
def Test_eval_command()
801850
var from = 3
802851
var to = 5

src/testdir/test_vim9_disassemble.vim

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,7 +1903,7 @@ enddef
19031903
def s:SilentIf()
19041904
silent if 4 == g:five
19051905
silent elseif 4 == g:five
1906-
silent endif
1906+
endif
19071907
enddef
19081908

19091909
def Test_silent_if()
@@ -1924,14 +1924,14 @@ def Test_silent_if()
19241924
'\d\+ COMPAREANY ==\_s*' ..
19251925
'\d\+ CMDMOD_REV\_s*' ..
19261926
'\d\+ JUMP_IF_FALSE -> \d\+\_s*' ..
1927-
'silent endif\_s*' ..
1927+
'endif\_s*' ..
19281928
'\d\+ RETURN 0',
19291929
res)
19301930
enddef
19311931

19321932
def s:SilentFor()
19331933
silent for i in [0]
1934-
silent endfor
1934+
endfor
19351935
enddef
19361936

19371937
def Test_silent_for()
@@ -1945,7 +1945,7 @@ def Test_silent_for()
19451945
'\d CMDMOD_REV\_s*' ..
19461946
'5 FOR $0 -> 8\_s*' ..
19471947
'\d STORE $1\_s*' ..
1948-
'silent endfor\_s*' ..
1948+
'endfor\_s*' ..
19491949
'\d JUMP -> 5\_s*' ..
19501950
'8 DROP\_s*' ..
19511951
'\d RETURN 0\_s*',
@@ -1954,7 +1954,7 @@ enddef
19541954

19551955
def s:SilentWhile()
19561956
silent while g:not
1957-
silent endwhile
1957+
endwhile
19581958
enddef
19591959

19601960
def Test_silent_while()
@@ -1967,7 +1967,7 @@ def Test_silent_while()
19671967
'\d CMDMOD_REV\_s*' ..
19681968
'\d JUMP_IF_FALSE -> 6\_s*' ..
19691969

1970-
'silent endwhile\_s*' ..
1970+
'endwhile\_s*' ..
19711971
'\d JUMP -> 0\_s*' ..
19721972
'6 RETURN 0\_s*',
19731973
res)

src/version.c

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

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2652,
753755
/**/
754756
2651,
755757
/**/

src/vim9compile.c

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2142,11 +2142,7 @@ generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
21422142
{
21432143
isn_T *isn;
21442144

2145-
if (cmod->cmod_flags != 0
2146-
|| cmod->cmod_split != 0
2147-
|| cmod->cmod_verbose != 0
2148-
|| cmod->cmod_tab != 0
2149-
|| cmod->cmod_filter_regmatch.regprog != NULL)
2145+
if (has_cmdmod(cmod))
21502146
{
21512147
cctx->ctx_has_cmdmod = TRUE;
21522148

@@ -2172,22 +2168,19 @@ generate_undo_cmdmods(cctx_T *cctx)
21722168
return OK;
21732169
}
21742170

2175-
/*
2176-
* If an ISN_CMDMOD was just generated drop it.
2177-
*/
2178-
static void
2179-
drop_cmdmod(cctx_T *cctx)
2171+
static int
2172+
misplaced_cmdmod(cctx_T *cctx)
21802173
{
21812174
garray_T *instr = &cctx->ctx_instr;
21822175

2183-
// Drop any CMDMOD instruction
21842176
if (cctx->ctx_has_cmdmod
21852177
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1].isn_type
21862178
== ISN_CMDMOD)
21872179
{
2188-
--instr->ga_len;
2189-
cctx->ctx_has_cmdmod = FALSE;
2180+
emsg(_(e_misplaced_command_modifier));
2181+
return TRUE;
21902182
}
2183+
return FALSE;
21912184
}
21922185

21932186
/*
@@ -7147,7 +7140,9 @@ compile_endif(char_u *arg, cctx_T *cctx)
71477140
garray_T *instr = &cctx->ctx_instr;
71487141
isn_T *isn;
71497142

7150-
drop_cmdmod(cctx);
7143+
if (misplaced_cmdmod(cctx))
7144+
return NULL;
7145+
71517146
if (scope == NULL || scope->se_type != IF_SCOPE)
71527147
{
71537148
emsg(_(e_endif_without_if));
@@ -7393,7 +7388,8 @@ compile_endfor(char_u *arg, cctx_T *cctx)
73937388
forscope_T *forscope;
73947389
isn_T *isn;
73957390

7396-
drop_cmdmod(cctx);
7391+
if (misplaced_cmdmod(cctx))
7392+
return NULL;
73977393

73987394
if (scope == NULL || scope->se_type != FOR_SCOPE)
73997395
{
@@ -7479,7 +7475,8 @@ compile_endwhile(char_u *arg, cctx_T *cctx)
74797475
scope_T *scope = cctx->ctx_scope;
74807476
garray_T *instr = &cctx->ctx_instr;
74817477

7482-
drop_cmdmod(cctx);
7478+
if (misplaced_cmdmod(cctx))
7479+
return NULL;
74837480
if (scope == NULL || scope->se_type != WHILE_SCOPE)
74847481
{
74857482
emsg(_(e_while));
@@ -7644,6 +7641,9 @@ compile_try(char_u *arg, cctx_T *cctx)
76447641
scope_T *try_scope;
76457642
scope_T *scope;
76467643

7644+
if (misplaced_cmdmod(cctx))
7645+
return NULL;
7646+
76477647
// scope that holds the jumps that go to catch/finally/endtry
76487648
try_scope = new_scope(cctx, TRY_SCOPE);
76497649
if (try_scope == NULL)
@@ -7684,6 +7684,9 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
76847684
char_u *p;
76857685
isn_T *isn;
76867686

7687+
if (misplaced_cmdmod(cctx))
7688+
return NULL;
7689+
76877690
// end block scope from :try or :catch
76887691
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
76897692
compile_endblock(cctx);
@@ -7796,6 +7799,9 @@ compile_finally(char_u *arg, cctx_T *cctx)
77967799
isn_T *isn;
77977800
int this_instr;
77987801

7802+
if (misplaced_cmdmod(cctx))
7803+
return NULL;
7804+
77997805
// end block scope from :try or :catch
78007806
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
78017807
compile_endblock(cctx);
@@ -7854,6 +7860,9 @@ compile_endtry(char_u *arg, cctx_T *cctx)
78547860
garray_T *instr = &cctx->ctx_instr;
78557861
isn_T *try_isn;
78567862

7863+
if (misplaced_cmdmod(cctx))
7864+
return NULL;
7865+
78577866
// end block scope from :catch or :finally
78587867
if (scope != NULL && scope->se_type == BLOCK_SCOPE)
78597868
compile_endblock(cctx);

0 commit comments

Comments
 (0)