scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit b98160148d250038b96881edf166880a2eb3d76e
parent bbb23c1bab015ae2a89d19ce00d2c29894ec8904
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 31 Oct 2013 07:18:38 +0100

Split type definition and storage definition

The storage definition is a charatheristic of the variable, and
not of the type. We have the storage definition en the ctype
struct, and it caused that any type assignation destroyed the
storage definition. This change symplify dealing with forward
declarations.

Diffstat:
decl.c | 37+++++++++++++++++++++----------------
lex.c | 4++--
symbol.h | 23+++++++++++++----------
types.c | 94++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
4 files changed, 88 insertions(+), 70 deletions(-)

diff --git a/decl.c b/decl.c @@ -75,18 +75,20 @@ aggregate(register struct ctype *tp) tp->sym = sym; } -static bool specifier(struct ctype *); +static bool specifier(struct ctype *, struct storage *); static struct ctype * fielddcl(unsigned char ns) { struct ctype base; + struct storage store; register struct ctype *tp; initctype(&base); - specifier(&base); + initstore(&store); + specifier(&base, &store); - if (HAS_STORAGE(&base)) + if (store.defined) error("storage specifier in a struct/union field declaration"); do { @@ -164,13 +166,13 @@ enumdcl(struct ctype *base) } bool -specifier(register struct ctype *tp) +specifier(register struct ctype *tp, register struct storage *store) { for (;; next()) { switch (yytoken) { case TYPEDEF: case EXTERN: case STATIC: case AUTO: case REGISTER: case CONST: case VOLATILE: - tp = storage(tp, yytoken); + store = storage(store, yytoken); break; case UNSIGNED: case SIGNED: case COMPLEX: case IMAGINARY: @@ -188,11 +190,11 @@ specifier(register struct ctype *tp) next(); return structdcl(tp); case IDEN: - if (!tp->tdef && !tp->sdef) { + if (!tp->defined && !store->defined) { register struct symbol *sym; sym = lookup(yytext, NS_IDEN); - if (sym->ctype && sym->ctype->c_typedef) { + if (sym->ctype && sym->store.c_typedef) { tp = ctype(tp, TYPEDEF); tp->base = sym->ctype; break; @@ -201,15 +203,15 @@ specifier(register struct ctype *tp) /* it is not a type name */ default: check_type: - if (!tp->tdef && !tp->sdef) { + /* TODO: simplify this checks */ + if (!tp->defined && !store->defined) { /* TODO: Allow no type in structs and union */ if (curctx != CTX_OUTER || yytoken != IDEN) return false; - tp = ctype(tp, INT); - tp = storage(tp, STATIC); + store->c_auto = false; warn(options.implicit, - "data definition has no type or storage class"); - } else if (!tp->tdef) { + "data definition has no type or storage class"); + } else if (!tp->defined) { warn(options.implicit, "type defaults to 'int' in declaration"); tp = ctype(tp, INT); @@ -282,7 +284,7 @@ initializer(register struct ctype *tp) } static struct node * -listdcl(struct ctype *base) +listdcl(struct ctype *base, struct storage *store) { struct compound c; @@ -293,6 +295,7 @@ listdcl(struct ctype *base) register struct ctype *tp; declarator(base, NS_IDEN); + cursym->store = *store; tp = cursym->ctype = decl_type(base); if ((tp->type == STRUCT || tp->type == UNION) && tp->forward) error("declaration of variable with incomplete type"); @@ -314,11 +317,13 @@ struct node * decl(void) { struct ctype base; + struct storage store; struct node *np; repeat: initctype(&base); + initstore(&store); - if (!specifier(&base)) + if (!specifier(&base, &store)) return NULL; if (accept(';')) { @@ -326,7 +331,7 @@ repeat: initctype(&base); switch (type) { case STRUCT: case UNION: case ENUM: - if (HAS_STORAGE(&base) || HAS_QUALIF(&base)) { + if (store.defined) { warn(options.useless, "useless storage class specifier in empty declaration"); } @@ -340,7 +345,7 @@ repeat: initctype(&base); } goto repeat; } - np = listdcl(&base); + np = listdcl(&base, &store); return np; } diff --git a/lex.c b/lex.c @@ -31,12 +31,12 @@ struct symbol *yyval; struct symbol * integer(char *s, char base) { - register struct ctype *tp; + static struct ctype *tp; register struct symbol *sym; static long long v; static char ch; - tp = ctype(NULL, INT); + tp = initctype(xmalloc(sizeof(*tp))); type: switch (ch = toupper(getc(yyin))) { case 'L': diff --git a/symbol.h b/symbol.h @@ -17,8 +17,7 @@ enum { NS_TAG }; -struct ctype { - unsigned type : 5; +struct storage { bool c_typedef : 1; bool c_extern : 1; bool c_static : 1; @@ -26,12 +25,18 @@ struct ctype { bool c_register : 1; bool c_const : 1; bool c_volatile : 1; + bool defined: 1; +}; + +struct ctype { + unsigned type : 5; + bool c_const : 1; bool c_restrict : 1; + bool c_volatile : 1; bool c_unsigned : 1; bool c_signed : 1; bool forward : 1; - bool tdef: 1; - bool sdef: 1; + bool defined: 1; union { unsigned len; struct { @@ -44,6 +49,7 @@ struct ctype { struct symbol { struct ctype *ctype; + struct storage store; unsigned char ctx; unsigned char ns; char *name; @@ -61,10 +67,6 @@ struct symbol { struct symbol *hash; }; -#define HAS_STORAGE(tp) ((tp)->c_extern || (tp)->c_static ||\ - (tp)->c_auto || (tp)->c_register || (tp)->c_typedef) - -#define HAS_QUALIF(tp) ((tp)->c_const || (tp)->c_volatile) extern struct ctype *decl_type(struct ctype *t); extern void pushtype(unsigned mod); @@ -74,10 +76,11 @@ extern void del_ctx(void); extern void freesyms(void); extern struct symbol *lookup(const char *s, signed char ns); extern void insert(struct symbol *sym, unsigned char ctx); -extern struct ctype *storage(struct ctype *tp, unsigned char mod); +extern struct storage *storage(struct storage *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); +extern struct ctype *initctype(register struct ctype *tp); +extern struct storage *initstore(register struct storage *store); #ifndef NDEBUG extern void ptype(register struct ctype *t); diff --git a/types.c b/types.c @@ -12,11 +12,21 @@ static unsigned char stack[NR_DECLARATORS]; static unsigned char *stackp = stack; -void +struct ctype * initctype(register struct ctype *tp) { memset(tp, 0, sizeof(*tp)); + tp->type = INT; tp->forward = 1; + return tp; +} + +struct storage * +initstore(register struct storage *store) +{ + memset(store, 0, sizeof(*store)); + store->c_auto = 1; + return store; } void @@ -60,7 +70,6 @@ mktype(register struct ctype *tp, unsigned char op) default: assert(0); } - tp->tdef = 1; return tp; } @@ -88,12 +97,13 @@ ctype(struct ctype *tp, unsigned char tok) { register unsigned char type; - if (!tp) { - tp = xmalloc(sizeof(*tp)); - initctype(tp); + if (!tp->defined) { + tp->type = 0; + tp->defined = 1; } - type = tp->type; + + switch (tok) { case VOID: case BOOL: case STRUCT: case UNION: case ENUM: case BITFLD: if (type) @@ -175,7 +185,6 @@ check_sign: switch (type) { default: assert(0); } - tp->tdef = 1; tp->type = type; return tp; @@ -189,76 +198,77 @@ two_or_more: error("two or more basic types"); } -struct ctype * -storage(register struct ctype *tp, unsigned char mod) +struct storage* +storage(register struct storage *sp, unsigned char mod) { extern unsigned char curctx; - if (!tp) { - tp = xmalloc(sizeof(*tp)); - initctype(tp); + if (!sp->defined) { + sp->c_auto = 0; + sp->defined = 1; } - tp->sdef = 1; switch (mod) { case TYPEDEF: - if (tp->c_typedef) + if (sp->c_typedef) goto duplicated; - if (tp->c_extern | tp->c_auto | tp->c_register | tp->c_static) + if (sp->c_extern | sp->c_auto | sp->c_register | sp->c_static) goto two_storage; - if (tp->c_const || tp->c_volatile) + if (sp->c_const || sp->c_volatile) goto bad_typedef; - tp->c_typedef = 1; - return tp; + sp->c_typedef = 1; + break; case EXTERN: - if (tp->c_extern) + if (sp->c_extern) goto duplicated; - if (tp->c_typedef | tp->c_auto | tp->c_register | tp->c_static) + if (sp->c_typedef | sp->c_auto | sp->c_register | sp->c_static) goto two_storage; - tp->c_extern = 1; - return tp; + sp->c_extern = 1; + break; case STATIC: - if (tp->c_static) + if (sp->c_static) goto duplicated; - if (tp->c_typedef | tp->c_extern | tp->c_auto | tp->c_register) + if (sp->c_typedef | sp->c_extern | sp->c_auto | sp->c_register) goto two_storage; - tp->c_static = 1; - return tp; + sp->c_static = 1; + break; case AUTO: if (curctx == CTX_OUTER) goto bad_file_scope_storage; - if (tp->c_typedef | tp->c_extern | tp->c_static |tp->c_register) + if (sp->c_typedef | sp->c_extern | sp->c_static |sp->c_register) goto two_storage; - if (tp->c_auto) + if (sp->c_auto) goto duplicated; - tp->c_static = 1; - return tp; + sp->c_static = 1; + break; case REGISTER: if (curctx == CTX_OUTER) goto bad_file_scope_storage; - if (tp->c_typedef | tp->c_extern | tp->c_auto | tp->c_static) + if (sp->c_typedef | sp->c_extern | sp->c_auto | sp->c_static) goto two_storage; - if (tp->c_register) + if (sp->c_register) goto duplicated; - tp->c_register = 1; - return tp; + sp->c_register = 1; + break; case CONST: - if (options.repeat && tp->c_const) + if (options.repeat && sp->c_const) goto duplicated; - if (tp->c_typedef) + if (sp->c_typedef) goto bad_typedef; - tp->c_const = 1; - return tp; + sp->c_const = 1; + break; case VOLATILE: - if (options.repeat && tp->c_volatile) + if (options.repeat && sp->c_volatile) goto duplicated; - if (tp->c_typedef) + if (sp->c_typedef) goto bad_typedef; - tp->c_volatile = 1; - return tp; + sp->c_volatile = 1; + break; default: assert(0); } + return sp; + bad_typedef: error("typedef specifies type qualifier"); bad_file_scope_storage: