summaryrefslogtreecommitdiff
path: root/sys/src/cmd
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2020-08-08 11:39:25 -0700
committerOri Bernstein <ori@eigenstate.org>2020-08-08 11:39:25 -0700
commit3ba1d83d2026ebac616ab17a2126df97c0a7a24c (patch)
tree3e12014a4794de9a7c7745cdbf675e1896fe9fbe /sys/src/cmd
parentac4e21f52d8458732b6e18d6ca481ab880c6c9be (diff)
cc: promote integer constants according to c99 spec.
C99 integer constants with no type suffix promote differently depending on the way that they're written: hex and oct consts promote as int => uint => long => ulong => vlong => uvlong. Decimal constants are always signed. We used to promote all values to uint on overflow, and never went wider. This change fixes that, and adds a warning when a decimal constant that would have been promoted to uint in the past gets promoted to int.
Diffstat (limited to 'sys/src/cmd')
-rw-r--r--sys/src/cmd/8c/txt.c2
-rw-r--r--sys/src/cmd/cc/lex.c13
2 files changed, 12 insertions, 3 deletions
diff --git a/sys/src/cmd/8c/txt.c b/sys/src/cmd/8c/txt.c
index 4feb0f7f4..9ddeea6ba 100644
--- a/sys/src/cmd/8c/txt.c
+++ b/sys/src/cmd/8c/txt.c
@@ -865,7 +865,7 @@ gmove(Node *f, Node *t)
gmove(f, &fregnode0);
gins(AFADDD, nodfconst(-2147483648.), &fregnode0);
gins(AFMOVLP, f, &nod);
- gins(ASUBL, nodconst(-2147483648), &nod);
+ gins(ASUBL, nodconst(-0x80000000), &nod);
gmove(&nod, t);
return;
diff --git a/sys/src/cmd/cc/lex.c b/sys/src/cmd/cc/lex.c
index 15da69bee..26dc65201 100644
--- a/sys/src/cmd/cc/lex.c
+++ b/sys/src/cmd/cc/lex.c
@@ -444,7 +444,7 @@ long
yylex(void)
{
vlong vv;
- long c, c1, t;
+ long c, c1, t, w;
char *cp;
Rune rune;
Sym *s;
@@ -844,7 +844,16 @@ ncu:
yyerror("overflow in constant");
vv = yylval.vval;
- if(c1 & Numvlong) {
+ /*
+ * c99 is silly: decimal constants stay signed,
+ * hex and octal go unsigned before widening.
+ */
+ w = 32;
+ if((c1 & (Numdec|Numuns)) == Numdec)
+ w = 31;
+ if(c1 & Numvlong || (c1 & Numlong) == 0 && (uvlong)vv >= 1ULL<<w){
+ if((c1&(Numdec|Numvlong)) == Numdec && vv < 1ULL<<32)
+ warn(Z, "int constant widened to vlong: %s", symb);
if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
c = LUVLCONST;
t = TUVLONG;