Mirror of the Vim source from https://github.com/vim/vim
Révision | 6ed31017c3033513aa55952bc06aa995e960681a (tree) |
---|---|
l'heure | 2022-01-16 06:45:03 |
Auteur | Bram Moolenaar <Bram@vim....> |
Commiter | Bram Moolenaar |
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
@@ -63,6 +63,7 @@ | ||
63 | 63 | int generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod); |
64 | 64 | int generate_undo_cmdmods(cctx_T *cctx); |
65 | 65 | 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); | |
66 | 67 | int generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl); |
67 | 68 | void may_generate_prof_end(cctx_T *cctx, int prof_lnum); |
68 | 69 | void delete_instr(isn_T *isn); |
@@ -587,6 +587,41 @@ | ||
587 | 587 | CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2) |
588 | 588 | enddef |
589 | 589 | |
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 | + | |
590 | 625 | def Test_extend_list() |
591 | 626 | var lines =<< trim END |
592 | 627 | var l1: list<number> |
@@ -751,6 +751,8 @@ | ||
751 | 751 | static int included_patches[] = |
752 | 752 | { /* Add new patch number below this line */ |
753 | 753 | /**/ |
754 | + 4103, | |
755 | +/**/ | |
754 | 756 | 4102, |
755 | 757 | /**/ |
756 | 758 | 4101, |
@@ -2256,12 +2256,17 @@ | ||
2256 | 2256 | case VAR_VOID: |
2257 | 2257 | case VAR_INSTR: |
2258 | 2258 | 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)) | |
2262 | 2264 | skip_store = TRUE; |
2263 | 2265 | else |
2266 | + { | |
2267 | + instr_count = instr->ga_len; | |
2264 | 2268 | generate_PUSHNR(cctx, 0); |
2269 | + } | |
2265 | 2270 | break; |
2266 | 2271 | } |
2267 | 2272 | } |
@@ -1845,6 +1845,25 @@ | ||
1845 | 1845 | return FAIL; |
1846 | 1846 | } |
1847 | 1847 | |
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 | + | |
1848 | 1867 | int |
1849 | 1868 | generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl) |
1850 | 1869 | { |
@@ -1869,8 +1888,9 @@ | ||
1869 | 1888 | varnumber_T val = isn->isn_arg.number; |
1870 | 1889 | garray_T *stack = &cctx->ctx_type_stack; |
1871 | 1890 | |
1872 | - if (val == 0 && is_decl) | |
1891 | + if (val == 0 && is_decl && !inside_loop_scope(cctx)) | |
1873 | 1892 | { |
1893 | + // zero is the default value, no need to do anything | |
1874 | 1894 | --instr->ga_len; |
1875 | 1895 | } |
1876 | 1896 | else |