diff --git a/tcc.h b/tcc.h index 47c3c5f..8b56516 100644 --- a/tcc.h +++ b/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); diff --git a/tccgen.c b/tccgen.c index c3185ca..f733598 100644 --- a/tccgen.c +++ b/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); diff --git a/tccpp.c b/tccpp.c index 99d3c0a..9ac98a6 100644 --- a/tccpp.c +++ b/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 */ diff --git a/tests/tcctest.c b/tests/tcctest.c index 10203ec..f657c14 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -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)