if a switch is unreachable then so are the case labels. Unlike normal labels they can't possibly be reached from not-yet parsed code, so there's no reason to enable codegen again for those.
Unified · Split
| @@ -62,7 +62,15 @@ ST_DATA int nocode_wanted; /* no code generation wanted */ · 61 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | /* Clear 'nocode_wanted' at label if it was used */ |
| 64 | 64 | ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }} |
| 65 | −static int gind(void) { int t = ind; CODE_ON(); if (debug_modes) tcc_tcov_block_begin(tcc_state); return t; } | |
| 65 | +static int gind(int known_unreachable) | |
| 66 | +{ | |
| 67 | + int t = ind; | |
| 68 | + if (!known_unreachable) | |
| 69 | + CODE_ON(); | |
| 70 | + if (debug_modes) | |
| 71 | + tcc_tcov_block_begin(tcc_state); | |
| 72 | + return t; | |
| 73 | +} | |
| 66 | 74 | |
| 67 | 75 | /* Set 'nocode_wanted' after unconditional jumps */ |
| 68 | 76 | static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } |
| @@ -99,6 +107,7 @@ static struct switch_t { · 30 unmodified lines | ||
| 99 | 107 | int sym; |
| 100 | 108 | } **p; int n; /* list of case ranges */ |
| 101 | 109 | int def_sym; /* default symbol */ |
| 110 | + int nocode_wanted; | |
| 102 | 111 | int *bsym; |
| 103 | 112 | struct scope *scope; |
| 104 | 113 | struct switch_t *prev; |
| @@ -6769,7 +6778,7 @@ again: · 6664 unmodified lines | ||
| 6769 | 6778 | } |
| 6770 | 6779 | |
| 6771 | 6780 | } else if (t == TOK_WHILE) { |
| 6772 | − d = gind(); | |
| 6781 | + d = gind(0); | |
| 6773 | 6782 | skip('('); |
| 6774 | 6783 | gexpr(); |
| 6775 | 6784 | skip(')'); |
| @@ -6869,7 +6878,7 @@ again: · 93 unmodified lines | ||
| 6869 | 6878 | } |
| 6870 | 6879 | skip(';'); |
| 6871 | 6880 | a = b = 0; |
| 6872 | − c = d = gind(); | |
| 6881 | + c = d = gind(0); | |
| 6873 | 6882 | if (tok != ';') { |
| 6874 | 6883 | gexpr(); |
| 6875 | 6884 | a = gvtst(1, 0); |
| @@ -6877,7 +6886,7 @@ again: · 1 unmodified line | ||
| 6877 | 6886 | skip(';'); |
| 6878 | 6887 | if (tok != ')') { |
| 6879 | 6888 | e = gjmp(0); |
| 6880 | − d = gind(); | |
| 6889 | + d = gind(0); | |
| 6881 | 6890 | gexpr(); |
| 6882 | 6891 | vpop(); |
| 6883 | 6892 | gjmp_addr(c); |
| @@ -6892,7 +6901,7 @@ again: · 8 unmodified lines | ||
| 6892 | 6901 | |
| 6893 | 6902 | } else if (t == TOK_DO) { |
| 6894 | 6903 | a = b = 0; |
| 6895 | − d = gind(); | |
| 6904 | + d = gind(0); | |
| 6896 | 6905 | lblock(&a, &b); |
| 6897 | 6906 | gsym(b); |
| 6898 | 6907 | skip(TOK_WHILE); |
| @@ -6911,6 +6920,7 @@ again: · 12 unmodified lines | ||
| 6911 | 6920 | sw->bsym = &a; |
| 6912 | 6921 | sw->scope = cur_scope; |
| 6913 | 6922 | sw->prev = cur_switch; |
| 6923 | + sw->nocode_wanted = nocode_wanted; | |
| 6914 | 6924 | cur_switch = sw; |
| 6915 | 6925 | |
| 6916 | 6926 | skip('('); |
| @@ -6965,7 +6975,7 @@ again: · 48 unmodified lines | ||
| 6965 | 6975 | } |
| 6966 | 6976 | if (debug_modes) |
| 6967 | 6977 | tcc_tcov_reset_ind(tcc_state); |
| 6968 | − cr->sym = gind(); | |
| 6978 | + cr->sym = gind(cur_switch->nocode_wanted); | |
| 6969 | 6979 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); |
| 6970 | 6980 | skip(':'); |
| 6971 | 6981 | is_expr = 0; |
| @@ -6978,7 +6988,7 @@ again: · 6 unmodified lines | ||
| 6978 | 6988 | tcc_error("too many 'default'"); |
| 6979 | 6989 | if (debug_modes) |
| 6980 | 6990 | tcc_tcov_reset_ind(tcc_state); |
| 6981 | − cur_switch->def_sym = gind(); | |
| 6991 | + cur_switch->def_sym = gind(cur_switch->nocode_wanted); | |
| 6982 | 6992 | skip(':'); |
| 6983 | 6993 | is_expr = 0; |
| 6984 | 6994 | goto block_after_label; |
| @@ -7044,7 +7054,7 @@ again: · 59 unmodified lines | ||
| 7044 | 7054 | } else { |
| 7045 | 7055 | s = label_push(&global_label_stack, t, LABEL_DEFINED); |
| 7046 | 7056 | } |
| 7047 | − s->jnext = gind(); | |
| 7057 | + s->jnext = gind(0); | |
| 7048 | 7058 | s->cleanupstate = cur_scope->cl.s; |
| 7049 | 7059 | |
| 7050 | 7060 | block_after_label: |
| @@ -1418,6 +1418,13 @@ void optimize_out_test(void) · 1417 unmodified lines | ||
| 1418 | 1418 | undefined_function(); |
| 1419 | 1419 | } |
| 1420 | 1420 | |
| 1421 | + if (0) { | |
| 1422 | + switch (defined_function()) { | |
| 1423 | + case 0: undefined_function(); break; | |
| 1424 | + default: undefined_function(); break; | |
| 1425 | + } | |
| 1426 | + } | |
| 1427 | + | |
| 1421 | 1428 | /* Leave the "if(1)return; printf()" in this order and last in the function */ |
| 1422 | 1429 | if (1) |
| 1423 | 1430 | return; |