diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index a2c364e7e1..f9daecd580 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d @@ -5331,6 +5331,33 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer error(loc, "instead of C-style syntax, use D-style `%s%s%s`", t.toChars(), sp, s); } + /***************************** + * Ad-hoc error message for missing or extra parens that close a condition. + * Params: + * start = "if", "while", etc. Must be 0 terminated. + * param = if the condition is a declaration, this will be non-null + * condition = if param is null, then this is the conditional Expression. If condition is null, + * then an error in the condition was already reported. + */ + private void closeCondition(string start, AST.Parameter param, AST.Expression condition) + { + string format; + if (token.value != TOK.rightParenthesis && condition) + { + format = "missing closing `)` after `%s (%s`"; + } + else + check(TOK.rightParenthesis); + if (token.value == TOK.rightParenthesis) + { + if (condition) // if not an error in condition + format = "extra `)` after `%s (%s)`"; + nextToken(); + } + if (format) + error(format.ptr, start.ptr, param ? "declaration".ptr : condition.toChars()); + } + /***************************************** * Parses `foreach` statements, `static foreach` statements and * `static foreach` declarations. @@ -5961,12 +5988,12 @@ LagainStc: } case TOK.while_: { - AST.Parameter param = null; nextToken(); check(TOK.leftParenthesis); - param = parseAssignCondition(); - AST.Expression condition = parseExpression(); - check(TOK.rightParenthesis); + auto param = parseAssignCondition(); + auto condition = parseExpression(); + closeCondition("while", param, condition); + Loc endloc; AST.Statement _body = parseStatement(ParseStatementFlags.scope_, null, &endloc); s = new AST.WhileStatement(loc, condition, _body, endloc, param); @@ -5987,7 +6014,6 @@ LagainStc: case TOK.do_: { AST.Statement _body; - AST.Expression condition; nextToken(); const lookingForElseSave = lookingForElse; @@ -5996,8 +6022,8 @@ LagainStc: lookingForElse = lookingForElseSave; check(TOK.while_); check(TOK.leftParenthesis); - condition = parseExpression(); - check(TOK.rightParenthesis); + auto condition = parseExpression(); + closeCondition("do .. while", null, condition); if (token.value == TOK.semicolon) nextToken(); else @@ -6058,25 +6084,11 @@ LagainStc: } case TOK.if_: { - AST.Parameter param = null; - AST.Expression condition; - nextToken(); check(TOK.leftParenthesis); - param = parseAssignCondition(); - condition = parseExpression(); - if (token.value != TOK.rightParenthesis && condition) - { - error("missing closing `)` after `if (%s`", param ? "declaration".ptr : condition.toChars()); - } - else - check(TOK.rightParenthesis); - if (token.value == TOK.rightParenthesis) - { - if (condition) // if not an error in condition - error("extra `)` after `if (%s)`", param ? "declaration".ptr : condition.toChars()); - nextToken(); - } + auto param = parseAssignCondition(); + auto condition = parseExpression(); + closeCondition("if", param, condition); { const lookingForElseSave = lookingForElse; @@ -6223,7 +6235,7 @@ LagainStc: nextToken(); check(TOK.leftParenthesis); AST.Expression condition = parseExpression(); - check(TOK.rightParenthesis); + closeCondition("switch", null, condition); AST.Statement _body = parseStatement(ParseStatementFlags.scope_); s = new AST.SwitchStatement(loc, condition, _body, isfinal); break; @@ -6402,7 +6414,7 @@ LagainStc: { nextToken(); exp = parseExpression(); - check(TOK.rightParenthesis); + closeCondition("synchronized", null, exp); } else exp = null; @@ -6419,7 +6431,7 @@ LagainStc: nextToken(); check(TOK.leftParenthesis); exp = parseExpression(); - check(TOK.rightParenthesis); + closeCondition("with", null, exp); _body = parseStatement(ParseStatementFlags.scope_, null, &endloc); s = new AST.WithStatement(loc, exp, _body, endloc); break; diff --git a/compiler/test/fail_compilation/ice8795.d b/compiler/test/fail_compilation/ice8795.d index 5d7d6dd17a..a30a65b200 100644 --- a/compiler/test/fail_compilation/ice8795.d +++ b/compiler/test/fail_compilation/ice8795.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/ice8795.d-mixin-14(14): Error: found `End of File` when expecting `(` fail_compilation/ice8795.d-mixin-14(14): Error: expression expected, not `End of File` -fail_compilation/ice8795.d-mixin-14(14): Error: found `End of File` when expecting `)` +fail_compilation/ice8795.d-mixin-14(14): Error: missing closing `)` after `switch (0` fail_compilation/ice8795.d-mixin-14(14): Error: found `End of File` instead of statement fail_compilation/ice8795.d-mixin-15(15): Error: { } expected following `interface` declaration fail_compilation/ice8795.d-mixin-15(15): Error: anonymous interfaces not allowed