Fix interaction of (local) labels and stmt exprs
as per testcase. We must not reset token.sym_label twice with kept symbols. This is no problem for non-label symbols because those aren't generated on demand when mentioning them.
This commit is contained in:
parent
6696da2f61
commit
096c93c0c6
3 changed files with 22 additions and 1 deletions
2
tcc.h
2
tcc.h
|
@ -575,6 +575,8 @@ typedef struct DLLReference {
|
||||||
#define LABEL_DEFINED 0 /* label is defined */
|
#define LABEL_DEFINED 0 /* label is defined */
|
||||||
#define LABEL_FORWARD 1 /* label is forward defined */
|
#define LABEL_FORWARD 1 /* label is forward defined */
|
||||||
#define LABEL_DECLARED 2 /* label is declared but never used */
|
#define LABEL_DECLARED 2 /* label is declared but never used */
|
||||||
|
#define LABEL_GONE 3 /* label isn't in scope, but not yet popped
|
||||||
|
from local_label_stack (stmt exprs) */
|
||||||
|
|
||||||
/* type_decl() types */
|
/* type_decl() types */
|
||||||
#define TYPE_ABSTRACT 1 /* type without variable */
|
#define TYPE_ABSTRACT 1 /* type without variable */
|
||||||
|
|
5
tccpp.c
5
tccpp.c
|
@ -1402,9 +1402,12 @@ ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* remove label */
|
/* remove label */
|
||||||
table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
|
if (s->r != LABEL_GONE)
|
||||||
|
table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
|
||||||
if (!keep)
|
if (!keep)
|
||||||
sym_free(s);
|
sym_free(s);
|
||||||
|
else
|
||||||
|
s->r = LABEL_GONE;
|
||||||
}
|
}
|
||||||
if (!keep)
|
if (!keep)
|
||||||
*ptop = slast;
|
*ptop = slast;
|
||||||
|
|
|
@ -3139,6 +3139,22 @@ void statement_expr_test(void)
|
||||||
|
|
||||||
/* Test that we can give out addresses of local labels. */
|
/* Test that we can give out addresses of local labels. */
|
||||||
consume_ulong(({ __label__ __here; __here: (unsigned long)&&__here; }));
|
consume_ulong(({ __label__ __here; __here: (unsigned long)&&__here; }));
|
||||||
|
|
||||||
|
/* Test interaction between local and global label stacks and the
|
||||||
|
need to defer popping symbol from them when within statement
|
||||||
|
expressions. Note how the labels are both named LBL. */
|
||||||
|
i = 0;
|
||||||
|
({
|
||||||
|
{
|
||||||
|
__label__ LBL;
|
||||||
|
LBL: if (i++ == 0) goto LBL;
|
||||||
|
}
|
||||||
|
/* jump to a classical label out of an expr-stmt that had previously
|
||||||
|
overshadowed that classical label */
|
||||||
|
goto LBL;
|
||||||
|
});
|
||||||
|
LBL:
|
||||||
|
printf("stmtexpr: %d should be 2\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void local_label_test(void)
|
void local_label_test(void)
|
||||||
|
|
Loading…
Reference in a new issue