From 6547ea47d66a4d382c9c2cfc317426d8a3a5734e Mon Sep 17 00:00:00 2001 From: "OpenCode[AI]" Date: Wed, 15 Apr 2026 20:56:01 -0700 Subject: [PATCH] No more ; needed --- AGENTS.md | 14 ++++++++++++++ tccgen.c | 22 +++++++++++++--------- tests/tests2/60_errors_and_warnings.expect | 2 +- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 25dc5c67..7d1b4f67 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,3 +38,17 @@ - Some tests need special flags (see `FLAGS =` assignments in `tests/tests2/Makefile`). - Bound-check tests (`-b` flag) are skipped when `CONFIG_bcheck=no`. - `.expect` files are generated with gcc by default; some use TCC (flagged with `GEN-TCC`). + +## Language Extension: Optional Semicolons + +Semicolons are optional after most statements and declarations: +- `return`, `break`, `continue`, `goto`, expression statements +- `do-while` trailing semicolon +- Variable declarations + +Semicolons are still **required** for: +- `for()` loop init/condition/increment sections (e.g., `for(i=0; ibsym = gjmp(*cur_scope->bsym); - skip(';'); + if (tok == ';') next(); } else if (t == TOK_CONTINUE) { /* compute jump */ @@ -7266,7 +7266,7 @@ again: tcc_error("cannot continue"); leave_scope(loop_scope); *cur_scope->csym = gjmp(*cur_scope->csym); - skip(';'); + if (tok == ';') next(); } else if (t == TOK_FOR) { new_scope(&o); @@ -7314,7 +7314,7 @@ again: gexpr(); c = gvtst(0, 0); skip(')'); - skip(';'); + if (tok == ';') next(); gsym_addr(c, d); gsym(a); prev_scope_s(&o); @@ -7426,7 +7426,7 @@ again: } else { expect("label identifier"); } - skip(';'); + if (tok == ';') next(); } else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) { asm_instr(); @@ -7481,7 +7481,7 @@ again: gexpr(); vpop(); } - skip(';'); + if (tok == ';') next(); } } } @@ -8637,7 +8637,7 @@ static void do_Static_assert(void) skip(')'); if (c == 0) tcc_error("%s", msg); - skip(';'); + if (tok == ';') next(); } #ifdef TCC_TARGET_PE @@ -8718,6 +8718,10 @@ static int decl(int l) return 1; next(); continue; + } else if (l != VT_JMP && l != VT_CMP) { + /* no semicolon - let caller handle it */ + } else { + expect(";"); } while (1) { /* iterate thru each declaration */ @@ -8904,7 +8908,7 @@ static int decl(int l) if (tok != ',') { if (l == VT_JMP) return has_init ? v : 1; - skip(';'); + if (tok == ';') next(); break; } next(); diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index a90f4153..0c60aab1 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -179,7 +179,7 @@ bar : 3 ; 3 60_errors_and_warnings.c:372: error: statement expression outside of function [test_invalid_tokckill] -60_errors_and_warnings.c:375: error: ';' expected (got '3') +60_errors_and_warnings.c:375: warning: function might return no value: 'f' [test_duplicate_member] 60_errors_and_warnings.c:381: error: duplicate member 'a'