summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-08-05 14:34:14 +0200
committerBram Moolenaar <Bram@vim.org>2020-08-05 14:34:14 +0200
commitf9b2b49663226235f94f08230fe9023caf80a6e9 (patch)
treef34be82de9372deb871b09a572157d7dcfefed6e
parentfdac71c5075062f97f77044e9619fa5c907e0327 (diff)
patch 8.2.1373: Vim9: no error for assigning to non-existing script varv8.2.1373
Problem: Vim9: no error for assigning to non-existing script var. Solution: Check that in Vim9 script the variable was defined. (closes #6630)
-rw-r--r--src/structs.h4
-rw-r--r--src/testdir/test_vim9_script.vim9
-rw-r--r--src/userfunc.c1
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c88
5 files changed, 68 insertions, 36 deletions
diff --git a/src/structs.h b/src/structs.h
index 7e34d80998..a80de6a71f 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1594,7 +1594,9 @@ typedef struct
int uf_tml_execed; // line being timed was executed
# endif
sctx_T uf_script_ctx; // SCTX where function was defined,
- // used for s: variables
+ // used for s: variables; sc_version changed
+ // for :function
+ int uf_script_ctx_version; // original sc_version of SCTX
int uf_refcount; // reference count, see func_name_refcount()
funccall_T *uf_scoped; // l: local variables for closure
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 64ac3bbd92..f99333c0cb 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -112,6 +112,15 @@ def Test_assignment()
call CheckDefFailure(['let s:var = 123'], 'E1101:')
call CheckDefFailure(['let s:var: number'], 'E1101:')
+ lines =<< trim END
+ vim9script
+ def SomeFunc()
+ s:var = 123
+ enddef
+ defcompile
+ END
+ call CheckScriptFailure(lines, 'E1089:')
+
g:inc_counter += 1
assert_equal(2, g:inc_counter)
diff --git a/src/userfunc.c b/src/userfunc.c
index 43aa146a98..684a805d8a 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -3508,6 +3508,7 @@ def_function(exarg_T *eap, char_u *name_arg)
fp->uf_calls = 0;
fp->uf_cleared = FALSE;
fp->uf_script_ctx = current_sctx;
+ fp->uf_script_ctx_version = current_sctx.sc_version;
fp->uf_script_ctx.sc_lnum += sourcing_lnum_top;
if (is_export)
{
diff --git a/src/version.c b/src/version.c
index 1e23a08ad6..7b1b8d8c21 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1373,
+/**/
1372,
/**/
1371,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index f8381d7837..dc10b4851b 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -148,6 +148,7 @@ static char e_syntax_at[] = N_("E1002: Syntax error at %s");
static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
static char e_cannot_use_void[] = N_("E1031: Cannot use void value");
static char e_namespace[] = N_("E1075: Namespace not supported: %s");
+static char e_unknown_var[] = N_("E1089: unknown variable: %s");
static void delete_def_function_contents(dfunc_T *dfunc);
static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
@@ -5335,7 +5336,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
else
{
int idx;
- imported_T *import = NULL;
for (idx = 0; reserved[idx] != NULL; ++idx)
if (STRCMP(reserved[idx], name) == 0)
@@ -5374,49 +5374,67 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
goto theend;
}
}
- else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)
- || lookup_script(var_start, varlen) == OK
- || (import = find_imported(var_start, varlen, cctx))
- != NULL)
+ else
{
- char_u *rawname = name + (name[1] == ':' ? 2 : 0);
-
- if (is_decl)
+ int script_namespace = varlen > 1
+ && STRNCMP(var_start, "s:", 2) == 0;
+ int script_var = (script_namespace
+ ? lookup_script(var_start + 2, varlen - 2)
+ : lookup_script(var_start, varlen)) == OK;
+ imported_T *import =
+ find_imported(var_start, varlen, cctx);
+
+ if (script_namespace || script_var || import != NULL)
{
- if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0))
- semsg(_("E1101: Cannot declare a script variable in a function: %s"),
+ char_u *rawname = name + (name[1] == ':' ? 2 : 0);
+
+ if (is_decl)
+ {
+ if (script_namespace)
+ semsg(_("E1101: Cannot declare a script variable in a function: %s"),
name);
- else
- semsg(_("E1054: Variable already declared in the script: %s"),
+ else
+ semsg(_("E1054: Variable already declared in the script: %s"),
name);
- goto theend;
- }
- dest = dest_script;
+ goto theend;
+ }
+ else if (cctx->ctx_ufunc->uf_script_ctx_version
+ == SCRIPT_VERSION_VIM9
+ && script_namespace
+ && !script_var && import == NULL)
+ {
+ semsg(_(e_unknown_var), name);
+ goto theend;
+ }
+
+ dest = dest_script;
- // existing script-local variables should have a type
- scriptvar_sid = current_sctx.sc_sid;
- if (import != NULL)
- scriptvar_sid = import->imp_sid;
- scriptvar_idx = get_script_item_idx(scriptvar_sid,
+ // existing script-local variables should have a type
+ scriptvar_sid = current_sctx.sc_sid;
+ if (import != NULL)
+ scriptvar_sid = import->imp_sid;
+ scriptvar_idx = get_script_item_idx(scriptvar_sid,
rawname, TRUE);
- if (scriptvar_idx >= 0)
- {
- scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
- svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
+ if (scriptvar_idx >= 0)
+ {
+ scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid);
+ svar_T *sv =
+ ((svar_T *)si->sn_var_vals.ga_data)
+ scriptvar_idx;
- type = sv->sv_type;
+ type = sv->sv_type;
+ }
}
- }
- else if (name[1] == ':' && name[2] != NUL)
- {
- semsg(_("E1082: Cannot use a namespaced variable: %s"),
+ else if (name[1] == ':' && name[2] != NUL)
+ {
+ semsg(_("E1082: Cannot use a namespaced variable: %s"),
name);
- goto theend;
- }
- else if (!is_decl)
- {
- semsg(_("E1089: unknown variable: %s"), name);
- goto theend;
+ goto theend;
+ }
+ else if (!is_decl)
+ {
+ semsg(_(e_unknown_var), name);
+ goto theend;
+ }
}
}