scc

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

commit 6948a02f5fe8c3fea01ec49f314e68b6557e39e6
parent d0edc9c7bc12d2a7a172e8be1ca44a671dca5d98
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri,  5 Jul 2013 16:48:38 +0200

Check all the sign combinations in btype()

btype() is the function with the responsability of checking all the
conditions in the different combinations of types, so it is the
best place for checking the combinations of signess. In order to can
detec all the combinations we need a c_signed flag in the ctype
struct.

Diffstat:
Mdecl.c | 33++++++++-------------------------
Msymbol.h | 1+
Mtypes.c | 40+++++++++++++++++++++++++++++++++-------
3 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/decl.c b/decl.c @@ -76,38 +76,22 @@ dirdcl(register struct ctype *tp) struct ctype * spec(void) { - unsigned char sign; register struct ctype *tp = NULL; - for (sign = 0; ; next()) { + for (;; next()) { switch (yytoken) { case TYPEDEF: case EXTERN: case STATIC: case AUTO: case REGISTER: case CONST: case VOLATILE: tp = storage(tp, yytoken); break; case UNSIGNED: case SIGNED: - if (sign == yytoken) - error("duplicated '%s'", yytext); - if (sign) - error("both 'signed' and 'unsigned' in declaration specifiers"); - if (!tp) - tp = newctype(); - switch (tp->type) { - case FLOAT: case DOUBLE: case LDOUBLE: case BOOL: - goto invalid_sign; - } - if ((sign = yytoken) == UNSIGNED) - tp->c_unsigned = 1; - break; - case FLOAT: case DOUBLE: case BOOL: - if (sign) - goto invalid_sign; - case VOID: case CHAR: case SHORT: case INT: case LONG: + case FLOAT: case DOUBLE: case BOOL: + case VOID: case CHAR: case SHORT: + case INT: case ENUM: case LONG: + case STRUCT: case UNION: tp = btype(tp, yytoken); break; - case STRUCT: /* TODO */ - case UNION: /* TODO */ - case ENUM: /* TODO */ + /* TODO: ENUM, STRUCT, UNION */ case IDEN: if (!tp || !tp->type) { struct symbol *sym; @@ -133,8 +117,6 @@ spec(void) return tp; } } -invalid_sign: - error("invalid sign modifier"); } static void @@ -226,7 +208,8 @@ decl(void) goto end; tp = newctype(); tp->type = INT; - warning("data definition has no type or storage class"); + warning_error(options.implicit, + "data definition has no type or storage class"); } if (accept(';')) { warning_error(options.useless, diff --git a/symbol.h b/symbol.h @@ -31,6 +31,7 @@ struct ctype { bool c_volatile : 1; bool c_restrict : 1; bool c_unsigned : 1; + bool c_signed : 1; unsigned len; struct ctype *base; unsigned char refcnt; diff --git a/types.c b/types.c @@ -93,15 +93,12 @@ btype(struct ctype *tp, unsigned char tok) type = tp->type; switch (tok) { - case VOID: + case VOID: case BOOL: case STRUCT: case UNION: case ENUM: if (type) goto two_or_more;; - type = VOID; - break; - case BOOL: - if (type) - goto two_or_more; - type = BOOL; + type = tok; + if (tp->c_signed || tp->c_unsigned) + goto invalid_sign; break; case CHAR: if (type) @@ -135,6 +132,8 @@ btype(struct ctype *tp, unsigned char tok) if (type) goto two_or_more; type = FLOAT; + if (tp->c_signed || tp->c_unsigned) + goto check_sign; break; case DOUBLE: if (type) @@ -143,6 +142,27 @@ btype(struct ctype *tp, unsigned char tok) type = DOUBLE; else if (type == LONG) type = LDOUBLE; + if (tp->c_signed || tp->c_unsigned) + goto check_sign; + break; + case UNSIGNED: + if (tp->c_unsigned) + goto duplicated; + if (tp->c_signed) + goto both_sign; + tp->c_unsigned = 1; + goto check_sign; + case SIGNED: + if (tp->c_signed) + goto duplicated; + if (tp->c_unsigned) + goto both_sign; + tp->c_signed = 1; + +check_sign: switch (type) { + case VOID: case BOOL: case STRUCT: case UNION: case ENUM: + goto invalid_sign; + } break; default: assert(0); @@ -150,6 +170,12 @@ btype(struct ctype *tp, unsigned char tok) tp->type = type; return tp; +both_sign: + error("both 'signed' and 'unsigned' in declaration specifiers"); +duplicated: + error("duplicated '%s'", yytext); +invalid_sign: + error("invalid sign modifier"); two_or_more: error("two or more basic types"); }