shithub: scc

Download patch

ref: a71f0ed6bf7bac612633c2c2b745d6bf2b45d314
parent: 99f65931e88b3a22b2bd5e9e88bf6798c529023c
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Oct 6 14:27:08 EDT 2015

Fix readint()

C99 imposes crazy rules in integer constant expressions, which
are different for decimal constants.

--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -258,40 +258,44 @@
 }
 
 static Symbol *
-readint(char *s, int base, Symbol *sym)
+readint(char *s, int base, int sign, Symbol *sym)
 {
 	Type *tp = sym->type;
-	struct limits *lim = getlimits(tp);
+	struct limits *lim;
 	TUINT u, val, max;
 	int c;
 
+	lim = getlimits(tp);
 	max = (tp->sign) ? lim->max.u : lim->max.i;
+	if (*s == '0')
+		++s;
+	if (toupper(*s) == 'X')
+		++s;
 
 	for (u = 0; isxdigit(c = *s++); u = u*base + val) {
 		val = (c <= '9') ? c - '0' :  10 + c - 'A';
+	repeat:
 		if (u <= max/base && u*base <= max - val)
 			continue;
 		if (tp->sign) {
-			if (tp == inttype) {
-				tp = longtype;
-			} else if (tp == longtype) {
-				tp == llongtype;
-			} else {
-				errorp("overflow in integer constant");
-				break;
-			}
+			if (tp == inttype)
+				tp = (base==10) ? longtype : uinttype;
+			else if (tp == longtype)
+				tp = (base==10) ? llongtype : ulongtype;
+			else
+				goto overflow;
 		} else {
-			if (tp == uinttype) {
-				tp = ulongtype;
-			} else if (tp == ulongtype) {
-				tp == ullongtype;
-			} else {
-				errorp("overflow in integer constant");
-				break;
-			}
+			if (tp == uinttype)
+				tp = (sign==UNSIGNED) ? ulongtype : longtype;
+			else if (tp == ulongtype)
+				tp = (sign==UNSIGNED) ? ullongtype : llongtype;
+			else
+				goto overflow;
 		}
 		sym->type = tp;
+		lim = getlimits(tp);
 		max = (tp->sign) ? lim->max.u : lim->max.i;
+		goto repeat;
 	}
 
 	if (tp->sign)
@@ -300,6 +304,10 @@
 		sym->u.u = u;
 
 	return sym;
+
+overflow:
+	errorp("overflow in integer constant");
+	return sym;
 }
 
 static unsigned
@@ -333,7 +341,7 @@
 	sym = newsym(NS_IDEN);
 	sym->type = tp;
 	sym->flags |= ISCONSTANT;
-	yylval.sym = readint(s, base, sym);
+	yylval.sym = readint(s, base, sign, sym);
 	return CONSTANT;
 }