diff --git a/releasenotes.md b/releasenotes.md index dce6f3ef4..a342fe78c 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -56,6 +56,7 @@ - Fix vector float -> bool conversion. - Fix `+a = 1` erronously being accepted. - Fix not freeing a zero length String +- Macros with trailing bodys aren't allowed as the single statement after a while loop with no body #1772. ### Stdlib changes - Increase BitWriter.write_bits limit up to 32 bits. diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index ef464215b..b2bfc03a4 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -590,7 +590,7 @@ static inline Ast* parse_while_stmt(ParseContext *c) CONSUME_OR_RET(TOKEN_RPAREN, poisoned_ast); unsigned row = c->prev_span.row; ASSIGN_AST_OR_RET(Ast *body, parse_stmt(c), poisoned_ast); - if (body->ast_kind != AST_COMPOUND_STMT && row != c->prev_span.row) + if (body->ast_kind != AST_COMPOUND_STMT && row != body->span.row) { PRINT_ERROR_AT(body, "A single statement after 'while' must be placed on the same line, or be enclosed in {}."); return poisoned_ast; @@ -1465,8 +1465,11 @@ Ast *parse_stmt(ParseContext *c) advance(c); return poisoned_ast; case TOKEN_EOS: + { + Ast *nop = ast_new_curr(c, AST_NOP_STMT); advance(c); - return ast_new_curr(c, AST_NOP_STMT); + return nop; + } case TOKEN_EOF: PRINT_ERROR_HERE("Reached the end of the file when expecting a statement."); return poisoned_ast; diff --git a/test/test_suite/statements/while_statement_placement2.c3 b/test/test_suite/statements/while_statement_placement2.c3 new file mode 100644 index 000000000..c53d6086f --- /dev/null +++ b/test/test_suite/statements/while_statement_placement2.c3 @@ -0,0 +1,34 @@ +import std; + +fn void loop_start() => io::printn("Loop Start"); +fn void loop_end() => io::printn("Loop End"); +fn void do_something() => io::printn("Do something"); + +macro @thing(; @body()) +{ + loop_start(); + @body(); + loop_end(); +} + +fn void strcpy(char *s1, char *s2) { + while (*s1++ = *s2++); +} + +fn void main() +{ + while (true) @thing() + { + do_something(); + break; + }; + for (;;) @thing() + { + do_something(); + break; + }; + if (true) @thing() + { + do_something(); + }; +} \ No newline at end of file