mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
Fix statement exprs returning a local label
Like returned local variables also labels local to a statement expression can be returned, and so their symbols must not be immediately freed (though they need to be removed from the symbol table).
This commit is contained in:
parent
2240422da9
commit
9bea88d616
2
tcc.h
2
tcc.h
@ -1234,7 +1234,7 @@ ST_INLN Sym *define_find(int v);
|
||||
ST_FUNC void free_defines(Sym *b);
|
||||
ST_FUNC Sym *label_find(int v);
|
||||
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags);
|
||||
ST_FUNC void label_pop(Sym **ptop, Sym *slast);
|
||||
ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep);
|
||||
ST_FUNC void parse_define(void);
|
||||
ST_FUNC void preprocess(int is_bof);
|
||||
ST_FUNC void next_nomacro(void);
|
||||
|
4
tccgen.c
4
tccgen.c
@ -5861,7 +5861,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
}
|
||||
}
|
||||
/* pop locally defined labels */
|
||||
label_pop(&local_label_stack, llabel);
|
||||
label_pop(&local_label_stack, llabel, is_expr);
|
||||
/* pop locally defined symbols */
|
||||
--local_scope;
|
||||
/* In the is_expr case (a statement expression is finished here),
|
||||
@ -6948,7 +6948,7 @@ static void gen_function(Sym *sym)
|
||||
gsym(rsym);
|
||||
gfunc_epilog();
|
||||
cur_text_section->data_offset = ind;
|
||||
label_pop(&global_label_stack, NULL);
|
||||
label_pop(&global_label_stack, NULL, 0);
|
||||
/* reset local stack */
|
||||
local_scope = 0;
|
||||
sym_pop(&local_stack, NULL, 0);
|
||||
|
8
tccpp.c
8
tccpp.c
@ -1376,7 +1376,7 @@ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
|
||||
|
||||
/* pop labels until element last is reached. Look if any labels are
|
||||
undefined. Define symbols if '&&label' was used. */
|
||||
ST_FUNC void label_pop(Sym **ptop, Sym *slast)
|
||||
ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep)
|
||||
{
|
||||
Sym *s, *s1;
|
||||
for(s = *ptop; s != slast; s = s1) {
|
||||
@ -1395,9 +1395,11 @@ ST_FUNC void label_pop(Sym **ptop, Sym *slast)
|
||||
}
|
||||
/* remove label */
|
||||
table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
|
||||
sym_free(s);
|
||||
if (!keep)
|
||||
sym_free(s);
|
||||
}
|
||||
*ptop = slast;
|
||||
if (!keep)
|
||||
*ptop = slast;
|
||||
}
|
||||
|
||||
/* eval an expression for #if/#elif */
|
||||
|
@ -2899,6 +2899,11 @@ struct hlist_head {
|
||||
struct hlist_node *first, *last;
|
||||
};
|
||||
|
||||
void consume_ulong (unsigned long i)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
void statement_expr_test(void)
|
||||
{
|
||||
int a, i;
|
||||
@ -2954,6 +2959,9 @@ void statement_expr_test(void)
|
||||
});
|
||||
printf ("stmtexpr: %d %d %d\n", t, b, c);
|
||||
printf ("stmtexpr: %ld %ld\n", (long)h.first, (long)h.last);
|
||||
|
||||
/* Test that we can give out addresses of local labels. */
|
||||
consume_ulong(({ __label__ __here; __here: (unsigned long)&&__here; }));
|
||||
}
|
||||
|
||||
void local_label_test(void)
|
||||
|
Loading…
Reference in New Issue
Block a user