scc

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

commit 585dc6d025dabe3e95271084e27e6c833c8c3dbf
parent 0e78d39ed924847e4e78662581c43ffdbe0d1ef4
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 22 Jul 2015 10:51:43 +0200

Make enumerations usable

Diffstat:
Mcc1/TODO | 2--
Mcc1/cc1.h | 3++-
Mcc1/decl.c | 37+++++++++++++++++++++++--------------
Mcc1/lex.c | 4++++
Mcc1/types.c | 23+++++++++++++++++++----
5 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/cc1/TODO b/cc1/TODO @@ -2,7 +2,6 @@ * Verify correctness in initializators * emit initializators * emit structures definition -* Assign const expression value to enum members * Define array types based in the value of constant expressions * Rewrite decl.c and use only one decl function with a function pointer parameter @@ -13,7 +12,6 @@ * Rewrite error recovery code, and ensure correct state after recovery * Allow comparisions between pointers and 0 * Implement function calls -* Implement enum type in eqtype() * Parse correctly all integer and float constants * Add C99 features (almost all the new features of C99 are missed) * Add correct emit for any kind of constant diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -130,7 +130,8 @@ enum { ISFIELD = 32, ISPARAM = 64, ISEXTERN = 128, - ISUSED = 256 + ISUSED = 256, + ISCONSTANT = 512 }; diff --git a/cc1/decl.c b/cc1/decl.c @@ -295,7 +295,7 @@ static Symbol * newtag(void) { Symbol *sym; - unsigned tag = yylval.token; + int op, tag = yylval.token; static unsigned ns = NS_STRUCTS; setnamespace(NS_TAG); @@ -304,6 +304,7 @@ newtag(void) case IDEN: case TYPEIDEN: sym = yylval.sym; + install(NS_TAG); next(); break; default: @@ -318,8 +319,8 @@ newtag(void) } sym->flags |= ISDEFINED; - if (sym->type->op != tag) - error("'%s' defined as wrong kind of tag", yytext); + if ((op = sym->type->op) != tag && op != INT) + error("'%s' defined as wrong kind of tag", sym->name); return sym; } @@ -390,28 +391,36 @@ static Type * enumdcl(void) { Type *tp; - Symbol *sym; - int val = 0; + Symbol *sym, *tagsym; + int val; - tp = newtag()->type; + tagsym = newtag(); + tp = tagsym->type; - if (yytoken == ';') + if (!accept('{')) return tp; - - expect('{'); if (tp->defined) - error("redefinition of enumeration '%s'", yytext); + error("redefinition of enumeration '%s'", tagsym->name); tp->defined = 1; - while (yytoken != '}') { + for (val = 0; yytoken != ')'; ++val) { if (yytoken != IDEN) unexpected(); if ((sym = install(NS_IDEN)) == NULL) error("'%s' redeclared as different kind of symbol", yytext); next(); + sym->flags |= ISCONSTANT; sym->type = inttype; - if (accept('=')) - constexpr(); - sym->u.i = val++; + if (accept('=')) { + Node *np = constexpr(); + /* + * TODO: check that the type of the constant + * expression is the correct, that in this + * case should be int + */ + val = np->sym->u.i; + freetree(np); + } + sym->u.i = val; if (!accept(',')) break; } diff --git a/cc1/lex.c b/cc1/lex.c @@ -231,6 +231,7 @@ convert: tp = ctype(INT, sign, size); sym = newsym(NS_IDEN); sym->type = tp; + sym->flags |= ISCONSTANT; v = strtol(s, NULL, base); if (tp == inttype) sym->u.i = v; @@ -358,6 +359,7 @@ repeat: yylen = bp - yytext + 1; yylval.sym = newsym(NS_IDEN); + yylval.sym->flags |= ISCONSTANT; yylval.sym->u.s = xstrdup(yytext+1); yylval.sym->type = mktype(chartype, ARY, yylen - 2, NULL); *bp++ = '"'; @@ -387,6 +389,8 @@ iden(void) */ sym = nextsym(sym, lex_ns); } + if (sym->flags & ISCONSTANT) + return CONSTANT; if (sym->token != IDEN) yylval.token = sym->u.token; return sym->token; diff --git a/cc1/types.c b/cc1/types.c @@ -292,10 +292,25 @@ mktype(Type *tp, unsigned op, short nelem, void *data) type.n.elem = nelem; type.ns = 0; - if (op == ARY && nelem == 0 || op == STRUCT || op == UNION) - type.defined = 0; - else + + switch (op) { + case ARY: + if (nelem == 0) + goto no_defined; + /* PASSTROUGH */ + case FTN: + case PTR: type.defined = 1; + break; + case ENUM: + type.printed = 1; + /* PASSTROUGH */ + case STRUCT: + case UNION: + no_defined: + type.defined = 0; + break; + } t = (op ^ (uintptr_t) tp >> 3) & NR_TYPE_HASH-1; tbl = &typetab[t]; @@ -336,7 +351,7 @@ eqtype(Type *tp1, Type *tp2) } return 1; case ENUM: - /* TODO: Check when two enum are the same type */ + break; case INT: case FLOAT: return tp1->letter == tp2->letter; default: