* c-exp.y (parse_number): Check for overflow regardless of range

checking.  Fix overflow check to use unsigned LONGEST, not
	unsigned int.

	* c-exp.y (parse_number): Make it so that integer constants are
	builtin_type_long_long if builtin_type_long isn't big enough or if
	an "LL" suffix is used.  Properly handle "UL" or "LU" suffixes.
This commit is contained in:
Jim Kingdon
1994-01-15 17:14:18 +00:00
parent 2069bd10d5
commit a9b32d6192
2 changed files with 91 additions and 44 deletions

View File

@ -1,5 +1,13 @@
Sat Jan 15 10:20:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com) Sat Jan 15 10:20:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
* c-exp.y (parse_number): Check for overflow regardless of range
checking. Fix overflow check to use unsigned LONGEST, not
unsigned int.
* c-exp.y (parse_number): Make it so that integer constants are
builtin_type_long_long if builtin_type_long isn't big enough or if
an "LL" suffix is used. Properly handle "UL" or "LU" suffixes.
* c-typeprint.c (c_type_print_varspec_suffix, case TYPE_CODE_FUNC): * c-typeprint.c (c_type_print_varspec_suffix, case TYPE_CODE_FUNC):
Print our "()" first, then recurse for the target type. Print our "()" first, then recurse for the target type.
@ -31,7 +39,6 @@ Fri Jan 14 11:06:10 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
* config/nm-lynx.h: Fix child_wait prototype and include target.h. * config/nm-lynx.h: Fix child_wait prototype and include target.h.
Fri Jan 14 14:17:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com) Fri Jan 14 14:17:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
>>>>>>> 1.2118
* Makefile.in (ALLPARAM): Add config/nm-lynx.h. * Makefile.in (ALLPARAM): Add config/nm-lynx.h.

View File

@ -899,13 +899,22 @@ parse_number (p, len, parsed_float, putithere)
int parsed_float; int parsed_float;
YYSTYPE *putithere; YYSTYPE *putithere;
{ {
/* FIXME: Shouldn't these be unsigned? We don't deal with negative values
here, and we do kind of silly things like cast to unsigned. */
register LONGEST n = 0; register LONGEST n = 0;
register LONGEST prevn = 0; register LONGEST prevn = 0;
register int i = 0; register int i = 0;
register int c; register int c;
register int base = input_radix; register int base = input_radix;
int unsigned_p = 0; int unsigned_p = 0;
/* Number of "L" suffixes encountered. */
int long_p = 0; int long_p = 0;
/* We have found a "L" or "U" suffix. */
int found_suffix = 0;
unsigned LONGEST high_bit; unsigned LONGEST high_bit;
struct type *signed_type; struct type *signed_type;
struct type *unsigned_type; struct type *unsigned_type;
@ -956,15 +965,29 @@ parse_number (p, len, parsed_float, putithere)
if (c != 'l' && c != 'u') if (c != 'l' && c != 'u')
n *= base; n *= base;
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9')
n += i = c - '0'; {
if (found_suffix)
return ERROR;
n += i = c - '0';
}
else else
{ {
if (base > 10 && c >= 'a' && c <= 'f') if (base > 10 && c >= 'a' && c <= 'f')
n += i = c - 'a' + 10; {
else if (len == 0 && c == 'l') if (found_suffix)
long_p = 1; return ERROR;
else if (len == 0 && c == 'u') n += i = c - 'a' + 10;
unsigned_p = 1; }
else if (c == 'l')
{
++long_p;
found_suffix = 1;
}
else if (c == 'u')
{
unsigned_p = 1;
found_suffix = 1;
}
else else
return ERROR; /* Char not a digit */ return ERROR; /* Char not a digit */
} }
@ -972,44 +995,61 @@ parse_number (p, len, parsed_float, putithere)
return ERROR; /* Invalid digit in this base */ return ERROR; /* Invalid digit in this base */
/* Portably test for overflow (only works for nonzero values, so make /* Portably test for overflow (only works for nonzero values, so make
a second check for zero). */ a second check for zero). FIXME: Can't we just make n and prevn
if((prevn >= n) && n != 0) unsigned and avoid this? */
unsigned_p=1; /* Try something unsigned */ if (c != 'l' && c != 'u' && (prevn >= n) && n != 0)
/* If range checking enabled, portably test for unsigned overflow. */ unsigned_p = 1; /* Try something unsigned */
if(RANGE_CHECK && n!=0)
{ /* Portably test for unsigned overflow.
if((unsigned_p && (unsigned)prevn >= (unsigned)n)) FIXME: This check is wrong; for example it doesn't find overflow
range_error("Overflow on numeric constant."); on 0x123456789 when LONGEST is 32 bits. */
} if (c != 'l' && c != 'u' && n != 0)
prevn=n; {
if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n))
error ("Numeric constant too large.");
}
prevn = n;
} }
/* If the number is too big to be an int, or it's got an l suffix /* An integer constant is an int, a long, or a long long. An L
then it's a long. Work out if this has to be a long by suffix forces it to be long; an LL suffix forces it to be long
shifting right and and seeing if anything remains, and the long. If not forced to a larger size, it gets the first type of
target int size is different to the target long size. the above that it fits in. To figure out whether it fits, we
shift it right and see whether anything remains. Note that we
can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
operation, because many compilers will warn about such a shift
(which always produces a zero result). Sometimes TARGET_INT_BIT
or TARGET_LONG_BIT will be that big, sometimes not. To deal with
the case where it is we just always shift the value more than
once, with fewer bits each time. */
In the expression below, we could have tested if (long_p == 0
(n >> TARGET_INT_BIT) && (((unsigned LONGEST)n >> 2) >> (TARGET_INT_BIT - 2)) == 0)
to see if it was zero, {
but too many compilers warn about that, when ints and longs high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
are the same size. So we shift it twice, with fewer bits
each time, for the same result. */
if ( (TARGET_INT_BIT != TARGET_LONG_BIT /* A large decimal (not hex or octal) constant (between INT_MAX
&& ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */ and UINT_MAX) is a long or unsigned long, according to ANSI,
|| long_p) never an unsigned int, but this code treats it as unsigned
{ int. This probably should be fixed. GCC gives a warning on
high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1); such constants. */
unsigned_type = builtin_type_unsigned_long;
signed_type = builtin_type_long; unsigned_type = builtin_type_unsigned_int;
} signed_type = builtin_type_int;
else }
{ else if (long_p <= 1
high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1); && (((unsigned LONGEST)n >> 2) >> (TARGET_LONG_BIT - 2)) == 0)
unsigned_type = builtin_type_unsigned_int; {
signed_type = builtin_type_int; high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
} unsigned_type = builtin_type_unsigned_long;
signed_type = builtin_type_long;
}
else
{
high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_LONG_BIT - 1);
unsigned_type = builtin_type_unsigned_long_long;
signed_type = builtin_type_long_long;
}
putithere->typed_val.val = n; putithere->typed_val.val = n;
@ -1018,11 +1058,11 @@ parse_number (p, len, parsed_float, putithere)
if (unsigned_p || (n & high_bit)) if (unsigned_p || (n & high_bit))
{ {
putithere->typed_val.type = unsigned_type; putithere->typed_val.type = unsigned_type;
} }
else else
{ {
putithere->typed_val.type = signed_type; putithere->typed_val.type = signed_type;
} }
return INT; return INT;