diff options
author | rms <rms@138bc75d-0d04-0410-961f-82ee72b054a4> | 1992-09-14 20:38:33 +0000 |
---|---|---|
committer | rms <rms@138bc75d-0d04-0410-961f-82ee72b054a4> | 1992-09-14 20:38:33 +0000 |
commit | 9569410121016c70ca064616bd36b3385a6c5062 (patch) | |
tree | d38935535237884a1672d0a8d46282d119a85932 /gcc/cexp.y | |
parent | ec0a9fd88edcab2e802578614f997f9225d099f1 (diff) | |
download | gcc-9569410121016c70ca064616bd36b3385a6c5062.tar.gz |
(parse_number): Diagnose integer constants that are too large.
Diagnose duplicate `l' and `u' suffixes. Diagnose ` 0x ' and ` 0a '.
Warn about integer constants that are so large that they are unsigned.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@2121 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cexp.y')
-rw-r--r-- | gcc/cexp.y | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/gcc/cexp.y b/gcc/cexp.y index 5041f4bf0af..4cb3674e42c 100644 --- a/gcc/cexp.y +++ b/gcc/cexp.y @@ -342,10 +342,12 @@ parse_number (olen) int olen; { register char *p = lexptr; - register long n = 0; register int c; + register unsigned long n = 0, nd, ULONG_MAX_over_base; register int base = 10; register int len = olen; + register int overflow = 0; + int spec_long = 0; for (c = 0; c < len; c++) if (p[c] == '.') { @@ -364,31 +366,43 @@ parse_number (olen) else if (*p == '0') base = 8; - while (len > 0) { + ULONG_MAX_over_base = (unsigned long) -1 / base; + + for (; len > 0; len--) { c = *p++; - len--; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; if (c >= '0' && c <= '9') { - n *= base; - n += c - '0'; + overflow |= ULONG_MAX_over_base < n; + nd = n * base + c - '0'; + overflow |= nd < n; + n = nd; } else if (base == 16 && c >= 'a' && c <= 'f') { - n *= base; - n += c - 'a' + 10; + overflow |= ULONG_MAX_over_base < n; + nd = n * 16 + c - 'a' + 10; + overflow |= nd < n; + n = nd; } else { /* `l' means long, and `u' means unsigned. */ while (1) { if (c == 'l' || c == 'L') - ; + { + if (spec_long) + yyerror ("two `l's in integer constant"); + spec_long = 1; + } else if (c == 'u' || c == 'U') - yylval.integer.unsignedp = 1; + { + if (yylval.integer.unsignedp) + yyerror ("two `u's in integer constant"); + yylval.integer.unsignedp = 1; + } else break; - if (len == 0) + if (--len == 0) break; c = *p++; - len--; } /* Don't look for any more digits after the suffixes. */ break; @@ -400,9 +414,16 @@ parse_number (olen) return ERROR; } + if (overflow) + warning ("integer constant out of range"); + /* If too big to be signed, consider it unsigned. */ - if (n < 0) - yylval.integer.unsignedp = 1; + if ((long) n < 0 && ! yylval.integer.unsignedp) + { + if (base == 10) + warning ("integer constant is so large that it is unsigned"); + yylval.integer.unsignedp = 1; + } lexptr = p; yylval.integer.value = n; |