| @@ -44,6 +44,7 @@ static int ncleanups; · 43 unmodified lines |
| 44 | 44 | |
| 45 | 45 | static int local_scope; |
| 46 | 46 | static int in_sizeof; |
| 47 | +static int in_generic; |
| 47 | 48 | static int section_sym; |
| 48 | 49 | |
| 49 | 50 | ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */ |
| @@ -56,6 +57,24 @@ ST_DATA int const_wanted; /* true if constant wanted */ · 6 unmodified lines |
| 56 | 57 | ST_DATA int nocode_wanted; /* no code generation wanted */ |
| 57 | 58 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ |
| 58 | 59 | #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ |
| 60 | + |
| 61 | +/* Automagical code suppression ----> */ |
| 62 | +#define CODE_OFF() (nocode_wanted |= 0x20000000) |
| 63 | +#define CODE_ON() (nocode_wanted &= ~0x20000000) |
| 64 | + |
| 65 | +/* Clear 'nocode_wanted' at label if it was used */ |
| 66 | +ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }} |
| 67 | +static int gind(void) { CODE_ON(); return ind; } |
| 68 | + |
| 69 | +/* Set 'nocode_wanted' after unconditional jumps */ |
| 70 | +static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } |
| 71 | +static int gjmp_acs(int t) { t = gjmp(t); CODE_OFF(); return t; } |
| 72 | + |
| 73 | +/* These are #undef'd at the end of this file */ |
| 74 | +#define gjmp_addr gjmp_addr_acs |
| 75 | +#define gjmp gjmp_acs |
| 76 | +/* <---- */ |
| 77 | + |
| 59 | 78 | ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ |
| 60 | 79 | ST_DATA CType func_vt; /* current function return type (used by return instruction) */ |
| 61 | 80 | ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ |
| @@ -3544,8 +3563,7 @@ redo: · 3482 unmodified lines |
| 3544 | 3563 | break; |
| 3545 | 3564 | case TOK_NORETURN1: |
| 3546 | 3565 | case TOK_NORETURN2: |
| 3547 | | − /* currently, no need to handle it because tcc does not |
| 3548 | | − track unused objects */ |
| 3566 | + ad->f.func_noreturn = 1; |
| 3549 | 3567 | break; |
| 3550 | 3568 | case TOK_CDECL1: |
| 3551 | 3569 | case TOK_CDECL2: |
| @@ -4129,7 +4147,7 @@ static void parse_btype_qualify(CType *type, int qualifiers) · 577 unmodified lines |
| 4129 | 4147 | */ |
| 4130 | 4148 | static int parse_btype(CType *type, AttributeDef *ad) |
| 4131 | 4149 | { |
| 4132 | | − int t, u, bt, st, type_found, typespec_found, g; |
| 4150 | + int t, u, bt, st, type_found, typespec_found, g, n; |
| 4133 | 4151 | Sym *s; |
| 4134 | 4152 | CType type1; |
| 4135 | 4153 | |
| @@ -4336,6 +4354,14 @@ static int parse_btype(CType *type, AttributeDef *ad) · 200 unmodified lines |
| 4336 | 4354 | s = sym_find(tok); |
| 4337 | 4355 | if (!s || !(s->type.t & VT_TYPEDEF)) |
| 4338 | 4356 | goto the_end; |
| 4357 | + |
| 4358 | + n = tok, next(); |
| 4359 | + if (tok == ':' && !in_generic) { |
| 4360 | + /* ignore if it's a label */ |
| 4361 | + unget_tok(n); |
| 4362 | + goto the_end; |
| 4363 | + } |
| 4364 | + |
| 4339 | 4365 | t &= ~(VT_BTYPE|VT_LONG); |
| 4340 | 4366 | u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u; |
| 4341 | 4367 | type->t = (s->type.t & ~VT_TYPEDEF) | u; |
| @@ -4345,7 +4371,6 @@ static int parse_btype(CType *type, AttributeDef *ad) · 3 unmodified lines |
| 4345 | 4371 | t = type->t; |
| 4346 | 4372 | /* get attributes from typedef */ |
| 4347 | 4373 | sym_to_attr(ad, s); |
| 4348 | | − next(); |
| 4349 | 4374 | typespec_found = 1; |
| 4350 | 4375 | st = bt = -2; |
| 4351 | 4376 | break; |
| @@ -5237,7 +5262,11 @@ ST_FUNC void unary(void) · 885 unmodified lines |
| 5237 | 5262 | AttributeDef ad_tmp; |
| 5238 | 5263 | int itmp; |
| 5239 | 5264 | CType cur_type; |
| 5265 | + |
| 5266 | + in_generic++; |
| 5240 | 5267 | parse_btype(&cur_type, &ad_tmp); |
| 5268 | + in_generic--; |
| 5269 | + |
| 5241 | 5270 | type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT); |
| 5242 | 5271 | if (compare_types(&controlling_type, &cur_type, 0)) { |
| 5243 | 5272 | if (has_match) { |
| @@ -5501,6 +5530,8 @@ special_math_val: · 257 unmodified lines |
| 5501 | 5530 | } |
| 5502 | 5531 | vset(&s->type, VT_LOCAL | VT_LVAL, addr); |
| 5503 | 5532 | } |
| 5533 | + if (s->f.func_noreturn) |
| 5534 | + CODE_OFF(); |
| 5504 | 5535 | } else { |
| 5505 | 5536 | break; |
| 5506 | 5537 | } |
| @@ -5603,86 +5634,50 @@ static void expr_or(void) · 96 unmodified lines |
| 5603 | 5634 | } |
| 5604 | 5635 | } |
| 5605 | 5636 | |
| 5637 | +static int condition_3way(void); |
| 5638 | + |
| 5639 | +static void expr_landor(void(*e_fn)(void), int e_op, int i) |
| 5640 | +{ |
| 5641 | + int t = 0, cc = 1, f = 0, c; |
| 5642 | + for(;;) { |
| 5643 | + c = f ? i : condition_3way(); |
| 5644 | + if (c < 0) { |
| 5645 | + save_regs(1), cc = 0; |
| 5646 | + } else if (c != i) { |
| 5647 | + nocode_wanted++, f = 1; |
| 5648 | + } |
| 5649 | + if (tok != e_op) { |
| 5650 | + if (cc || f) { |
| 5651 | + vpop(); |
| 5652 | + vpushi(i ^ f); |
| 5653 | + gsym(t); |
| 5654 | + nocode_wanted -= f; |
| 5655 | + } else { |
| 5656 | + vseti(VT_JMP + i, gvtst(i, t)); |
| 5657 | + } |
| 5658 | + break; |
| 5659 | + } |
| 5660 | + if (c < 0) |
| 5661 | + t = gvtst(i, t); |
| 5662 | + else |
| 5663 | + vpop(); |
| 5664 | + next(); |
| 5665 | + e_fn(); |
| 5666 | + } |
| 5667 | +} |
| 5668 | + |
| 5606 | 5669 | static void expr_land(void) |
| 5607 | 5670 | { |
| 5608 | 5671 | expr_or(); |
| 5609 | | − if (tok == TOK_LAND) { |
| 5610 | | − int t = 0; |
| 5611 | | − for(;;) { |
| 5612 | | − if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 5613 | | − gen_cast_s(VT_BOOL); |
| 5614 | | − if (vtop->c.i) { |
| 5615 | | − vpop(); |
| 5616 | | − } else { |
| 5617 | | − nocode_wanted++; |
| 5618 | | − while (tok == TOK_LAND) { |
| 5619 | | − next(); |
| 5620 | | − expr_or(); |
| 5621 | | − vpop(); |
| 5622 | | − } |
| 5623 | | − nocode_wanted--; |
| 5624 | | − if (t) |
| 5625 | | − gsym(t); |
| 5626 | | − gen_cast_s(VT_INT); |
| 5627 | | − break; |
| 5628 | | − } |
| 5629 | | − } else { |
| 5630 | | − if (!t) |
| 5631 | | − save_regs(1); |
| 5632 | | − t = gvtst(1, t); |
| 5633 | | − } |
| 5634 | | − if (tok != TOK_LAND) { |
| 5635 | | − if (t) |
| 5636 | | − vseti(VT_JMPI, t); |
| 5637 | | − else |
| 5638 | | − vpushi(1); |
| 5639 | | − break; |
| 5640 | | − } |
| 5641 | | − next(); |
| 5642 | | − expr_or(); |
| 5643 | | − } |
| 5644 | | − } |
| 5672 | + if (tok == TOK_LAND) |
| 5673 | + expr_landor(expr_or, TOK_LAND, 1); |
| 5645 | 5674 | } |
| 5646 | 5675 | |
| 5647 | 5676 | static void expr_lor(void) |
| 5648 | 5677 | { |
| 5649 | 5678 | expr_land(); |
| 5650 | | − if (tok == TOK_LOR) { |
| 5651 | | − int t = 0; |
| 5652 | | − for(;;) { |
| 5653 | | − if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 5654 | | − gen_cast_s(VT_BOOL); |
| 5655 | | − if (!vtop->c.i) { |
| 5656 | | − vpop(); |
| 5657 | | − } else { |
| 5658 | | − nocode_wanted++; |
| 5659 | | − while (tok == TOK_LOR) { |
| 5660 | | − next(); |
| 5661 | | − expr_land(); |
| 5662 | | − vpop(); |
| 5663 | | − } |
| 5664 | | − nocode_wanted--; |
| 5665 | | − if (t) |
| 5666 | | − gsym(t); |
| 5667 | | − gen_cast_s(VT_INT); |
| 5668 | | − break; |
| 5669 | | − } |
| 5670 | | − } else { |
| 5671 | | − if (!t) |
| 5672 | | − save_regs(1); |
| 5673 | | − t = gvtst(0, t); |
| 5674 | | − } |
| 5675 | | − if (tok != TOK_LOR) { |
| 5676 | | − if (t) |
| 5677 | | − vseti(VT_JMP, t); |
| 5678 | | − else |
| 5679 | | − vpushi(0); |
| 5680 | | − break; |
| 5681 | | − } |
| 5682 | | − next(); |
| 5683 | | − expr_land(); |
| 5684 | | − } |
| 5685 | | − } |
| 5679 | + if (tok == TOK_LOR) |
| 5680 | + expr_landor(expr_land, TOK_LOR, 0); |
| 5686 | 5681 | } |
| 5687 | 5682 | |
| 5688 | 5683 | /* Assuming vtop is a value used in a conditional context |
| @@ -5706,15 +5701,25 @@ static void expr_cond(void) · 17 unmodified lines |
| 5706 | 5701 | int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g; |
| 5707 | 5702 | SValue sv; |
| 5708 | 5703 | CType type, type1, type2; |
| 5704 | + int ncw_prev; |
| 5709 | 5705 | |
| 5710 | 5706 | expr_lor(); |
| 5711 | 5707 | if (tok == '?') { |
| 5712 | 5708 | next(); |
| 5713 | 5709 | c = condition_3way(); |
| 5714 | 5710 | g = (tok == ':' && gnu_ext); |
| 5715 | | − if (c < 0) { |
| 5711 | + tt = 0; |
| 5712 | + if (!g) { |
| 5713 | + if (c < 0) { |
| 5714 | + save_regs(1); |
| 5715 | + tt = gvtst(1, 0); |
| 5716 | + } else { |
| 5717 | + vpop(); |
| 5718 | + } |
| 5719 | + } else if (c < 0) { |
| 5716 | 5720 | /* needed to avoid having different registers saved in |
| 5717 | 5721 | each branch */ |
| 5722 | + rc = RC_INT; |
| 5718 | 5723 | if (is_float(vtop->type.t)) { |
| 5719 | 5724 | rc = RC_FLOAT; |
| 5720 | 5725 | #ifdef TCC_TARGET_X86_64 |
| @@ -5722,20 +5727,14 @@ static void expr_cond(void) · 1 unmodified line |
| 5722 | 5727 | rc = RC_ST0; |
| 5723 | 5728 | } |
| 5724 | 5729 | #endif |
| 5725 | | − } else |
| 5726 | | − rc = RC_INT; |
| 5730 | + } |
| 5727 | 5731 | gv(rc); |
| 5728 | 5732 | save_regs(1); |
| 5729 | | − if (g) |
| 5730 | | − gv_dup(); |
| 5731 | | − tt = gvtst(1, 0); |
| 5732 | | − |
| 5733 | | − } else { |
| 5734 | | − if (!g) |
| 5735 | | − vpop(); |
| 5736 | | − tt = 0; |
| 5733 | + gv_dup(); |
| 5734 | + tt = gvtst(0, 0); |
| 5737 | 5735 | } |
| 5738 | 5736 | |
| 5737 | + ncw_prev = nocode_wanted; |
| 5739 | 5738 | if (1) { |
| 5740 | 5739 | if (c == 0) |
| 5741 | 5740 | nocode_wanted++; |
| @@ -5747,20 +5746,21 @@ static void expr_cond(void) · 5 unmodified lines |
| 5747 | 5746 | type1 = vtop->type; |
| 5748 | 5747 | sv = *vtop; /* save value to handle it later */ |
| 5749 | 5748 | vtop--; /* no vpop so that FP stack is not flushed */ |
| 5750 | | − skip(':'); |
| 5751 | 5749 | |
| 5752 | | − u = 0; |
| 5753 | | − if (c < 0) |
| 5750 | + if (g) { |
| 5751 | + u = tt; |
| 5752 | + } else if (c < 0) { |
| 5754 | 5753 | u = gjmp(0); |
| 5755 | | − gsym(tt); |
| 5754 | + gsym(tt); |
| 5755 | + } else |
| 5756 | + u = 0; |
| 5756 | 5757 | |
| 5757 | | − if (c == 0) |
| 5758 | | − nocode_wanted--; |
| 5758 | + nocode_wanted = ncw_prev; |
| 5759 | 5759 | if (c == 1) |
| 5760 | 5760 | nocode_wanted++; |
| 5761 | + skip(':'); |
| 5761 | 5762 | expr_cond(); |
| 5762 | | − if (c == 1) |
| 5763 | | − nocode_wanted--; |
| 5763 | + |
| 5764 | 5764 | |
| 5765 | 5765 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) |
| 5766 | 5766 | mk_pointer(&vtop->type); |
| @@ -5771,7 +5771,6 @@ static void expr_cond(void) · 4 unmodified lines |
| 5771 | 5771 | bt2 = t2 & VT_BTYPE; |
| 5772 | 5772 | type.ref = NULL; |
| 5773 | 5773 | |
| 5774 | | − |
| 5775 | 5774 | /* cast operands to correct type according to ISOC rules */ |
| 5776 | 5775 | if (bt1 == VT_VOID || bt2 == VT_VOID) { |
| 5777 | 5776 | type.t = VT_VOID; /* NOTE: as an extension, we accept void on only one side */ |
| @@ -5902,15 +5901,17 @@ static void expr_cond(void) · 124 unmodified lines |
| 5902 | 5901 | gaddrof(); |
| 5903 | 5902 | } |
| 5904 | 5903 | |
| 5905 | | − if (c < 0 || islv) { |
| 5904 | + if (c < 0) { |
| 5906 | 5905 | r1 = gv(rc); |
| 5907 | 5906 | move_reg(r2, r1, type.t); |
| 5908 | 5907 | vtop->r = r2; |
| 5909 | 5908 | gsym(tt); |
| 5910 | | − if (islv) |
| 5911 | | − indir(); |
| 5912 | 5909 | } |
| 5910 | + |
| 5911 | + if (islv) |
| 5912 | + indir(); |
| 5913 | 5913 | } |
| 5914 | + nocode_wanted = ncw_prev; |
| 5914 | 5915 | } |
| 5915 | 5916 | } |
| 5916 | 5917 | |
| @@ -5982,25 +5983,8 @@ ST_FUNC int expr_const(void) · 65 unmodified lines |
| 5982 | 5983 | return c; |
| 5983 | 5984 | } |
| 5984 | 5985 | |
| 5985 | | −/* return the label token if current token is a label, otherwise |
| 5986 | | − return zero */ |
| 5987 | | −static int is_label(void) |
| 5988 | | −{ |
| 5989 | | − int last_tok; |
| 5990 | | − |
| 5991 | | − /* fast test first */ |
| 5992 | | − if (tok < TOK_UIDENT) |
| 5993 | | − return 0; |
| 5994 | | − /* no need to save tokc because tok is an identifier */ |
| 5995 | | − last_tok = tok; |
| 5996 | | − next(); |
| 5997 | | − if (tok == ':') { |
| 5998 | | − return last_tok; |
| 5999 | | − } else { |
| 6000 | | − unget_tok(last_tok); |
| 6001 | | − return 0; |
| 6002 | | − } |
| 6003 | | −} |
| 5986 | +/* ------------------------------------------------------------------------- */ |
| 5987 | +/* return from function */ |
| 6004 | 5988 | |
| 6005 | 5989 | #ifndef TCC_TARGET_ARM64 |
| 6006 | 5990 | static void gfunc_return(CType *func_type) |
| @@ -6135,75 +6119,97 @@ static void gcase(struct case_t **base, int len, int *bsym) · 128 unmodified lines |
| 6135 | 6119 | } |
| 6136 | 6120 | } |
| 6137 | 6121 | |
| 6122 | +/* call 'func' for each __attribute__((cleanup(func))) */ |
| 6123 | +static void block_cleanup(Sym *lcleanup, int lncleanups) |
| 6124 | +{ |
| 6125 | + int jmp = 0; |
| 6126 | + Sym *g, **pg; |
| 6127 | + for (pg = &pending_gotos; (g = *pg) && g->c > lncleanups;) { |
| 6128 | + if (g->prev_tok->r & LABEL_FORWARD) { |
| 6129 | + Sym *pcl = g->next; |
| 6130 | + if (!jmp) |
| 6131 | + jmp = gjmp(0); |
| 6132 | + gsym(pcl->jnext); |
| 6133 | + try_call_scope_cleanup(lcleanup); |
| 6134 | + pcl->jnext = gjmp(0); |
| 6135 | + if (!lncleanups) |
| 6136 | + goto remove_pending; |
| 6137 | + g->c = lncleanups; |
| 6138 | + pg = &g->prev; |
| 6139 | + } else { |
| 6140 | + remove_pending: |
| 6141 | + *pg = g->prev; |
| 6142 | + sym_free(g); |
| 6143 | + } |
| 6144 | + } |
| 6145 | + gsym(jmp); |
| 6146 | + try_call_scope_cleanup(lcleanup); |
| 6147 | + current_cleanups = lcleanup; |
| 6148 | + ncleanups = lncleanups; |
| 6149 | +} |
| 6150 | + |
| 6151 | +static void check_func_return(void) |
| 6152 | +{ |
| 6153 | + if ((func_vt.t & VT_BTYPE) == VT_VOID) |
| 6154 | + return; |
| 6155 | + if (!strcmp (funcname, "main") |
| 6156 | + && (func_vt.t & VT_BTYPE) == VT_INT) { |
| 6157 | + /* main returns 0 by default */ |
| 6158 | + vpushi(0); |
| 6159 | + gen_assign_cast(&func_vt); |
| 6160 | + gfunc_return(&func_vt); |
| 6161 | + } else { |
| 6162 | + tcc_warning("function might return no value: '%s'", funcname); |
| 6163 | + } |
| 6164 | +} |
| 6165 | + |
| 6138 | 6166 | static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) |
| 6139 | 6167 | { |
| 6140 | | − int a, b, c, d, cond; |
| 6168 | + int a, b, c, d, e, t; |
| 6141 | 6169 | Sym *s; |
| 6142 | 6170 | |
| 6143 | | − /* generate line number info */ |
| 6144 | | − if (tcc_state->do_debug) |
| 6145 | | − tcc_debug_line(tcc_state); |
| 6146 | | − |
| 6147 | 6171 | if (is_expr) { |
| 6148 | 6172 | /* default return value is (void) */ |
| 6149 | 6173 | vpushi(0); |
| 6150 | 6174 | vtop->type.t = VT_VOID; |
| 6151 | 6175 | } |
| 6152 | 6176 | |
| 6153 | | − if (tok == TOK_IF) { |
| 6154 | | − /* if test */ |
| 6155 | | − int saved_nocode_wanted = nocode_wanted; |
| 6156 | | − next(); |
| 6177 | + t = tok, next(); |
| 6178 | + |
| 6179 | + if (t == TOK_IF) { |
| 6157 | 6180 | skip('('); |
| 6158 | 6181 | gexpr(); |
| 6159 | 6182 | skip(')'); |
| 6160 | | − cond = condition_3way(); |
| 6161 | | − if (cond == 1) |
| 6162 | | − a = 0, vpop(); |
| 6163 | | − else |
| 6164 | | − a = gvtst(1, 0); |
| 6165 | | − if (cond == 0) |
| 6166 | | − nocode_wanted |= 0x20000000; |
| 6183 | + a = gvtst(1, 0); |
| 6167 | 6184 | block(bsym, bcl, csym, ccl, 0); |
| 6168 | | − if (cond != 1) |
| 6169 | | − nocode_wanted = saved_nocode_wanted; |
| 6170 | 6185 | if (tok == TOK_ELSE) { |
| 6171 | | − next(); |
| 6172 | 6186 | d = gjmp(0); |
| 6173 | 6187 | gsym(a); |
| 6174 | | − if (cond == 1) |
| 6175 | | − nocode_wanted |= 0x20000000; |
| 6188 | + next(); |
| 6176 | 6189 | block(bsym, bcl, csym, ccl, 0); |
| 6177 | 6190 | gsym(d); /* patch else jmp */ |
| 6178 | | − if (cond != 0) |
| 6179 | | − nocode_wanted = saved_nocode_wanted; |
| 6180 | | − } else |
| 6191 | + } else { |
| 6181 | 6192 | gsym(a); |
| 6182 | | − } else if (tok == TOK_WHILE) { |
| 6183 | | − int saved_nocode_wanted; |
| 6184 | | − nocode_wanted &= ~0x20000000; |
| 6185 | | − next(); |
| 6186 | | − d = ind; |
| 6193 | + } |
| 6194 | + |
| 6195 | + } else if (t == TOK_WHILE) { |
| 6196 | + d = gind(); |
| 6187 | 6197 | vla_sp_restore(); |
| 6188 | 6198 | skip('('); |
| 6189 | 6199 | gexpr(); |
| 6190 | 6200 | skip(')'); |
| 6191 | 6201 | a = gvtst(1, 0); |
| 6192 | 6202 | b = 0; |
| 6193 | | − ++local_scope; |
| 6194 | | − saved_nocode_wanted = nocode_wanted; |
| 6195 | 6203 | block(&a, current_cleanups, &b, current_cleanups, 0); |
| 6196 | | − nocode_wanted = saved_nocode_wanted; |
| 6197 | | − --local_scope; |
| 6198 | 6204 | gjmp_addr(d); |
| 6199 | | − gsym(a); |
| 6200 | 6205 | gsym_addr(b, d); |
| 6201 | | − } else if (tok == '{') { |
| 6206 | + gsym(a); |
| 6207 | + |
| 6208 | + } else if (t == '{') { |
| 6202 | 6209 | Sym *llabel, *lcleanup; |
| 6203 | 6210 | int block_vla_sp_loc = vla_sp_loc, saved_vlas_in_scope = vlas_in_scope; |
| 6204 | 6211 | int lncleanups = ncleanups; |
| 6205 | 6212 | |
| 6206 | | − next(); |
| 6207 | 6213 | /* record local declaration stack position */ |
| 6208 | 6214 | s = local_stack; |
| 6209 | 6215 | llabel = local_label_stack; |
| @@ -6212,25 +6218,18 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 2 unmodified lines |
| 6212 | 6218 | |
| 6213 | 6219 | /* handle local labels declarations */ |
| 6214 | 6220 | while (tok == TOK_LABEL) { |
| 6215 | | − next(); |
| 6216 | | − for(;;) { |
| 6221 | + do { |
| 6222 | + next(); |
| 6217 | 6223 | if (tok < TOK_UIDENT) |
| 6218 | 6224 | expect("label identifier"); |
| 6219 | 6225 | label_push(&local_label_stack, tok, LABEL_DECLARED); |
| 6220 | 6226 | next(); |
| 6221 | | − if (tok == ',') { |
| 6222 | | − next(); |
| 6223 | | − } else { |
| 6224 | | − skip(';'); |
| 6225 | | − break; |
| 6226 | | − } |
| 6227 | | − } |
| 6227 | + } while (tok == ','); |
| 6228 | + skip(';'); |
| 6228 | 6229 | } |
| 6230 | + |
| 6229 | 6231 | while (tok != '}') { |
| 6230 | | − if ((a = is_label())) |
| 6231 | | − unget_tok(a); |
| 6232 | | − else |
| 6233 | | − decl(VT_LOCAL); |
| 6232 | + decl(VT_LOCAL); |
| 6234 | 6233 | if (tok != '}') { |
| 6235 | 6234 | if (is_expr) |
| 6236 | 6235 | vpop(); |
| @@ -6238,39 +6237,12 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 1 unmodified line |
| 6238 | 6237 | } |
| 6239 | 6238 | } |
| 6240 | 6239 | |
| 6241 | | − if (current_cleanups != lcleanup) { |
| 6242 | | − int jmp = 0; |
| 6243 | | − Sym *g, **pg; |
| 6244 | | − |
| 6245 | | − for (pg = &pending_gotos; (g = *pg) && g->c > lncleanups;) |
| 6246 | | − if (g->prev_tok->r & LABEL_FORWARD) { |
| 6247 | | − Sym *pcl = g->next; |
| 6248 | | − if (!jmp) |
| 6249 | | − jmp = gjmp(0); |
| 6250 | | − gsym(pcl->jnext); |
| 6251 | | − try_call_scope_cleanup(lcleanup); |
| 6252 | | − pcl->jnext = gjmp(0); |
| 6253 | | − if (!lncleanups) |
| 6254 | | − goto remove_pending; |
| 6255 | | − g->c = lncleanups; |
| 6256 | | − pg = &g->prev; |
| 6257 | | − } else { |
| 6258 | | − remove_pending: |
| 6259 | | − *pg = g->prev; |
| 6260 | | − sym_free(g); |
| 6261 | | − } |
| 6262 | | − gsym(jmp); |
| 6263 | | − if (!nocode_wanted) { |
| 6264 | | − try_call_scope_cleanup(lcleanup); |
| 6265 | | − } |
| 6266 | | − } |
| 6240 | + if (current_cleanups != lcleanup) |
| 6241 | + block_cleanup(lcleanup, lncleanups); |
| 6267 | 6242 | |
| 6268 | | − current_cleanups = lcleanup; |
| 6269 | | − ncleanups = lncleanups; |
| 6270 | 6243 | /* pop locally defined labels */ |
| 6271 | 6244 | label_pop(&local_label_stack, llabel, is_expr); |
| 6272 | | − /* pop locally defined symbols */ |
| 6273 | | − --local_scope; |
| 6245 | + |
| 6274 | 6246 | /* In the is_expr case (a statement expression is finished here), |
| 6275 | 6247 | vtop might refer to symbols on the local_stack. Either via the |
| 6276 | 6248 | type or via vtop->sym. We can't pop those nor any that in turn |
| @@ -6278,6 +6250,8 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 1 unmodified line |
| 6278 | 6250 | any symbols in that case; some upper level call to block() will |
| 6279 | 6251 | do that. We do have to remove such symbols from the lookup |
| 6280 | 6252 | tables, though. sym_pop will do that. */ |
| 6253 | + |
| 6254 | + /* pop locally defined symbols */ |
| 6281 | 6255 | sym_pop(&local_stack, s, is_expr); |
| 6282 | 6256 | |
| 6283 | 6257 | /* Pop VLA frames and restore stack pointer if required */ |
| @@ -6287,52 +6261,49 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 3 unmodified lines |
| 6287 | 6261 | } |
| 6288 | 6262 | vlas_in_scope = saved_vlas_in_scope; |
| 6289 | 6263 | |
| 6264 | + if (0 == --local_scope && !nocode_wanted) |
| 6265 | + check_func_return(); |
| 6290 | 6266 | next(); |
| 6291 | | − } else if (tok == TOK_RETURN) { |
| 6292 | | − next(); |
| 6293 | | − if (tok != ';') { |
| 6294 | | − gexpr(); |
| 6295 | | − gen_assign_cast(&func_vt); |
| 6296 | | − try_call_scope_cleanup(NULL); |
| 6297 | | − if ((func_vt.t & VT_BTYPE) == VT_VOID) |
| 6298 | | − vtop--; |
| 6299 | | − else |
| 6300 | | − gfunc_return(&func_vt); |
| 6301 | | − } else { |
| 6302 | | − try_call_scope_cleanup(NULL); |
| 6303 | | − } |
| 6267 | + |
| 6268 | + } else if (t == TOK_RETURN) { |
| 6269 | + a = tok != ';'; |
| 6270 | + b = (func_vt.t & VT_BTYPE) != VT_VOID; |
| 6271 | + if (a) |
| 6272 | + gexpr(), gen_assign_cast(&func_vt); |
| 6273 | + try_call_scope_cleanup(NULL); |
| 6274 | + if (a && b) |
| 6275 | + gfunc_return(&func_vt); |
| 6276 | + else if (a) |
| 6277 | + vtop--; |
| 6278 | + else if (b) |
| 6279 | + tcc_warning("'return' with no value."); |
| 6304 | 6280 | skip(';'); |
| 6305 | 6281 | /* jump unless last stmt in top-level block */ |
| 6306 | 6282 | if (tok != '}' || local_scope != 1) |
| 6307 | 6283 | rsym = gjmp(rsym); |
| 6308 | | − nocode_wanted |= 0x20000000; |
| 6309 | | − } else if (tok == TOK_BREAK) { |
| 6284 | + CODE_OFF(); |
| 6285 | + |
| 6286 | + } else if (t == TOK_BREAK) { |
| 6310 | 6287 | /* compute jump */ |
| 6311 | 6288 | if (!bsym) |
| 6312 | 6289 | tcc_error("cannot break"); |
| 6313 | 6290 | try_call_scope_cleanup(bcl); |
| 6314 | 6291 | *bsym = gjmp(*bsym); |
| 6315 | | − next(); |
| 6316 | 6292 | skip(';'); |
| 6317 | | − nocode_wanted |= 0x20000000; |
| 6318 | | − } else if (tok == TOK_CONTINUE) { |
| 6293 | + |
| 6294 | + } else if (t == TOK_CONTINUE) { |
| 6319 | 6295 | /* compute jump */ |
| 6320 | 6296 | if (!csym) |
| 6321 | 6297 | tcc_error("cannot continue"); |
| 6322 | 6298 | try_call_scope_cleanup(ccl); |
| 6323 | 6299 | vla_sp_restore_root(); |
| 6324 | 6300 | *csym = gjmp(*csym); |
| 6325 | | − next(); |
| 6326 | 6301 | skip(';'); |
| 6327 | | − nocode_wanted |= 0x20000000; |
| 6328 | | − } else if (tok == TOK_FOR) { |
| 6329 | | − int e; |
| 6330 | | − int saved_nocode_wanted; |
| 6302 | + |
| 6303 | + } else if (t == TOK_FOR) { |
| 6331 | 6304 | Sym *lcleanup = current_cleanups; |
| 6332 | 6305 | int lncleanups = ncleanups; |
| 6333 | 6306 | |
| 6334 | | − nocode_wanted &= ~0x20000000; |
| 6335 | | − next(); |
| 6336 | 6307 | skip('('); |
| 6337 | 6308 | s = local_stack; |
| 6338 | 6309 | ++local_scope; |
| @@ -6345,11 +6316,9 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 6 unmodified lines |
| 6345 | 6316 | } |
| 6346 | 6317 | } |
| 6347 | 6318 | skip(';'); |
| 6348 | | − d = ind; |
| 6349 | | − c = ind; |
| 6319 | + a = b = 0; |
| 6320 | + c = d = gind(); |
| 6350 | 6321 | vla_sp_restore(); |
| 6351 | | − a = 0; |
| 6352 | | − b = 0; |
| 6353 | 6322 | if (tok != ';') { |
| 6354 | 6323 | gexpr(); |
| 6355 | 6324 | a = gvtst(1, 0); |
| @@ -6357,55 +6326,43 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 1 unmodified line |
| 6357 | 6326 | skip(';'); |
| 6358 | 6327 | if (tok != ')') { |
| 6359 | 6328 | e = gjmp(0); |
| 6360 | | − c = ind; |
| 6329 | + d = gind(); |
| 6361 | 6330 | vla_sp_restore(); |
| 6362 | 6331 | gexpr(); |
| 6363 | 6332 | vpop(); |
| 6364 | | − gjmp_addr(d); |
| 6333 | + gjmp_addr(c); |
| 6365 | 6334 | gsym(e); |
| 6366 | 6335 | } |
| 6367 | 6336 | skip(')'); |
| 6368 | | − saved_nocode_wanted = nocode_wanted; |
| 6369 | 6337 | block(&a, current_cleanups, &b, current_cleanups, 0); |
| 6370 | | − nocode_wanted = saved_nocode_wanted; |
| 6371 | | − gjmp_addr(c); |
| 6338 | + gjmp_addr(d); |
| 6339 | + gsym_addr(b, d); |
| 6372 | 6340 | gsym(a); |
| 6373 | | − gsym_addr(b, c); |
| 6374 | 6341 | --local_scope; |
| 6375 | 6342 | try_call_scope_cleanup(lcleanup); |
| 6376 | 6343 | ncleanups = lncleanups; |
| 6377 | 6344 | current_cleanups = lcleanup; |
| 6378 | 6345 | sym_pop(&local_stack, s, 0); |
| 6379 | 6346 | |
| 6380 | | − } else |
| 6381 | | − if (tok == TOK_DO) { |
| 6382 | | − int saved_nocode_wanted; |
| 6383 | | − nocode_wanted &= ~0x20000000; |
| 6384 | | − next(); |
| 6385 | | − a = 0; |
| 6386 | | − b = 0; |
| 6387 | | − d = ind; |
| 6347 | + } else if (t == TOK_DO) { |
| 6348 | + a = b = 0; |
| 6349 | + d = gind(); |
| 6388 | 6350 | vla_sp_restore(); |
| 6389 | | − saved_nocode_wanted = nocode_wanted; |
| 6390 | 6351 | block(&a, current_cleanups, &b, current_cleanups, 0); |
| 6352 | + gsym(b); |
| 6391 | 6353 | skip(TOK_WHILE); |
| 6392 | 6354 | skip('('); |
| 6393 | | − gsym(b); |
| 6394 | | − if (b) |
| 6395 | | − nocode_wanted = saved_nocode_wanted; |
| 6396 | 6355 | gexpr(); |
| 6356 | + skip(')'); |
| 6357 | + skip(';'); |
| 6397 | 6358 | c = gvtst(0, 0); |
| 6398 | 6359 | gsym_addr(c, d); |
| 6399 | | − nocode_wanted = saved_nocode_wanted; |
| 6400 | | − skip(')'); |
| 6401 | 6360 | gsym(a); |
| 6402 | | − skip(';'); |
| 6403 | | − } else |
| 6404 | | − if (tok == TOK_SWITCH) { |
| 6361 | + |
| 6362 | + } else if (t == TOK_SWITCH) { |
| 6405 | 6363 | struct switch_t *saved, sw; |
| 6406 | | − int saved_nocode_wanted = nocode_wanted; |
| 6407 | 6364 | SValue switchval; |
| 6408 | | − next(); |
| 6365 | + |
| 6409 | 6366 | skip('('); |
| 6410 | 6367 | gexpr(); |
| 6411 | 6368 | skip(')'); |
| @@ -6416,7 +6373,6 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 4 unmodified lines |
| 6416 | 6373 | saved = cur_switch; |
| 6417 | 6374 | cur_switch = &sw; |
| 6418 | 6375 | block(&a, current_cleanups, csym, ccl, 0); |
| 6419 | | − nocode_wanted = saved_nocode_wanted; |
| 6420 | 6376 | a = gjmp(a); /* add implicit break */ |
| 6421 | 6377 | /* case lookup */ |
| 6422 | 6378 | gsym(b); |
| @@ -6437,13 +6393,11 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 14 unmodified lines |
| 6437 | 6393 | cur_switch = saved; |
| 6438 | 6394 | /* break label */ |
| 6439 | 6395 | gsym(a); |
| 6440 | | − } else |
| 6441 | | − if (tok == TOK_CASE) { |
| 6396 | + |
| 6397 | + } else if (t == TOK_CASE) { |
| 6442 | 6398 | struct case_t *cr = tcc_malloc(sizeof(struct case_t)); |
| 6443 | 6399 | if (!cur_switch) |
| 6444 | 6400 | expect("switch"); |
| 6445 | | − nocode_wanted &= ~0x20000000; |
| 6446 | | − next(); |
| 6447 | 6401 | cr->v1 = cr->v2 = expr_const64(); |
| 6448 | 6402 | if (gnu_ext && tok == TOK_DOTS) { |
| 6449 | 6403 | next(); |
| @@ -6451,25 +6405,23 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 1 unmodified line |
| 6451 | 6405 | if (cr->v2 < cr->v1) |
| 6452 | 6406 | tcc_warning("empty case range"); |
| 6453 | 6407 | } |
| 6454 | | − cr->sym = ind; |
| 6408 | + cr->sym = gind(); |
| 6455 | 6409 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); |
| 6456 | 6410 | skip(':'); |
| 6457 | 6411 | is_expr = 0; |
| 6458 | 6412 | goto block_after_label; |
| 6459 | | − } else |
| 6460 | | − if (tok == TOK_DEFAULT) { |
| 6461 | | − next(); |
| 6462 | | − skip(':'); |
| 6413 | + |
| 6414 | + } else if (t == TOK_DEFAULT) { |
| 6463 | 6415 | if (!cur_switch) |
| 6464 | 6416 | expect("switch"); |
| 6465 | 6417 | if (cur_switch->def_sym) |
| 6466 | 6418 | tcc_error("too many 'default'"); |
| 6467 | | − cur_switch->def_sym = ind; |
| 6419 | + cur_switch->def_sym = gind(); |
| 6420 | + skip(':'); |
| 6468 | 6421 | is_expr = 0; |
| 6469 | 6422 | goto block_after_label; |
| 6470 | | − } else |
| 6471 | | − if (tok == TOK_GOTO) { |
| 6472 | | − next(); |
| 6423 | + |
| 6424 | + } else if (t == TOK_GOTO) { |
| 6473 | 6425 | if (tok == '*' && gnu_ext) { |
| 6474 | 6426 | /* computed goto */ |
| 6475 | 6427 | next(); |
| @@ -6500,18 +6452,20 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 24 unmodified lines |
| 6500 | 6452 | gjmp_addr(s->jnext); |
| 6501 | 6453 | } |
| 6502 | 6454 | next(); |
| 6503 | | − } else { |
| 6455 | + |
| 6456 | + } else { |
| 6504 | 6457 | expect("label identifier"); |
| 6505 | 6458 | } |
| 6506 | 6459 | skip(';'); |
| 6507 | | − } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) { |
| 6460 | + |
| 6461 | + } else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) { |
| 6508 | 6462 | asm_instr(); |
| 6463 | + |
| 6509 | 6464 | } else { |
| 6510 | | − b = is_label(); |
| 6511 | | − if (b) { |
| 6465 | + if (tok == ':' && t >= TOK_UIDENT) { |
| 6512 | 6466 | /* label case */ |
| 6513 | 6467 | next(); |
| 6514 | | − s = label_find(b); |
| 6468 | + s = label_find(t); |
| 6515 | 6469 | if (s) { |
| 6516 | 6470 | if (s->r == LABEL_DEFINED) |
| 6517 | 6471 | tcc_error("duplicate label '%s'", get_tok_str(s->v, NULL)); |
| @@ -6524,14 +6478,14 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 6 unmodified lines |
| 6524 | 6478 | } else |
| 6525 | 6479 | gsym(s->jnext); |
| 6526 | 6480 | } else { |
| 6527 | | − s = label_push(&global_label_stack, b, LABEL_DEFINED); |
| 6481 | + s = label_push(&global_label_stack, t, LABEL_DEFINED); |
| 6528 | 6482 | } |
| 6529 | | − s->jnext = ind; |
| 6530 | | − s->cleanupstate = current_cleanups; |
| 6483 | + s->jnext = gind(); |
| 6484 | + s->cleanupstate = current_cleanups; |
| 6485 | + |
| 6486 | + block_after_label: |
| 6531 | 6487 | vla_sp_restore(); |
| 6532 | 6488 | /* we accept this, but it is a mistake */ |
| 6533 | | − block_after_label: |
| 6534 | | − nocode_wanted &= ~0x20000000; |
| 6535 | 6489 | if (tok == '}') { |
| 6536 | 6490 | tcc_warning("deprecated use of label at end of compound statement"); |
| 6537 | 6491 | } else { |
| @@ -6539,9 +6493,11 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 1 unmodified line |
| 6539 | 6493 | vpop(); |
| 6540 | 6494 | block(bsym, bcl, csym, ccl, is_expr); |
| 6541 | 6495 | } |
| 6496 | + |
| 6542 | 6497 | } else { |
| 6543 | 6498 | /* expression case */ |
| 6544 | | − if (tok != ';') { |
| 6499 | + if (t != ';') { |
| 6500 | + unget_tok(t); |
| 6545 | 6501 | if (is_expr) { |
| 6546 | 6502 | vpop(); |
| 6547 | 6503 | gexpr(); |
| @@ -6549,8 +6505,8 @@ static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr) · 1 unmodified line |
| 6549 | 6505 | gexpr(); |
| 6550 | 6506 | vpop(); |
| 6551 | 6507 | } |
| 6508 | + skip(';'); |
| 6552 | 6509 | } |
| 6553 | | − skip(';'); |
| 6554 | 6510 | } |
| 6555 | 6511 | } |
| 6556 | 6512 | } |
| @@ -6661,10 +6617,17 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 104 unmodified lines |
| 6661 | 6617 | |
| 6662 | 6618 | elem_size = 0; |
| 6663 | 6619 | nb_elems = 1; |
| 6620 | + |
| 6664 | 6621 | if (flags & DIF_HAVE_ELEM) |
| 6665 | 6622 | goto no_designator; |
| 6666 | | − if (gnu_ext && (l = is_label()) != 0) |
| 6667 | | − goto struct_field; |
| 6623 | + |
| 6624 | + if (gnu_ext && tok >= TOK_UIDENT) { |
| 6625 | + l = tok, next(); |
| 6626 | + if (tok == ':') |
| 6627 | + goto struct_field; |
| 6628 | + unget_tok(l); |
| 6629 | + } |
| 6630 | + |
| 6668 | 6631 | /* NOTE: we only support ranges for last designator */ |
| 6669 | 6632 | while (nb_elems == 1 && (tok == '[' || tok == '.')) { |
| 6670 | 6633 | if (tok == '[') { |
| @@ -7413,19 +7376,10 @@ static void gen_function(Sym *sym) · 742 unmodified lines |
| 7413 | 7376 | gfunc_prolog(&sym->type); |
| 7414 | 7377 | reset_local_scope(); |
| 7415 | 7378 | rsym = 0; |
| 7416 | | − clear_temp_local_var_list(); |
| 7417 | | − block(NULL, NULL, NULL, NULL, 0); |
| 7418 | | − if (!(nocode_wanted & 0x20000000) |
| 7419 | | − && ((func_vt.t & VT_BTYPE) == VT_INT) |
| 7420 | | − && !strcmp (funcname, "main")) |
| 7421 | | − { |
| 7422 | | − nocode_wanted = 0; |
| 7423 | | − vpushi(0); |
| 7424 | | − gen_assign_cast(&func_vt); |
| 7425 | | − gfunc_return(&func_vt); |
| 7426 | | − } |
| 7427 | | − nocode_wanted = 0; |
| 7379 | + clear_temp_local_var_list(); |
| 7380 | + block(NULL, NULL, NULL, NULL, 0); |
| 7428 | 7381 | gsym(rsym); |
| 7382 | + nocode_wanted = 0; |
| 7429 | 7383 | gfunc_epilog(); |
| 7430 | 7384 | cur_text_section->data_offset = ind; |
| 7431 | 7385 | label_pop(&global_label_stack, NULL, 0); |
| @@ -7746,3 +7700,6 @@ static void decl(int l) · 314 unmodified lines |
| 7746 | 7700 | } |
| 7747 | 7701 | |
| 7748 | 7702 | /* ------------------------------------------------------------------------- */ |
| 7703 | +#undef gjmp_addr |
| 7704 | +#undef gjmp |
| 7705 | +/* ------------------------------------------------------------------------- */ |