aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2012-04-15 22:17:51 +0200
committerMichael Matz <matz@suse.de>2012-04-18 20:57:13 +0200
commit15f4ac2b1a4453b73904bb2ff4441498d5911a64 (patch)
tree4907f114145ae9ef8be7a6a34bad1cca8728e6a7
parent1d0a5c251553d8d9199ad18d4780bf356f456298 (diff)
downloadtinycc-15f4ac2b1a4453b73904bb2ff4441498d5911a64.tar.gz
tinycc-15f4ac2b1a4453b73904bb2ff4441498d5911a64.tar.bz2
Fix detection of labels with a typedef name
This needs to be accepted: typedef int foo; void f (void) { foo: return; } namespaces for labels and types are different. The problem is that the block parser always tries to find a decl first and that routine doesn't peek enough to detect this case. Needs some adjustments to unget_tok() so that we can call it even when we already called it once, but next() didn't come around restoring the buffer yet. (It lazily does so not when the buffer becomes empty, but rather when the next call detects that the buffer is empty, i.e. it requires two next() calls until the unget buffer gets switched back).
-rw-r--r--tccgen.c21
-rw-r--r--tccpp.c12
-rw-r--r--tests/tcctest.c3
3 files changed, 33 insertions, 3 deletions
diff --git a/tccgen.c b/tccgen.c
index 2c759e1..6031611 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -4286,6 +4286,25 @@ static int is_label(void)
}
}
+static void label_or_decl(int l)
+{
+ int last_tok;
+
+ /* fast test first */
+ if (tok >= TOK_UIDENT)
+ {
+ /* no need to save tokc because tok is an identifier */
+ last_tok = tok;
+ next();
+ if (tok == ':') {
+ unget_tok(last_tok);
+ return;
+ }
+ unget_tok(last_tok);
+ }
+ decl(l);
+}
+
static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
int case_reg, int is_expr)
{
@@ -4359,7 +4378,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
}
}
while (tok != '}') {
- decl(VT_LOCAL);
+ label_or_decl(VT_LOCAL);
if (tok != '}') {
if (is_expr)
vpop();
diff --git a/tccpp.c b/tccpp.c
index 913bded..f3dd232 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -2995,8 +2995,16 @@ ST_INLN void unget_tok(int last_tok)
{
int i, n;
int *q;
- unget_saved_macro_ptr = macro_ptr;
- unget_buffer_enabled = 1;
+ if (unget_buffer_enabled)
+ {
+ /* assert(macro_ptr == unget_saved_buffer + 1);
+ assert(*macro_ptr == 0); */
+ }
+ else
+ {
+ unget_saved_macro_ptr = macro_ptr;
+ unget_buffer_enabled = 1;
+ }
q = unget_saved_buffer;
macro_ptr = q;
*q++ = tok;
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 03be501..eee7039 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -432,6 +432,7 @@ void loop_test()
printf("\n");
}
+typedef int typedef_and_label;
void goto_test()
{
@@ -440,6 +441,8 @@ void goto_test()
printf("goto:\n");
i = 0;
+ /* This needs to parse as label, not as start of decl. */
+ typedef_and_label:
s_loop:
if (i >= 10)
goto s_end;