[PATCH 0/2] MR10965: vbscript: Check top-level name redefinition against global scope only.
A local Dim or Const may shadow a global Sub, Function, or Class name, and a Class name does not collide with a local declaration of another procedure. A global Dim and a global Sub of the same name still clash. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10965
From: Francis De Brabandere <francisdb@gmail.com> A local Dim or Const may shadow a global Sub, Function, or Class name, and a Class name does not collide with a local declaration of another procedure. A global Dim and a global Sub of the same name still clash. --- dlls/vbscript/tests/run.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index c9fd66588a5..c6a012d8bcf 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2965,6 +2965,12 @@ static void test_parse_errors(void) 1, 4, NULL, S_OK, 1041 }, + { + /* A global Sub collides with a global Dim of the same name - error 1041 */ + L"Dim s\nSub S\nEnd Sub\n", + 1, 4, + NULL, S_OK, 1041 + }, { /* Expected identifier - error 1010 */ L"Dim If\n", @@ -3514,6 +3520,28 @@ static void test_parse_errors(void) error_source_line = NULL; } +static void test_redefine_scope(void) +{ + static const WCHAR *valid[] = { + /* a local Dim may shadow a global Sub */ + L"Sub S\nEnd Sub\nSub Other\nDim s\nEnd Sub\n", + /* a local Const may shadow a global Sub */ + L"Sub S\nEnd Sub\nSub Other\nConst s = 1\nEnd Sub\n", + /* a Class name does not collide with a local Dim of another Sub */ + L"Class S\nEnd Class\nSub Other\nDim s\nEnd Sub\n", + L"Sub Other\nDim s\nEnd Sub\nClass S\nEnd Class\n", + }; + HRESULT hres; + unsigned i; + + for (i = 0; i < ARRAY_SIZE(valid); i++) { + SET_EXPECT(OnScriptError); + hres = parse_script_wr(valid[i]); + todo_wine ok(hres == S_OK, "[%u] parse returned %08lx\n", i, hres); + CLEAR_CALLED(OnScriptError); + } +} + static void test_msgbox(void) { HRESULT hres; @@ -4210,6 +4238,7 @@ static void run_tests(void) test_isexpression(); test_option_explicit_errors(); test_parse_errors(); + test_redefine_scope(); test_parse_context(); test_callbacks(); test_multiple_parse(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10965
From: Francis De Brabandere <francisdb@gmail.com> compile_func() reuses ctx.dim_decls and ctx.const_decls to hold each function's local declarations, so by the time a Sub, Function, or Class name was checked for redefinition it was compared against whatever locals the previously compiled procedure left behind, wrongly rejecting valid code such as a local Dim that shadows a global Sub. Restore the global declaration lists before each top-level check, and gate the Const-vs-Sub check on global scope as the Dim path already does. --- dlls/vbscript/compile.c | 12 +++++++++++- dlls/vbscript/tests/run.c | 4 +--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c index 940703762f5..8aef25f21b1 100644 --- a/dlls/vbscript/compile.c +++ b/dlls/vbscript/compile.c @@ -1398,7 +1398,7 @@ static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *st } } - if(lookup_func_decls(ctx, decl->name)) { + if(ctx->func->type == FUNC_GLOBAL && lookup_func_decls(ctx, decl->name)) { ctx->loc = decl->loc; WARN("%s redefined\n", debugstr_w(decl->name)); return MAKE_VBSERROR(VBSE_NAME_REDEFINED); @@ -2355,6 +2355,7 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item function_decl_t *func_decl; named_item_t *item = NULL; class_decl_t *class_decl; + dim_decl_t *global_dims; function_t *new_func; compile_ctx_t ctx; vbscode_t *code; @@ -2399,8 +2400,15 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item ctx.global_consts = ctx.const_decls; code->option_explicit = ctx.parser.option_explicit; + /* compile_func() repurposes ctx.dim_decls and ctx.const_decls for each + function's locals, so capture the global dims now and restore the global + scope before each top-level redefinition check: a function or class name + collides only with a global Dim/Const, not another function's local one. */ + global_dims = ctx.dim_decls; for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) { + ctx.dim_decls = global_dims; + ctx.const_decls = ctx.global_consts; hres = create_function(&ctx, func_decl, &new_func); if(FAILED(hres)) { hres = compile_error(script, &ctx, hres); @@ -2413,6 +2421,8 @@ HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *item } for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) { + ctx.dim_decls = global_dims; + ctx.const_decls = ctx.global_consts; hres = compile_class(&ctx, class_decl); if(FAILED(hres)) { hres = compile_error(script, &ctx, hres); diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index c6a012d8bcf..decde599d0c 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -3535,10 +3535,8 @@ static void test_redefine_scope(void) unsigned i; for (i = 0; i < ARRAY_SIZE(valid); i++) { - SET_EXPECT(OnScriptError); hres = parse_script_wr(valid[i]); - todo_wine ok(hres == S_OK, "[%u] parse returned %08lx\n", i, hres); - CLEAR_CALLED(OnScriptError); + ok(hres == S_OK, "[%u] parse returned %08lx\n", i, hres); } } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10965
This merge request was approved by Jacek Caban. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10965
participants (3)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb) -
Jacek Caban (@jacek)