diff --git a/parser/c2_parser.c2 b/parser/c2_parser.c2 index 1a5a7b084..5ae698e93 100644 --- a/parser/c2_parser.c2 +++ b/parser/c2_parser.c2 @@ -226,11 +226,6 @@ fn Kind Parser.peekToken2(Parser* p, u32 n, Token* tok) { fn void Parser.consumeSemicolon(Parser* p, bool need_semi) { if (need_semi) { p.expectAndConsume(Semicolon); - } else { - if (p.tok.kind == Semicolon) { - p.diags.error(p.tok.loc, "no semicolon allowed after initializer list"); - p.consumeToken(); - } } } @@ -242,6 +237,14 @@ fn void Parser.expectAndConsume(Parser* p, Kind kind) { p.expectError(kind); } +fn void Parser.consumeRBrace(Parser* p, const char* context) { + p.expectAndConsume(RBrace); + if (p.tok.kind == Semicolon) { + p.diags.warn(p.tok.loc, "no semicolon allowed after %s", context); + p.consumeToken(); + } +} + fn void Parser.expect(Parser* p, Kind kind) { if (p.tok.kind == kind) return; @@ -377,7 +380,7 @@ fn void Parser.parseImports(Parser* p) { p.consumeToken(); } } - p.expectAndConsume(RBrace); + p.consumeRBrace("import list"); } else { p.expectAndConsume(Semicolon); } @@ -1103,7 +1106,7 @@ fn void Parser.parseExternDecl(Parser* p) { p.parseTopLevel(); } p.tokenizer.c_mode--; // must set before consuming the token - p.consumeToken(); + p.consumeRBrace("extern \"C\" block"); } else { p.parseTopLevel(); } diff --git a/parser/c2_parser_expr.c2 b/parser/c2_parser_expr.c2 index 2dc0e6292..5145a7696 100644 --- a/parser/c2_parser_expr.c2 +++ b/parser/c2_parser_expr.c2 @@ -617,7 +617,7 @@ fn Expr* Parser.parseInitList(Parser* p) { if (p.tok.kind == LBrace) p.expect(Comma); // always gives error SrcLoc endLoc = p.tok.loc; - p.expectAndConsume(RBrace); + p.consumeRBrace("initializer list"); Expr* e = (Expr*)p.builder.actOnInitList(loc, endLoc, values.getExprs(), values.size()); values.free(); return e; diff --git a/parser/c2_parser_stmt.c2 b/parser/c2_parser_stmt.c2 index 03e0113c0..9d374c75f 100644 --- a/parser/c2_parser_stmt.c2 +++ b/parser/c2_parser_stmt.c2 @@ -213,7 +213,7 @@ fn CompoundStmt* Parser.parseCompoundStmt(Parser* p) { } SrcLoc endLoc = p.tok.loc + 1; - p.expectAndConsume(RBrace); + p.consumeRBrace("block"); CompoundStmt* s = p.builder.actOnCompoundStmt(endLoc, stmts.getData(), stmts.size()); p.putStmtList(); diff --git a/parser/c2_parser_switch.c2 b/parser/c2_parser_switch.c2 index ae9613709..04a8ec94f 100644 --- a/parser/c2_parser_switch.c2 +++ b/parser/c2_parser_switch.c2 @@ -64,7 +64,7 @@ fn Stmt* Parser.parseSwitchStmt(Parser* p) { cases.add(c); } - p.expectAndConsume(RBrace); + p.consumeRBrace("switch block"); Stmt* s = p.builder.actOnSwitchStmt(loc, decl, cond, cases.getData(), cases.size(), has_default); cases.free(); diff --git a/parser/c2_parser_type.c2 b/parser/c2_parser_type.c2 index 670127cc9..54c8ca683 100644 --- a/parser/c2_parser_type.c2 +++ b/parser/c2_parser_type.c2 @@ -232,7 +232,7 @@ fn void Parser.parseStructBlock(Parser* p, DeclList* members, bool is_public) { p.expectAndConsume(Semicolon); } - p.expectAndConsume(RBrace); + p.consumeRBrace("struct definition"); } fn void Parser.parseEnumType(Parser* p, u32 name, SrcLoc loc, bool is_public) { @@ -334,7 +334,7 @@ fn void Parser.parseEnumType(Parser* p, u32 name, SrcLoc loc, bool is_public) { } } - p.expectAndConsume(RBrace); + p.consumeRBrace("enum definition"); EnumTypeDecl* d = p.builder.actOnEnumType(name, loc, diff --git a/test/parser/invalid_initlist.c2 b/test/parser/invalid_initlist.c2 index 9b0fcdd42..7b7f4854b 100644 --- a/test/parser/invalid_initlist.c2 +++ b/test/parser/invalid_initlist.c2 @@ -1,13 +1,13 @@ // @warnings{no-unused} module test; -u32[] a1 = {1, 2, 3}; // @error{no semicolon allowed after initializer list} +u32[] a1 = {1, 2, 3}; // @warning{no semicolon allowed after initializer list} u32[+] b; -a += {1, 2, 3}; // @error{no semicolon allowed after initializer list} +a += {1, 2, 3}; // @warning{no semicolon allowed after initializer list} fn void fn1() { - u32[] a = {1, 2, 3}; // @error{no semicolon allowed after initializer list} + u32[] a = {1, 2, 3}; // @warning{no semicolon allowed after initializer list} } public fn i32 main() {