commit a71f0ed6bf7bac612633c2c2b745d6bf2b45d314
parent 99f65931e88b3a22b2bd5e9e88bf6798c529023c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 6 Oct 2015 18:27:08 +0200
Fix readint()
C99 imposes crazy rules in integer constant expressions, which
are different for decimal constants.
Diffstat:
M | cc1/lex.c | | | 46 | +++++++++++++++++++++++++++------------------- |
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -258,40 +258,44 @@ tok2str(void)
}
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 @@ readint(char *s, int base, Symbol *sym)
sym->u.u = u;
return sym;
+
+overflow:
+ errorp("overflow in integer constant");
+ return sym;
}
static unsigned
@@ -333,7 +341,7 @@ convert:
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;
}