scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit bbb23c1bab015ae2a89d19ce00d2c29894ec8904
parent b0126dcc1e00f427b21754693c8d6dcbf5101e58
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 30 Oct 2013 21:21:27 +0100

Pass type struct to specifier

This is the first step for removing the storage specifier
from the type struct. We need this step because we will
have a pointer to the type and a pointer to the storage,
while specifier was a void function returning a pointer
to ctype, and it is no longer valid.

This change implies we can not test against NULL in specifier,
because it is not going to be true anymore, so we introduce two
new fields, that indicate if type or storage are defined. This
fields are going to be splitted later in two different structs.

Diffstat:
Mdecl.c | 56+++++++++++++++++++++++++++-----------------------------
Msymbol.h | 3+++
Mtypes.c | 6++++++
3 files changed, 36 insertions(+), 29 deletions(-)

diff --git a/decl.c b/decl.c @@ -75,24 +75,23 @@ aggregate(register struct ctype *tp) tp->sym = sym; } -static struct ctype *specifier(void); +static bool specifier(struct ctype *); static struct ctype * fielddcl(unsigned char ns) { - register struct ctype *tp, *base; + struct ctype base; + register struct ctype *tp; - if (!(base = specifier())) { - base = ctype(NULL, INT); - warn(options.implicit, - "data definition has no type or storage class"); - } - if (HAS_STORAGE(base)) + initctype(&base); + specifier(&base); + + if (HAS_STORAGE(&base)) error("storage specifier in a struct/union field declaration"); do { - declarator(base, ns); - tp = decl_type(base); + declarator(&base, ns); + tp = decl_type(&base); if (accept(':')) { expect(CONSTANT); switch (tp->type) { @@ -108,7 +107,6 @@ fielddcl(unsigned char ns) cursym->ctype = tp; } while (accept(',')); - delctype(base); expect(';'); return tp; } @@ -165,11 +163,9 @@ enumdcl(struct ctype *base) return base; } -struct ctype * -specifier(void) +bool +specifier(register struct ctype *tp) { - register struct ctype *tp = NULL; - for (;; next()) { switch (yytoken) { case TYPEDEF: case EXTERN: case STATIC: case AUTO: @@ -192,7 +188,7 @@ specifier(void) next(); return structdcl(tp); case IDEN: - if (!tp || !tp->type) { + if (!tp->tdef && !tp->sdef) { register struct symbol *sym; sym = lookup(yytext, NS_IDEN); @@ -205,16 +201,18 @@ specifier(void) /* it is not a type name */ default: check_type: - if (!tp) { + if (!tp->tdef && !tp->sdef) { + /* TODO: Allow no type in structs and union */ if (curctx != CTX_OUTER || yytoken != IDEN) - return NULL; + return false; tp = ctype(tp, INT); + tp = storage(tp, STATIC); warn(options.implicit, "data definition has no type or storage class"); - } else if (!tp->type) { + } else if (!tp->tdef) { warn(options.implicit, "type defaults to 'int' in declaration"); - tp->type = INT; + tp = ctype(tp, INT); } if (!tp->c_signed && !tp->c_unsigned) { switch (tp->type) { @@ -227,7 +225,7 @@ specifier(void) tp->c_signed = 1; } } - return tp; + return true; } } } @@ -315,22 +313,24 @@ listdcl(struct ctype *base) struct node * decl(void) { - register struct ctype *base; + struct ctype base; struct node *np; -repeat: if (!(base = specifier())) +repeat: initctype(&base); + + if (!specifier(&base)) return NULL; if (accept(';')) { - register unsigned char type = base->type; + register unsigned char type = base.type; switch (type) { case STRUCT: case UNION: case ENUM: - if (HAS_STORAGE(base) || HAS_QUALIF(base)) { + if (HAS_STORAGE(&base) || HAS_QUALIF(&base)) { warn(options.useless, "useless storage class specifier in empty declaration"); } - if (!base->sym && type != ENUM) { + if (base.sym && type != ENUM) { warn(options.useless, "unnamed struct/union that defines no instances"); } @@ -338,11 +338,9 @@ repeat: if (!(base = specifier())) warn(options.useless, "useless type name in empty declaration"); } - delctype(base); goto repeat; } - np = listdcl(base); - delctype(base); + np = listdcl(&base); return np; } diff --git a/symbol.h b/symbol.h @@ -30,6 +30,8 @@ struct ctype { bool c_unsigned : 1; bool c_signed : 1; bool forward : 1; + bool tdef: 1; + bool sdef: 1; union { unsigned len; struct { @@ -75,6 +77,7 @@ extern void insert(struct symbol *sym, unsigned char ctx); extern struct ctype *storage(struct ctype *tp, unsigned char mod); extern void delctype(struct ctype *tp); extern unsigned char hash(register const char *s); +extern void initctype(register struct ctype *tp); #ifndef NDEBUG extern void ptype(register struct ctype *t); diff --git a/types.c b/types.c @@ -60,6 +60,7 @@ mktype(register struct ctype *tp, unsigned char op) default: assert(0); } + tp->tdef = 1; return tp; } @@ -174,6 +175,7 @@ check_sign: switch (type) { default: assert(0); } + tp->tdef = 1; tp->type = type; return tp; @@ -196,6 +198,8 @@ storage(register struct ctype *tp, unsigned char mod) tp = xmalloc(sizeof(*tp)); initctype(tp); } + + tp->sdef = 1; switch (mod) { case TYPEDEF: if (tp->c_typedef) @@ -252,6 +256,8 @@ storage(register struct ctype *tp, unsigned char mod) goto bad_typedef; tp->c_volatile = 1; return tp; + default: + assert(0); } bad_typedef: error("typedef specifies type qualifier");