diff options
author | Ori Bernstein <ori@eigenstate.org> | 2020-08-08 11:39:25 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2020-08-08 11:39:25 -0700 |
commit | 3ba1d83d2026ebac616ab17a2126df97c0a7a24c (patch) | |
tree | 3e12014a4794de9a7c7745cdbf675e1896fe9fbe /sys/src/cmd/cc | |
parent | ac4e21f52d8458732b6e18d6ca481ab880c6c9be (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/cc')
-rw-r--r-- | sys/src/cmd/cc/lex.c | 13 |
1 files changed, 11 insertions, 2 deletions
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; |