summaryrefslogtreecommitdiff
path: root/gcc/cexp.y
diff options
context:
space:
mode:
authorrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>1992-09-14 20:38:33 +0000
committerrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>1992-09-14 20:38:33 +0000
commit9569410121016c70ca064616bd36b3385a6c5062 (patch)
treed38935535237884a1672d0a8d46282d119a85932 /gcc/cexp.y
parentec0a9fd88edcab2e802578614f997f9225d099f1 (diff)
downloadgcc-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.y47
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;