ref: b98160148d250038b96881edf166880a2eb3d76e
parent: bbb23c1bab015ae2a89d19ce00d2c29894ec8904
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Oct 31 03:18:38 EDT 2013
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.
--- a/decl.c
+++ b/decl.c
@@ -75,18 +75,20 @@
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 @@
}
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 @@
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 @@
/* 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 @@
}
static struct node *
-listdcl(struct ctype *base)
+listdcl(struct ctype *base, struct storage *store)
{
struct compound c;
@@ -293,6 +295,7 @@
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 @@
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 @@
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 @@
}
goto repeat;
}
- np = listdcl(&base);
+ np = listdcl(&base, &store);
return np;
}
--- a/lex.c
+++ b/lex.c
@@ -31,12 +31,12 @@
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':
--- a/symbol.h
+++ b/symbol.h
@@ -17,8 +17,7 @@
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 @@
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 symbol {
struct ctype *ctype;
+ struct storage store;
unsigned char ctx;
unsigned char ns;
char *name;
@@ -61,11 +67,7 @@
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);
extern struct ctype *ctype(struct ctype *tp, unsigned char tok);
@@ -74,10 +76,11 @@
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);
--- a/types.c
+++ b/types.c
@@ -12,13 +12,23 @@
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
delctype(register struct ctype *tp)
{
@@ -60,7 +70,6 @@
default:
assert(0);
}
- tp->tdef = 1;
return tp;
}
@@ -88,12 +97,13 @@
{
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 @@
default:
assert(0);
}
- tp->tdef = 1;
tp->type = type;
return tp;
@@ -189,76 +198,77 @@
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: