• R/O
  • SSH

vim: Commit

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

Révision6ed31017c3033513aa55952bc06aa995e960681a (tree)
l'heure2022-01-16 06:45:03
AuteurBram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Message de Log

patch 8.2.4103: Vim9: variable declared in for loop not initialzed

Commit: https://github.com/vim/vim/commit/38ecd9722664049d636f4fba759b3ebbfd34e97d
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 15 21:44:44 2022 +0000

patch 8.2.4103: Vim9: variable declared in for loop not initialzed
Problem: Vim9: variable declared in for loop not initialzed.
Solution: Always initialze the variable. (closes https://github.com/vim/vim/issues/9535)

Change Summary

Modification

diff -r bcaefb769725 -r 6ed31017c303 src/proto/vim9instr.pro
--- a/src/proto/vim9instr.pro Sat Jan 15 22:15:03 2022 +0100
+++ b/src/proto/vim9instr.pro Sat Jan 15 22:45:03 2022 +0100
@@ -63,6 +63,7 @@
6363 int generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod);
6464 int generate_undo_cmdmods(cctx_T *cctx);
6565 int generate_store_var(cctx_T *cctx, assign_dest_T dest, int opt_flags, int vimvaridx, int scriptvar_idx, int scriptvar_sid, type_T *type, char_u *name);
66+int inside_loop_scope(cctx_T *cctx);
6667 int generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl);
6768 void may_generate_prof_end(cctx_T *cctx, int prof_lnum);
6869 void delete_instr(isn_T *isn);
diff -r bcaefb769725 -r 6ed31017c303 src/testdir/test_vim9_assign.vim
--- a/src/testdir/test_vim9_assign.vim Sat Jan 15 22:15:03 2022 +0100
+++ b/src/testdir/test_vim9_assign.vim Sat Jan 15 22:45:03 2022 +0100
@@ -587,6 +587,41 @@
587587 CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2)
588588 enddef
589589
590+def Test_init_in_for_loop()
591+ var lines =<< trim END
592+ var l: list<number> = []
593+ for i in [3, 4]
594+ var n: number
595+ add(l, n)
596+ n = 123
597+ endfor
598+ assert_equal([0, 0], l)
599+ END
600+ CheckDefAndScriptSuccess(lines)
601+
602+ lines =<< trim END
603+ var l: list<number> = []
604+ for i in [3, 4]
605+ var n: number = 0
606+ add(l, n)
607+ n = 123
608+ endfor
609+ assert_equal([0, 0], l)
610+ END
611+ CheckDefAndScriptSuccess(lines)
612+
613+ lines =<< trim END
614+ var l: list<number> = []
615+ for i in [3, 4]
616+ var n: number = 3
617+ add(l, n)
618+ n = 123
619+ endfor
620+ assert_equal([3, 3], l)
621+ END
622+ CheckDefAndScriptSuccess(lines)
623+enddef
624+
590625 def Test_extend_list()
591626 var lines =<< trim END
592627 var l1: list<number>
diff -r bcaefb769725 -r 6ed31017c303 src/version.c
--- a/src/version.c Sat Jan 15 22:15:03 2022 +0100
+++ b/src/version.c Sat Jan 15 22:45:03 2022 +0100
@@ -751,6 +751,8 @@
751751 static int included_patches[] =
752752 { /* Add new patch number below this line */
753753 /**/
754+ 4103,
755+/**/
754756 4102,
755757 /**/
756758 4101,
diff -r bcaefb769725 -r 6ed31017c303 src/vim9compile.c
--- a/src/vim9compile.c Sat Jan 15 22:15:03 2022 +0100
+++ b/src/vim9compile.c Sat Jan 15 22:45:03 2022 +0100
@@ -2256,12 +2256,17 @@
22562256 case VAR_VOID:
22572257 case VAR_INSTR:
22582258 case VAR_SPECIAL: // cannot happen
2259- // This is skipped for local variables, they are
2260- // always initialized to zero.
2261- if (lhs.lhs_dest == dest_local)
2259+ // This is skipped for local variables, they are always
2260+ // initialized to zero. But in a "for" or "while" loop
2261+ // the value may have been changed.
2262+ if (lhs.lhs_dest == dest_local
2263+ && !inside_loop_scope(cctx))
22622264 skip_store = TRUE;
22632265 else
2266+ {
2267+ instr_count = instr->ga_len;
22642268 generate_PUSHNR(cctx, 0);
2269+ }
22652270 break;
22662271 }
22672272 }
diff -r bcaefb769725 -r 6ed31017c303 src/vim9instr.c
--- a/src/vim9instr.c Sat Jan 15 22:15:03 2022 +0100
+++ b/src/vim9instr.c Sat Jan 15 22:45:03 2022 +0100
@@ -1845,6 +1845,25 @@
18451845 return FAIL;
18461846 }
18471847
1848+/*
1849+ * Return TRUE when inside a "for" or "while" loop.
1850+ */
1851+ int
1852+inside_loop_scope(cctx_T *cctx)
1853+{
1854+ scope_T *scope = cctx->ctx_scope;
1855+
1856+ for (;;)
1857+ {
1858+ if (scope == NULL)
1859+ break;
1860+ if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
1861+ return TRUE;
1862+ scope = scope->se_outer;
1863+ }
1864+ return FALSE;
1865+}
1866+
18481867 int
18491868 generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl)
18501869 {
@@ -1869,8 +1888,9 @@
18691888 varnumber_T val = isn->isn_arg.number;
18701889 garray_T *stack = &cctx->ctx_type_stack;
18711890
1872- if (val == 0 && is_decl)
1891+ if (val == 0 && is_decl && !inside_loop_scope(cctx))
18731892 {
1893+ // zero is the default value, no need to do anything
18741894 --instr->ga_len;
18751895 }
18761896 else
Afficher sur ancien navigateur de dépôt.