[hackers] [scc] Add correct parsing of integer constants || Roberto E. Vargas Caballero
commit 609bb6b7743e8a37538a2701df3aaa3b652ebfb7
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Mon Sep 7 16:31:39 2015 +0200
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Mon Sep 7 16:31:39 2015 +0200
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.
diff --git a/cc1/fold.c b/cc1/fold.c
index a9e474e..d464173 100644
--- a/cc1/fold.c
+++ b/cc1/fold.c
_AT_@ -507,6 +507,7 @@ simplify(int op, Type *tp, Node *lp, Node *rp)
Node *
castcode(Node *np, Type *newtp)
{
+ TUINT mask;
Type *oldtp = np->type;
Symbol aux, *sym, *osym = np->sym;
_AT_@ -517,6 +518,7 @@ castcode(Node *np, Type *newtp)
case PTR:
case INT:
case ENUM:
+ mask = ones(newtp->size);
switch (oldtp->op) {
case PTR:
case INT:
_AT_@ -524,21 +526,25 @@ castcode(Node *np, Type *newtp)
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;
}
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:
diff --git a/cc1/lex.c b/cc1/lex.c
index 3df6ab1..0a4132a 100644
--- a/cc1/lex.c
+++ b/cc1/lex.c
_AT_@ -201,6 +201,55 @@ tok2str(void)
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)
{
_AT_@ -233,10 +282,7 @@ convert:
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;
}
diff --git a/cc1/types.c b/cc1/types.c
index 2c86d23..5f13f6f 100644
--- a/cc1/types.c
+++ b/cc1/types.c
_AT_@ -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
_AT_@ -53,6 +35,24 @@ static struct limits limits[][4] = {
}
},
{
+ { /* 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,
+ }
+ },
+ {
{
/* 0 = float 4 bytes */
.min.f = -1,
Received on Mon Sep 07 2015 - 16:55:29 CEST
This archive was generated by hypermail 2.3.0
: Mon Sep 07 2015 - 17:00:14 CEST