scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

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:
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; }