shithub: scc

Download patch

ref: 6948a02f5fe8c3fea01ec49f314e68b6557e39e6
parent: d0edc9c7bc12d2a7a172e8be1ca44a671dca5d98
author: Roberto E. Vargas Caballero <[email protected]>
date: Fri Jul 5 12:48:38 EDT 2013

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.

--- a/decl.c
+++ b/decl.c
@@ -76,10 +76,9 @@
 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:
@@ -86,28 +85,13 @@
 			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 @@
 			return tp;
 		}
 	}
-invalid_sign:
-	error("invalid sign modifier");
 }
 
 static void
@@ -226,7 +208,8 @@
 			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,
--- a/symbol.h
+++ b/symbol.h
@@ -31,6 +31,7 @@
 	bool c_volatile : 1;
 	bool c_restrict : 1;
 	bool c_unsigned : 1;
+	bool c_signed : 1;
 	unsigned len;
 	struct ctype *base;
 	unsigned char refcnt;
--- a/types.c
+++ b/types.c
@@ -93,16 +93,13 @@
 
 	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;
+		type = tok;
+		if (tp->c_signed || tp->c_unsigned)
+			goto invalid_sign;
 		break;
-	case BOOL:
-		if (type)
-			goto two_or_more;
-		type = BOOL;
-		break;
 	case CHAR:
 		if (type)
 			goto two_or_more;
@@ -135,6 +132,8 @@
 		if (type)
 			goto two_or_more;
 		type = FLOAT;
+		if (tp->c_signed || tp->c_unsigned)
+			goto check_sign;
 		break;
 	case DOUBLE:
 		if (type)
@@ -143,7 +142,28 @@
 			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 @@
 	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");
 }