@@ -99,6 +99,18 @@ typedef struct {
9999 bool is_volatile ;
100100} EvalContext ;
101101
102+ typedef struct JumpContext JumpContext ;
103+ struct JumpContext {
104+ JumpContext * next ;
105+ char * brk_label ;
106+ char * cont_label ;
107+ DeferStmt * defr_end ;
108+ Token * labels ;
109+ Node * switch_node ;
110+ };
111+
112+ static JumpContext * jump_ctx ;
113+
102114// Likewise, global variables are accumulated to this list.
103115static Obj * globals ;
104116
@@ -111,17 +123,8 @@ static Obj *current_fn;
111123static Node * gotos ;
112124static Node * labels ;
113125
114- // Current "goto" and "continue" jump targets.
115- static char * brk_label ;
116- static char * cont_label ;
117-
118- // Points to a node representing a switch if we are parsing
119- // a switch statement. Otherwise, NULL.
120- static Node * current_switch ;
121-
122126static DeferStmt * current_defr ;
123- static DeferStmt * brk_defr ;
124- static DeferStmt * cont_defr ;
127+
125128static bool fn_use_vla ;
126129static bool dont_dealloc_vla ;
127130static bool is_global_init_context ;
@@ -143,7 +146,7 @@ static Node *lvar_initializer(Token **rest, Token *tok, Obj *var);
143146static void gvar_initializer (Token * * rest , Token * tok , Obj * var );
144147static void constexpr_initializer (Token * * rest , Token * tok , Obj * init_var , Obj * var );
145148static Node * compound_stmt (Token * * rest , Token * tok , NodeKind kind );
146- static Node * stmt (Token * * rest , Token * tok );
149+ static Node * stmt (Token * * rest , Token * tok , Token * label_list );
147150static Node * expr_stmt (Token * * rest , Token * tok );
148151static Node * expr (Token * * rest , Token * tok );
149152static int64_t eval (Node * node );
@@ -2336,9 +2339,13 @@ static Node *asm_stmt(Token **rest, Token *tok) {
23362339 return node ;
23372340}
23382341
2339- static void label_stmt (Node * * cur , Token * * rest , Token * tok ) {
2342+ static Token * label_stmt (Node * * cur , Token * * rest , Token * tok ) {
2343+ Token * label_list = NULL ;
2344+ Node * active_switch = NULL ;
23402345 for (;;) {
23412346 if (tok -> kind == TK_IDENT && equal (tok -> next , ":" )) {
2347+ if (!label_list )
2348+ label_list = tok ;
23422349 Node * node = new_node (ND_LABEL , tok );
23432350 node -> label = strndup (tok -> loc , tok -> len );
23442351 node -> unique_label = new_unique_name ();
@@ -2350,17 +2357,26 @@ static void label_stmt(Node **cur, Token **rest, Token *tok) {
23502357 }
23512358
23522359 if (equal (tok , "case" ) || equal (tok , "default" )) {
2353- if (!current_switch )
2354- error_tok (tok , "stray case" );
2355- if (current_defr != brk_defr )
2356- error_tok (tok , "illegal jump" );
2360+ label_list = NULL ;
2361+
2362+ if (!active_switch ) {
2363+ JumpContext * ctx = jump_ctx ;
2364+ for (; ctx ; ctx = ctx -> next )
2365+ if (ctx -> switch_node )
2366+ break ;
2367+ if (!ctx )
2368+ error_tok (tok , "stray case" );
2369+ if (jump_ctx -> defr_end != current_defr )
2370+ error_tok (tok , "illegal jump" );
2371+ active_switch = ctx -> switch_node ;
2372+ }
23572373
23582374 Node * node = new_node (ND_CASE , tok );
23592375 node -> label = new_unique_name ();
23602376
23612377 if (equal (tok , "default" )) {
23622378 tok = skip (tok -> next , ":" );
2363- current_switch -> default_case = node ;
2379+ active_switch -> default_case = node ;
23642380 (* cur ) = (* cur )-> next = node ;
23652381 continue ;
23662382 }
@@ -2374,7 +2390,7 @@ static void label_stmt(Node **cur, Token **rest, Token *tok) {
23742390 else
23752391 end = begin ;
23762392
2377- Type * cond_ty = current_switch -> cond -> ty ;
2393+ Type * cond_ty = active_switch -> cond -> ty ;
23782394 if (cond_ty -> size <= 4 ) {
23792395 if (!cond_ty -> is_unsigned )
23802396 begin = (int32_t )begin , end = (int32_t )end ;
@@ -2388,14 +2404,14 @@ static void label_stmt(Node **cur, Token **rest, Token *tok) {
23882404 tok = skip (tok , ":" );
23892405 node -> begin = begin ;
23902406 node -> end = end ;
2391- node -> case_next = current_switch -> case_next ;
2392- current_switch -> case_next = node ;
2407+ node -> case_next = active_switch -> case_next ;
2408+ active_switch -> case_next = node ;
23932409 (* cur ) = (* cur )-> next = node ;
23942410 continue ;
23952411 }
23962412
23972413 * rest = tok ;
2398- return ;
2414+ return label_list ;
23992415 }
24002416}
24012417
@@ -2406,27 +2422,43 @@ static Node *secondary_block(Token **rest, Token *tok) {
24062422 DeferStmt * dfr = new_block_scope ();
24072423 Node head = {0 };
24082424 Node * cur = & head ;
2409- label_stmt (& cur , & tok , tok );
2410- cur -> next = stmt (rest , tok );
2425+ Token * label_list = label_stmt (& cur , & tok , tok );
2426+ cur -> next = stmt (rest , tok , label_list );
24112427 return leave_block_scope (dfr , head .next );
24122428}
24132429
2414- static void loop_body (Token * * rest , Token * tok , Node * node ) {
2415- char * brk = brk_label ;
2416- char * cont = cont_label ;
2417- brk_label = node -> brk_label = new_unique_name ();
2418- cont_label = node -> cont_label = new_unique_name ();
2430+ static void loop_body (Token * * rest , Token * tok , Node * node , Token * label_list ) {
2431+ JumpContext ctx = {.next = jump_ctx };
2432+ jump_ctx = & ctx ;
24192433
2420- DeferStmt * brkdefr = brk_defr ;
2421- DeferStmt * contdefr = cont_defr ;
2422- brk_defr = cont_defr = current_defr ;
2434+ ctx .labels = label_list ;
2435+ ctx .brk_label = node -> brk_label = new_unique_name ();
2436+ ctx .cont_label = node -> cont_label = new_unique_name ();
2437+ ctx .defr_end = current_defr ;
24232438
24242439 node -> then = secondary_block (rest , tok );
24252440
2426- brk_label = brk ;
2427- cont_label = cont ;
2428- brk_defr = brkdefr ;
2429- cont_defr = contdefr ;
2441+ jump_ctx = ctx .next ;
2442+ }
2443+
2444+ static JumpContext * resolve_labeled_jump (Token * * rest , Token * tok , bool is_cont ) {
2445+ Token * name = NULL ;
2446+ if (tok -> next -> kind == TK_IDENT )
2447+ name = tok = tok -> next ;
2448+ * rest = skip (tok -> next , ";" );
2449+
2450+ for (JumpContext * ctx = jump_ctx ; ctx ; ctx = ctx -> next ) {
2451+ if (is_cont && ctx -> switch_node )
2452+ continue ;
2453+ if (!name )
2454+ return ctx ;
2455+ for (Token * t = ctx -> labels ; t && t -> kind == TK_IDENT && equal (t -> next , ":" );) {
2456+ if (name -> len == t -> len && !memcmp (name -> loc , t -> loc , t -> len ))
2457+ return ctx ;
2458+ t = t -> next -> next ;
2459+ }
2460+ }
2461+ error_tok (tok , "cannot resolve jump" );
24302462}
24312463
24322464// stmt = "return" expr? ";"
@@ -2444,7 +2476,7 @@ static void loop_body(Token **rest, Token *tok, Node *node) {
24442476// | ident ":" stmt
24452477// | "{" compound-stmt
24462478// | expr-stmt
2447- static Node * stmt (Token * * rest , Token * tok ) {
2479+ static Node * stmt (Token * * rest , Token * tok , Token * label_list ) {
24482480 if (equal (tok , "return" )) {
24492481 Node * node = new_node (ND_RETURN , tok );
24502482 node -> defr_start = current_defr ;
@@ -2485,21 +2517,16 @@ static Node *stmt(Token **rest, Token *tok) {
24852517 if (!is_integer (node -> cond -> ty ))
24862518 error_tok (tok , "controlling expression not integer" );
24872519
2488- Node * sw = current_switch ;
2489- current_switch = node ;
2490-
2491- char * brk = brk_label ;
2492- brk_label = node -> brk_label = new_unique_name ();
2520+ JumpContext ctx = {.next = jump_ctx , .switch_node = node };
2521+ jump_ctx = & ctx ;
24932522
2494- DeferStmt * defr = brk_defr ;
2495- brk_defr = current_defr ;
2523+ ctx .labels = label_list ;
2524+ ctx .brk_label = node -> brk_label = new_unique_name ();
2525+ ctx .defr_end = current_defr ;
24962526
24972527 node -> then = secondary_block (rest , tok );
24982528
2499- current_switch = sw ;
2500- brk_label = brk ;
2501- brk_defr = defr ;
2502-
2529+ jump_ctx = ctx .next ;
25032530 return leave_block_scope (dfr , node );
25042531 }
25052532
@@ -2531,7 +2558,7 @@ static Node *stmt(Token **rest, Token *tok) {
25312558 node -> inc = expr (& tok , tok );
25322559 tok = skip (tok , ")" );
25332560
2534- loop_body (rest , tok , node );
2561+ loop_body (rest , tok , node , label_list );
25352562
25362563 return leave_block_scope (dfr , node );
25372564 }
@@ -2544,15 +2571,15 @@ static Node *stmt(Token **rest, Token *tok) {
25442571 node -> cond = to_bool (cond_declaration (& tok , skip (tok -> next , "(" ), ")" , 1 ));
25452572 node -> defr_start = current_defr ;
25462573
2547- loop_body (rest , tok , node );
2574+ loop_body (rest , tok , node , label_list );
25482575
25492576 return leave_block_scope (dfr , node );
25502577 }
25512578
25522579 if (equal (tok , "do" )) {
25532580 Node * node = new_node (ND_DO , tok );
25542581
2555- loop_body (& tok , tok -> next , node );
2582+ loop_body (& tok , tok -> next , node , label_list );
25562583
25572584 tok = skip (tok , "while" );
25582585 tok = skip (tok , "(" );
@@ -2591,25 +2618,15 @@ static Node *stmt(Token **rest, Token *tok) {
25912618 return node ;
25922619 }
25932620
2594- if (equal (tok , "break" )) {
2595- if (!brk_label )
2596- error_tok (tok , "stray break" );
2621+ if (equal (tok , "break" ) || equal (tok , "continue" )) {
25972622 Node * node = new_node (ND_GOTO , tok );
2598- node -> unique_label = brk_label ;
2599- node -> defr_end = brk_defr ;
2600- node -> defr_start = current_defr ;
2601- * rest = skip (tok -> next , ";" );
2602- return node ;
2603- }
26042623
2605- if (equal (tok , "continue" )) {
2606- if (!cont_label )
2607- error_tok (tok , "stray continue" );
2608- Node * node = new_node (ND_GOTO , tok );
2609- node -> unique_label = cont_label ;
2610- node -> defr_end = cont_defr ;
2624+ bool is_cont = equal (tok , "continue" );
2625+ JumpContext * ctx = resolve_labeled_jump (rest , tok , is_cont );
2626+
2627+ node -> unique_label = is_cont ? ctx -> cont_label : ctx -> brk_label ;
2628+ node -> defr_end = ctx -> defr_end ;
26112629 node -> defr_start = current_defr ;
2612- * rest = skip (tok -> next , ";" );
26132630 return node ;
26142631 }
26152632
@@ -2636,7 +2653,7 @@ static Node *compound_stmt(Token **rest, Token *tok, NodeKind kind) {
26362653 Node * cur = & head ;
26372654
26382655 for (;;) {
2639- label_stmt (& cur , & tok , tok );
2656+ Token * label_list = label_stmt (& cur , & tok , tok );
26402657
26412658 if (equal (tok , "}" ))
26422659 break ;
@@ -2647,7 +2664,7 @@ static Node *compound_stmt(Token **rest, Token *tok, NodeKind kind) {
26472664 }
26482665
26492666 if (!is_typename (tok )) {
2650- cur = cur -> next = stmt (& tok , tok );
2667+ cur = cur -> next = stmt (& tok , tok , label_list );
26512668 add_type (cur );
26522669 continue ;
26532670 }
0 commit comments