From 3ba1d83d2026ebac616ab17a2126df97c0a7a24c Mon Sep 17 00:00:00 2001 From: Ori Bernstein Date: Sat, 8 Aug 2020 11:39:25 -0700 Subject: [PATCH] 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. --- sys/src/cmd/8c/txt.c | 2 +- sys/src/cmd/cc/lex.c | 13 +++++++++++-- 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<