ref: 609bb6b7743e8a37538a2701df3aaa3b652ebfb7
parent: 10faf603cace3ffda21153466dfbd9e672bcf656
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon Sep 7 12:31:39 EDT 2015
Add correct parsing of integer constants Until this moment there was no check of overflow, and there was no cast to bigger types when the constant was bigger than the type declared by the user.
--- a/cc1/fold.c
+++ b/cc1/fold.c
@@ -507,6 +507,7 @@
Node *
castcode(Node *np, Type *newtp)
{
+ TUINT mask;
Type *oldtp = np->type;
Symbol aux, *sym, *osym = np->sym;
@@ -517,6 +518,7 @@
case PTR:
case INT:
case ENUM:
+ mask = ones(newtp->size);
switch (oldtp->op) {
case PTR:
case INT:
@@ -524,15 +526,18 @@
if (newtp->sign == oldtp->sign)
aux.u = osym->u;
if (newtp->sign && !oldtp->sign)
- aux.u.i = osym->u.u;
+ aux.u.i = osym->u.u & mask;
else if (!newtp->sign && oldtp->sign)
- aux.u.u = osym->u.u;
+ aux.u.u = osym->u.u & mask;
break;
case FLOAT:
- if (newtp->sign)
+ if (newtp->sign) {
aux.u.i = osym->u.f;
- else
+ aux.u.i &= mask;
+ } else {
aux.u.u = osym->u.f;
+ aux.u.u &= mask;
+ }
break;
default:
goto noconstant;
@@ -539,6 +544,7 @@
}
break;
case FLOAT:
+ /* FIXME: The cast can be from another floar type */
aux.u.f = (oldtp->sign) ? osym->u.i : osym->u.u;
break;
default:
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -201,6 +201,55 @@
input->begin = input->p;
}
+static Symbol *
+readint(char *s, int base, Symbol *sym)
+{
+ Type *tp = sym->type;
+ struct limits *lim = getlimits(tp);
+ TUINT u, val, max, factor = 1;
+ int c;
+
+ max = (tp->sign) ? lim->max.u : lim->max.i;
+ switch (*s++) {
+ case '-': factor = -1; break;
+ default: --s;
+ case '+': factor = 1; break;
+ }
+
+ for (u = 0; isxdigit(c = *s++); u = u * base + val) {
+ val = (c <= '9') ? c - '0' : 10 + c - 'A';
+ if (u <= max/base + val)
+ continue;
+ if (tp->sign) {
+ if (tp == inttype)
+ tp = longtype;
+ else if (tp == longtype)
+ tp == llongtype;
+ else {
+ errorp("overflow in integer constant");
+ break;
+ }
+ } else {
+ if (tp == uinttype)
+ tp = ulongtype;
+ else if (tp == ulongtype)
+ tp == ullongtype;
+ else {
+ errorp("overflow in integer constant");
+ break;
+ }
+ }
+ sym->type = tp;
+ }
+
+ if (tp->sign)
+ sym->u.i = u * factor;
+ else
+ sym->u.u = u;
+
+ return sym;
+}
+
static unsigned
integer(char *s, char base)
{
@@ -233,10 +282,7 @@
sym = newsym(NS_IDEN);
sym->type = tp;
sym->flags |= ISCONSTANT;
- v = strtol(s, NULL, base);
- if (tp == inttype)
- sym->u.i = v;
- yylval.sym = sym;
+ yylval.sym = readint(s, base, sym);
return CONSTANT;
}
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -17,24 +17,6 @@
*/
static struct limits limits[][4] = {
{
- { /* 0 = signed 1 byte */
- .min.i = -127,
- .max.i = 127
- },
- { /* 1 = signed 2 byte */
- .min.i = -32767,
- .max.i = 327677
- },
- { /* 2 = signed 4 byte */
- .min.i = -2147483647L,
- .max.i = 2147483647L
- },
- { /* 3 = signed 8 byte */
- .min.i = -9223372036854775807LL,
- .max.i = 9223372036854775807LL,
- }
- },
- {
{ /* 0 = unsigned 1 byte */
.min.u = 0,
.max.u = 255
@@ -50,6 +32,24 @@
{ /* 3 = unsigned 4 bytes */
.min.u = 0,
.max.u = 18446744073709551615u
+ }
+ },
+ {
+ { /* 0 = signed 1 byte */
+ .min.i = -127,
+ .max.i = 127
+ },
+ { /* 1 = signed 2 byte */
+ .min.i = -32767,
+ .max.i = 32767
+ },
+ { /* 2 = signed 4 byte */
+ .min.i = -2147483647L,
+ .max.i = 2147483647L
+ },
+ { /* 3 = signed 8 byte */
+ .min.i = -9223372036854775807LL,
+ .max.i = 9223372036854775807LL,
}
},
{