fix cleanup with break and continue

fix cleanup
This commit is contained in:
matthias 2019-04-29 11:18:57 +02:00
parent d30bc6d00a
commit 0d54946dec

View file

@ -94,7 +94,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
static void parse_expr_type(CType *type); static void parse_expr_type(CType *type);
static void init_putv(CType *type, Section *sec, unsigned long c); static void init_putv(CType *type, Section *sec, unsigned long c);
static void decl_initializer(CType *type, Section *sec, unsigned long c, int flags); static void decl_initializer(CType *type, Section *sec, unsigned long c, int flags);
static void block(int *bsym, int *csym, int is_expr); static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr);
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
static void decl(int l); static void decl(int l);
static int decl0(int l, int is_for_loop_init, Sym *); static int decl0(int l, int is_for_loop_init, Sym *);
@ -4891,7 +4891,7 @@ ST_FUNC void unary(void)
as statement expressions can't ever be entered from the as statement expressions can't ever be entered from the
outside, so any reactivation of code emission (from labels outside, so any reactivation of code emission (from labels
or loop heads) can be disabled again after the end of it. */ or loop heads) can be disabled again after the end of it. */
block(NULL, NULL, 1); block(NULL, NULL, NULL, NULL, 1);
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
skip(')'); skip(')');
} else { } else {
@ -6083,7 +6083,7 @@ static void gcase(struct case_t **base, int len, int *bsym)
} }
} }
static void block(int *bsym, int *csym, int is_expr) static void block(int *bsym, Sym *bcl, int *csym, Sym *ccl, int is_expr)
{ {
int a, b, c, d, cond; int a, b, c, d, cond;
Sym *s; Sym *s;
@ -6112,7 +6112,7 @@ static void block(int *bsym, int *csym, int is_expr)
a = gvtst(1, 0); a = gvtst(1, 0);
if (cond == 0) if (cond == 0)
nocode_wanted |= 0x20000000; nocode_wanted |= 0x20000000;
block(bsym, csym, 0); block(bsym, bcl, csym, ccl, 0);
if (cond != 1) if (cond != 1)
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
if (tok == TOK_ELSE) { if (tok == TOK_ELSE) {
@ -6121,7 +6121,7 @@ static void block(int *bsym, int *csym, int is_expr)
gsym(a); gsym(a);
if (cond == 1) if (cond == 1)
nocode_wanted |= 0x20000000; nocode_wanted |= 0x20000000;
block(bsym, csym, 0); block(bsym, bcl, csym, ccl, 0);
gsym(d); /* patch else jmp */ gsym(d); /* patch else jmp */
if (cond != 0) if (cond != 0)
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
@ -6140,7 +6140,7 @@ static void block(int *bsym, int *csym, int is_expr)
b = 0; b = 0;
++local_scope; ++local_scope;
saved_nocode_wanted = nocode_wanted; saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0); block(&a, current_cleanups, &b, current_cleanups, 0);
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
--local_scope; --local_scope;
gjmp_addr(d); gjmp_addr(d);
@ -6182,7 +6182,7 @@ static void block(int *bsym, int *csym, int is_expr)
if (tok != '}') { if (tok != '}') {
if (is_expr) if (is_expr)
vpop(); vpop();
block(bsym, csym, is_expr); block(bsym, bcl, csym, ccl, is_expr);
} }
} }
@ -6258,6 +6258,7 @@ static void block(int *bsym, int *csym, int is_expr)
/* compute jump */ /* compute jump */
if (!bsym) if (!bsym)
tcc_error("cannot break"); tcc_error("cannot break");
try_call_scope_cleanup(bcl);
*bsym = gjmp(*bsym); *bsym = gjmp(*bsym);
next(); next();
skip(';'); skip(';');
@ -6266,6 +6267,7 @@ static void block(int *bsym, int *csym, int is_expr)
/* compute jump */ /* compute jump */
if (!csym) if (!csym)
tcc_error("cannot continue"); tcc_error("cannot continue");
try_call_scope_cleanup(ccl);
vla_sp_restore_root(); vla_sp_restore_root();
*csym = gjmp(*csym); *csym = gjmp(*csym);
next(); next();
@ -6309,7 +6311,7 @@ static void block(int *bsym, int *csym, int is_expr)
} }
skip(')'); skip(')');
saved_nocode_wanted = nocode_wanted; saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0); block(&a, current_cleanups, &b, current_cleanups, 0);
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
gjmp_addr(c); gjmp_addr(c);
gsym(a); gsym(a);
@ -6327,7 +6329,7 @@ static void block(int *bsym, int *csym, int is_expr)
d = ind; d = ind;
vla_sp_restore(); vla_sp_restore();
saved_nocode_wanted = nocode_wanted; saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0); block(&a, current_cleanups, &b, current_cleanups, 0);
skip(TOK_WHILE); skip(TOK_WHILE);
skip('('); skip('(');
gsym(b); gsym(b);
@ -6355,7 +6357,7 @@ static void block(int *bsym, int *csym, int is_expr)
sw.p = NULL; sw.n = 0; sw.def_sym = 0; sw.p = NULL; sw.n = 0; sw.def_sym = 0;
saved = cur_switch; saved = cur_switch;
cur_switch = &sw; cur_switch = &sw;
block(&a, csym, 0); block(&a, current_cleanups, csym, ccl, 0);
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
a = gjmp(a); /* add implicit break */ a = gjmp(a); /* add implicit break */
/* case lookup */ /* case lookup */
@ -6477,7 +6479,7 @@ static void block(int *bsym, int *csym, int is_expr)
} else { } else {
if (is_expr) if (is_expr)
vpop(); vpop();
block(bsym, csym, is_expr); block(bsym, bcl, csym, ccl, is_expr);
} }
} else { } else {
/* expression case */ /* expression case */
@ -7357,7 +7359,7 @@ static void gen_function(Sym *sym)
reset_local_scope(); reset_local_scope();
rsym = 0; rsym = 0;
clear_temp_local_var_list(); clear_temp_local_var_list();
block(NULL, NULL, 0); block(NULL, NULL, NULL, NULL, 0);
if (!(nocode_wanted & 0x20000000) if (!(nocode_wanted & 0x20000000)
&& ((func_vt.t & VT_BTYPE) == VT_INT) && ((func_vt.t & VT_BTYPE) == VT_INT)
&& !strcmp (funcname, "main")) && !strcmp (funcname, "main"))