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.
This commit is contained in:
parent
ac4e21f52d
commit
3ba1d83d20
2 changed files with 12 additions and 3 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue