From: Francis De Brabandere <francisdb@gmail.com> Windows VBScript rejects member expressions (e.g. x.y) as For/For Each loop control variables with error 1040. Accept MemberExpression in the parser rules and check for obj_expr to report the proper error instead of a generic syntax error. --- dlls/vbscript/parser.y | 13 +++++++++---- dlls/vbscript/tests/run.c | 12 ++++++++++++ dlls/vbscript/vbscript.rc | 1 + dlls/vbscript/vbscript_defs.h | 1 + 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index e716bf98d3a..8f51f902a72 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -252,10 +252,15 @@ SimpleStatement | tON tERROR tRESUME tNEXT { $$ = new_onerror_statement(ctx, @$, TRUE); CHECK_ERROR; } | tON tERROR tGOTO '0' { $$ = new_onerror_statement(ctx, @$, FALSE); CHECK_ERROR; } | tCONST ConstDeclList { $$ = new_const_statement(ctx, @$, $2); CHECK_ERROR; } - | tFOR Identifier '=' Expression tTO Expression Step_opt StSep StatementsNl_opt tNEXT - { $$ = new_forto_statement(ctx, @$, $2, $4, $6, $7, $9); CHECK_ERROR; } - | tFOR tEACH Identifier tIN Expression StSep StatementsNl_opt tNEXT - { $$ = new_foreach_statement(ctx, @$, $3, $5, $7); } + | tFOR MemberExpression '=' Expression tTO Expression Step_opt StSep StatementsNl_opt tNEXT + { if($2->obj_expr) { ctx->error_loc = @3; + ctx->hres = MAKE_VBSERROR(VBSE_INVALID_FOR_CONTROL); CHECK_ERROR; } + $$ = new_forto_statement(ctx, @$, $2->identifier, $4, $6, $7, $9); + CHECK_ERROR; } + | tFOR tEACH MemberExpression tIN Expression StSep StatementsNl_opt tNEXT + { if($3->obj_expr) { ctx->error_loc = @4; + ctx->hres = MAKE_VBSERROR(VBSE_INVALID_FOR_CONTROL); CHECK_ERROR; } + $$ = new_foreach_statement(ctx, @$, $3->identifier, $5, $7); } | tSELECT tCASE Expression StSep CaseClausules tEND tSELECT { $$ = new_select_statement(ctx, @$, $3, $5); } | tSELECT tCASE Expression StSep CaseClausules tEND error diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index bc09f7a96c0..3a4081bc83b 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -3257,6 +3257,18 @@ static void test_parse_errors(void) "End Class\n", -4, -20, NULL, S_OK, 1051 + }, + { + /* Invalid 'for' loop control variable (member expression) - error 1040 */ + L"Dim x\nFor x.y = 1 To 3\nNext\n", + 1, 8, + NULL, S_OK, 1040 + }, + { + /* Invalid 'for each' loop control variable (member expression) - error 1040 */ + L"Dim x\nFor Each x.y In Array(1)\nNext\n", + 1, 13, + NULL, S_OK, 1040 } }; HRESULT hres; diff --git a/dlls/vbscript/vbscript.rc b/dlls/vbscript/vbscript.rc index 73aedb4dcaf..bc1d886d63f 100644 --- a/dlls/vbscript/vbscript.rc +++ b/dlls/vbscript/vbscript.rc @@ -93,6 +93,7 @@ STRINGTABLE VBSE_INVALID_USE_OF_ME "Invalid use of 'Me' keyword" VBSE_LOOP_WITHOUT_DO "'loop' without 'do'" VBSE_INVALID_EXIT "Invalid 'exit' statement" + VBSE_INVALID_FOR_CONTROL "Invalid 'for' loop control variable" VBSE_NAME_REDEFINED "Name redefined" VBSE_MUST_BE_FIRST_STATEMENT "Must be first statement on the line" VBSE_CANNOT_USE_PARENS_CALLING_SUB "Cannot use parentheses when calling a Sub" diff --git a/dlls/vbscript/vbscript_defs.h b/dlls/vbscript/vbscript_defs.h index 200e1ac4929..7debe737074 100644 --- a/dlls/vbscript/vbscript_defs.h +++ b/dlls/vbscript/vbscript_defs.h @@ -304,6 +304,7 @@ #define VBSE_INVALID_USE_OF_ME 1037 #define VBSE_LOOP_WITHOUT_DO 1038 #define VBSE_INVALID_EXIT 1039 +#define VBSE_INVALID_FOR_CONTROL 1040 #define VBSE_NAME_REDEFINED 1041 #define VBSE_MUST_BE_FIRST_STATEMENT 1042 #define VBSE_CANNOT_USE_PARENS_CALLING_SUB 1044 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10484