scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 3dca060d1ad6e41aa5ec4c4bc26bfff2fff54a1d
parent af0a60913386396971fb0c4311370d68ae247c26
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 11 Jul 2014 09:50:31 +0200

Allow labels with same name that a previous typedef

Labels have a separate namespace, so it is correct this combination,
but the problem is the lexer returns a different token for an
identifier after a typedef for it. For example:

	main()
	{
		typedef int pepe;

	pepe:	return 0;
	}

The easier solution is a hack, where we modify the grammar to
accept an IDEN or a TYPE when creating labels.

Diffstat:
Mcc1/stmt.c | 26+++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -170,11 +170,16 @@ static void stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch); static void Label(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) { - emitlabel(label(yytext, 1)); - - expect(IDEN); - expect(':'); - stmt(lbreak, lcont, lswitch); + switch (yytoken) { + case IDEN: case TYPE: + emitlabel(label(yytext, 1)); + next(); + expect(':'); + stmt(lbreak, lcont, lswitch); + break; + default: + unexpected(); + } } static void @@ -297,10 +302,15 @@ compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) case '}': next(); return; - case TYPE: case SCLASS: case TQUALIFIER: + case TYPE: + if (ahead() == ':') + goto statement; + /* pass through */ + case SCLASS: case TQUALIFIER: decl(); break; default: + statement: stmt(lbreak, lcont, lswitch); } } @@ -325,7 +335,9 @@ stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) case CASE: fun = Case; break; case DEFAULT: fun = Default; break; default: fun = stmtexp; break; - case IDEN: fun = (ahead() == ':') ? Label : stmtexp; break; + case TYPE: case IDEN: + fun = (ahead() == ':') ? Label : stmtexp; + break; } (*fun)(lbreak, lcont, lswitch); }