Skip to content

Commit

Permalink
Assume case/default follows a statemet
Browse files Browse the repository at this point in the history
  • Loading branch information
tyfkda committed Oct 7, 2024
1 parent 03f5fd9 commit 8ed9aca
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/cc/backend/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
static void gen_expr_stmt(Expr *expr);

void set_curbb(BB *bb) {
assert(bb != NULL);
assert(curfunc != NULL);
if (curbb != NULL)
curbb->next = bb;
Expand Down Expand Up @@ -510,6 +511,7 @@ static void gen_switch(Stmt *stmt) {

inline void gen_case(Stmt *stmt) {
set_curbb(stmt->case_.bb);
gen_stmt(stmt->case_.stmt);
}

static void gen_while(Stmt *stmt) {
Expand Down
1 change: 1 addition & 0 deletions src/cc/frontend/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ Stmt *new_stmt_case(const Token *token, Stmt *swtch, Expr *value) {
Stmt *stmt = new_stmt(ST_CASE, token);
stmt->case_.swtch = swtch;
stmt->case_.value = value;
stmt->case_.stmt = NULL;
stmt->case_.bb = NULL;
return stmt;
}
Expand Down
1 change: 1 addition & 0 deletions src/cc/frontend/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ typedef struct Stmt {
struct {
struct Stmt *swtch;
Expr *value; // NULL => default
struct Stmt *stmt;
//
BB *bb;
} case_;
Expand Down
8 changes: 7 additions & 1 deletion src/cc/frontend/fe_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,10 @@ static void check_reachability_stmt(Stmt *stmt) {
stmt->break_.parent->reach &= ~REACH_STOP;
stmt->reach |= REACH_STOP;
break;
case ST_CASE:
check_reachability_stmt(stmt->case_.stmt);
stmt->reach = stmt->case_.stmt->reach;
break;
case ST_GOTO:
// TODO:
stmt->reach |= REACH_STOP;
Expand Down Expand Up @@ -1585,7 +1589,7 @@ static void check_reachability_stmt(Stmt *stmt) {
}
}
break;
case ST_EMPTY: case ST_CASE: case ST_VARDECL: case ST_ASM:
case ST_EMPTY: case ST_VARDECL: case ST_ASM:
stmt->reach = 0;
break;
}
Expand Down Expand Up @@ -1968,6 +1972,8 @@ static Stmt *duplicate_inline_function_stmt(Function *targetfunc, Scope *targets
// Value is constant so reuse.
assert(is_const(stmt->case_.value));
}
dup->case_.stmt = duplicate_inline_function_stmt(targetfunc, targetscope, stmt->case_.stmt);

// Find index.
Stmt *org_swtch = stmt->case_.swtch;
Vector *org_cases = org_swtch->switch_.cases;
Expand Down
8 changes: 8 additions & 0 deletions src/cc/frontend/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,14 @@ static Stmt *parse_case(const Token *tok) {
vec_push(swtch->switch_.cases, stmt);
if (tok->kind == TK_DEFAULT)
swtch->switch_.default_ = stmt;

Stmt *next = parse_stmt();
if (next == NULL) {
parse_error(PE_NOFATAL, tok, "statement expected");
next = new_stmt(ST_EMPTY, tok); // Dummy
}
stmt->case_.stmt = next;

return stmt;
}

Expand Down
6 changes: 3 additions & 3 deletions src/wcc/gen_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1202,11 +1202,11 @@ static void gen_switch(Stmt *stmt) {
break_depth = save_depth;
}

static void gen_case(Stmt *stmt) {
UNUSED(stmt);
static void gen_case(Stmt *stmt, bool is_last) {
ADD_CODE(OP_END);
--cur_depth;
assert(cur_depth >= 0);
gen_stmt(stmt->case_.stmt, is_last);
}

static void gen_while(Stmt *stmt) {
Expand Down Expand Up @@ -1445,7 +1445,7 @@ static void gen_stmt(Stmt *stmt, bool is_last) {
case ST_BLOCK: gen_block(stmt, is_last); break;
case ST_IF: gen_if(stmt, is_last); break;
case ST_SWITCH: gen_switch(stmt); break;
case ST_CASE: gen_case(stmt); break;
case ST_CASE: gen_case(stmt, is_last); break;
case ST_WHILE: gen_while(stmt); break;
case ST_DO_WHILE: gen_do_while(stmt); break;
case ST_FOR: gen_for(stmt); break;
Expand Down
1 change: 1 addition & 0 deletions src/wcc/traverse.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ static void traverse_switch(Stmt *stmt) {
static void traverse_case(Stmt *stmt) {
if (branching_stmt->kind != ST_SWITCH)
parse_error(PE_FATAL, stmt->token, "case/default inside branch not supported");
traverse_stmt(stmt->case_.stmt);
}

static void traverse_while(Stmt *stmt) {
Expand Down
7 changes: 7 additions & 0 deletions tests/valtest.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,13 @@ TEST(all) {
}
EXPECT("switch fallthrough", 11, x);
}
{
int x = 44;
switch (x)
case 1:
x = 55;
EXPECT("switch w/o bracket", 44, x);
}
{
int x = 10, *p = &x;
++(*p);
Expand Down

0 comments on commit 8ed9aca

Please sign in to comment.