Improve parser errors for statements at global scope (#20871)

This commit is contained in:
Dennis 2025-02-15 23:50:34 +01:00 committed by GitHub
parent e85bc5f16e
commit 4b57724c91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 75 additions and 19 deletions

View file

@ -1041,6 +1041,30 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
nextToken();
continue;
// The following are all errors, the cases are just for better error messages than the default case
case TOK.return_:
case TOK.goto_:
case TOK.break_:
case TOK.continue_:
error("`%s` statement must be inside function scope", token.toChars());
goto Lerror;
case TOK.asm_:
case TOK.do_:
case TOK.for_:
case TOK.foreach_:
case TOK.foreach_reverse_:
case TOK.if_:
case TOK.switch_:
case TOK.try_:
case TOK.while_:
error("`%s` statement must be inside function scope", token.toChars());
if (peekNext() == TOK.leftParenthesis || peekNext() == TOK.leftCurly)
{
parseStatement(0);
s = null;
continue;
}
goto Lerror;
default:
error("declaration expected, not `%s`", token.toChars());
Lerror:
@ -1504,28 +1528,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value != TOK.identifier)
{
error("identifier expected following `template`");
goto Lerr;
return null;
}
id = token.ident;
nextToken();
tpl = parseTemplateParameterList();
if (!tpl)
goto Lerr;
return null;
constraint = parseConstraint();
if (token.value != TOK.leftCurly)
{
error("`{` expected after template parameter list, not `%s`", token.toChars()); /* } */
goto Lerr;
nextToken();
return null;
}
decldefs = parseBlock(null);
tempdecl = new AST.TemplateDeclaration(loc, id, tpl, constraint, decldefs, ismixin);
return tempdecl;
Lerr:
return null;
}
/******************************************
@ -4571,6 +4593,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
default:
error("semicolon expected to close `alias` declaration, not `%s`", token.toChars());
nextToken();
break;
}
}
@ -5016,6 +5039,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
default:
error("semicolon expected to close `alias` declaration, not `%s`", token.toChars());
nextToken();
break;
}
break;
@ -5356,9 +5380,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
error("template constraint must follow parameter lists and attributes");
else
error("cannot use function constraints for non-template functions. Use `static if` instead");
parseConstraint();
}
else
{
error("semicolon expected following function declaration, not `%s`", token.toChars());
nextToken();
}
}
break;
}

View file

@ -0,0 +1,26 @@
/**
TEST_OUTPUT:
---
fail_compilation/code_global_scope.d(18): Error: `switch` statement must be inside function scope
fail_compilation/code_global_scope.d(19): Error: `do` statement must be inside function scope
fail_compilation/code_global_scope.d(20): Error: `foreach` statement must be inside function scope
fail_compilation/code_global_scope.d(21): Error: `while` statement must be inside function scope
fail_compilation/code_global_scope.d(22): Error: `if` statement must be inside function scope
fail_compilation/code_global_scope.d(23): Error: `return` statement must be inside function scope
fail_compilation/code_global_scope.d(24): Error: `goto` statement must be inside function scope
fail_compilation/code_global_scope.d(25): Error: `continue` statement must be inside function scope
fail_compilation/code_global_scope.d(26): Error: `break` statement must be inside function scope
---
*/
switch s;
do d;
foreach (i; 0 .. 4) {}
while (x) {}
if (y) {}
return 0;
goto A;
continue B;
break;

View file

@ -4,7 +4,7 @@ TEST_OUTPUT:
fail_compilation/diag_template_alias.d(1): Error: identifier expected for template `alias` parameter
fail_compilation/diag_template_alias.d(1): Error: found `alias` when expecting `(`
fail_compilation/diag_template_alias.d(1): Error: semicolon expected following function declaration, not `(`
fail_compilation/diag_template_alias.d(1): Error: declaration expected, not `(`
fail_compilation/diag_template_alias.d(1): Error: declaration expected, not `)`
---
*/
#line 1

View file

@ -4,7 +4,7 @@ TEST_OUTPUT:
fail_compilation/diag_template_this.d(1): Error: identifier expected for template `this` parameter
fail_compilation/diag_template_this.d(1): Error: found `this` when expecting `(`
fail_compilation/diag_template_this.d(1): Error: semicolon expected following function declaration, not `(`
fail_compilation/diag_template_this.d(1): Error: declaration expected, not `(`
fail_compilation/diag_template_this.d(1): Error: declaration expected, not `)`
---
*/
#line 1

View file

@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/fail17570.d(12): Error: cannot use function constraints for non-template functions. Use `static if` instead
fail_compilation/fail17570.d(12): Error: declaration expected, not `if`
fail_compilation/fail17570.d(13): Error: declaration expected, not `{`
fail_compilation/fail17570.d(15): Error: `}` expected following members in `struct` declaration
fail_compilation/fail17570.d(11): struct `S` starts here
---

View file

@ -2,9 +2,9 @@
TEST_OUTPUT:
---
fail_compilation/fnconstraint.d(14): Error: template constraint must follow parameter lists and attributes
fail_compilation/fnconstraint.d(14): Error: declaration expected, not `if`
fail_compilation/fnconstraint.d(15): Error: declaration expected, not `{`
fail_compilation/fnconstraint.d(23): Error: template constraint must follow parameter lists and attributes
fail_compilation/fnconstraint.d(23): Error: declaration expected, not `if`
fail_compilation/fnconstraint.d(23): Error: declaration expected, not `{`
fail_compilation/fnconstraint.d(27): Error: `}` expected following members in `struct` declaration
fail_compilation/fnconstraint.d(19): struct `S` starts here
---

View file

@ -1,10 +1,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/issue16020.d(13): Error: user-defined attributes not allowed for `alias` declarations
fail_compilation/issue16020.d(14): Error: semicolon expected to close `alias` declaration, not `(`
fail_compilation/issue16020.d(14): Error: declaration expected, not `(`
fail_compilation/issue16020.d(15): Deprecation: storage class `final` has no effect in type aliases
fail_compilation/issue16020.d(14): Error: user-defined attributes not allowed for `alias` declarations
fail_compilation/issue16020.d(15): Error: semicolon expected to close `alias` declaration, not `(`
fail_compilation/issue16020.d(15): Error: semicolon needed to end declaration of `t` instead of `)`
fail_compilation/issue16020.d(15): Error: declaration expected, not `)`
fail_compilation/issue16020.d(16): Deprecation: storage class `final` has no effect in type aliases
---
*/
module issue16020;

View file

@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/template_decl.d(8): Error: `{` expected after template parameter list, not `(`
fail_compilation/template_decl.d(8): Error: declaration expected, not `(`
fail_compilation/template_decl.d(8): Error: declaration expected, not `)`
---
*/
template b(alias d)() {

View file

@ -15,19 +15,19 @@ fail_compilation/udaparams.d(45): Error: `@nogc` attribute for function paramete
fail_compilation/udaparams.d(51): Error: cannot put a storage-class in an `alias` declaration.
fail_compilation/udaparams.d(52): Error: cannot put a storage-class in an `alias` declaration.
fail_compilation/udaparams.d(53): Error: semicolon expected to close `alias` declaration, not `=>`
fail_compilation/udaparams.d(53): Error: declaration expected, not `=>`
fail_compilation/udaparams.d(53): Error: declaration expected, not `1`
fail_compilation/udaparams.d(54): Error: semicolon expected to close `alias` declaration, not `=>`
fail_compilation/udaparams.d(54): Error: declaration expected, not `=>`
fail_compilation/udaparams.d(54): Error: declaration expected, not `1`
fail_compilation/udaparams.d(57): Error: basic type expected, not `@`
fail_compilation/udaparams.d(57): Error: identifier expected for template value parameter
fail_compilation/udaparams.d(57): Error: found `@` when expecting `)`
fail_compilation/udaparams.d(57): Error: basic type expected, not `3`
fail_compilation/udaparams.d(57): Error: found `3` when expecting `)`
fail_compilation/udaparams.d(57): Error: semicolon expected following function declaration, not `)`
fail_compilation/udaparams.d(57): Error: no identifier for declarator `T`
fail_compilation/udaparams.d(57): Error: declaration expected, not `)`
---
*/
void vararg1(int a, @(10) ...);
extern(C) void vararg2(int a, @(10) ...);