diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-01-15 21:44:44 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-01-15 21:44:44 +0000 |
commit | 38ecd9722664049d636f4fba759b3ebbfd34e97d (patch) | |
tree | 9c21a2fbb6312962d1531bc721fa5253eedbd7ca | |
parent | 857c8bb1bbe754cf2c5b709703d2eb848c800285 (diff) | |
download | vim-git-38ecd9722664049d636f4fba759b3ebbfd34e97d.tar.gz |
patch 8.2.4103: Vim9: variable declared in for loop not initialzedv8.2.4103
Problem: Vim9: variable declared in for loop not initialzed.
Solution: Always initialze the variable. (closes #9535)
-rw-r--r-- | src/proto/vim9instr.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_vim9_assign.vim | 35 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 11 | ||||
-rw-r--r-- | src/vim9instr.c | 22 |
5 files changed, 67 insertions, 4 deletions
diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro index c9455003e..04ac89c7a 100644 --- a/src/proto/vim9instr.pro +++ b/src/proto/vim9instr.pro @@ -63,6 +63,7 @@ int generate_UNPACK(cctx_T *cctx, int var_count, int semicolon); int generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod); int generate_undo_cmdmods(cctx_T *cctx); 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); +int inside_loop_scope(cctx_T *cctx); int generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl); void may_generate_prof_end(cctx_T *cctx, int prof_lnum); void delete_instr(isn_T *isn); diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 80ee6b71f..7f4d87ab3 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -587,6 +587,41 @@ def Test_assign_index() CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2) enddef +def Test_init_in_for_loop() + var lines =<< trim END + var l: list<number> = [] + for i in [3, 4] + var n: number + add(l, n) + n = 123 + endfor + assert_equal([0, 0], l) + END + CheckDefAndScriptSuccess(lines) + + lines =<< trim END + var l: list<number> = [] + for i in [3, 4] + var n: number = 0 + add(l, n) + n = 123 + endfor + assert_equal([0, 0], l) + END + CheckDefAndScriptSuccess(lines) + + lines =<< trim END + var l: list<number> = [] + for i in [3, 4] + var n: number = 3 + add(l, n) + n = 123 + endfor + assert_equal([3, 3], l) + END + CheckDefAndScriptSuccess(lines) +enddef + def Test_extend_list() var lines =<< trim END var l1: list<number> diff --git a/src/version.c b/src/version.c index dd97a716e..d0d9b623b 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4103, +/**/ 4102, /**/ 4101, diff --git a/src/vim9compile.c b/src/vim9compile.c index afc788543..89520f93b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2256,12 +2256,17 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) case VAR_VOID: case VAR_INSTR: case VAR_SPECIAL: // cannot happen - // This is skipped for local variables, they are - // always initialized to zero. - if (lhs.lhs_dest == dest_local) + // This is skipped for local variables, they are always + // initialized to zero. But in a "for" or "while" loop + // the value may have been changed. + if (lhs.lhs_dest == dest_local + && !inside_loop_scope(cctx)) skip_store = TRUE; else + { + instr_count = instr->ga_len; generate_PUSHNR(cctx, 0); + } break; } } diff --git a/src/vim9instr.c b/src/vim9instr.c index 50572978a..493683acb 100644 --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -1845,6 +1845,25 @@ generate_store_var( return FAIL; } +/* + * Return TRUE when inside a "for" or "while" loop. + */ + int +inside_loop_scope(cctx_T *cctx) +{ + scope_T *scope = cctx->ctx_scope; + + for (;;) + { + if (scope == NULL) + break; + if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE) + return TRUE; + scope = scope->se_outer; + } + return FALSE; +} + int generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl) { @@ -1869,8 +1888,9 @@ generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl) varnumber_T val = isn->isn_arg.number; garray_T *stack = &cctx->ctx_type_stack; - if (val == 0 && is_decl) + if (val == 0 && is_decl && !inside_loop_scope(cctx)) { + // zero is the default value, no need to do anything --instr->ga_len; } else |