From: Jim Kingdon Date: Sat, 15 Jan 1994 17:14:18 +0000 (+0000) Subject: * c-exp.y (parse_number): Check for overflow regardless of range X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a9b32d6192a3f30e3e7f34881f4914875a383f92;p=binutils-gdb.git * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 22100b24d8a..c6190ead29d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 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): 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. Fri Jan 14 14:17:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com) ->>>>>>> 1.2118 * Makefile.in (ALLPARAM): Add config/nm-lynx.h. diff --git a/gdb/c-exp.y b/gdb/c-exp.y index ebc1ca66c71..6a96eb11ee4 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -899,13 +899,22 @@ parse_number (p, len, parsed_float, putithere) int parsed_float; 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 prevn = 0; + register int i = 0; register int c; register int base = input_radix; int unsigned_p = 0; + + /* Number of "L" suffixes encountered. */ int long_p = 0; + + /* We have found a "L" or "U" suffix. */ + int found_suffix = 0; + unsigned LONGEST high_bit; struct type *signed_type; struct type *unsigned_type; @@ -956,15 +965,29 @@ parse_number (p, len, parsed_float, putithere) if (c != 'l' && c != 'u') n *= base; if (c >= '0' && c <= '9') - n += i = c - '0'; + { + if (found_suffix) + return ERROR; + n += i = c - '0'; + } else { if (base > 10 && c >= 'a' && c <= 'f') - n += i = c - 'a' + 10; - else if (len == 0 && c == 'l') - long_p = 1; - else if (len == 0 && c == 'u') - unsigned_p = 1; + { + if (found_suffix) + return ERROR; + n += i = c - 'a' + 10; + } + else if (c == 'l') + { + ++long_p; + found_suffix = 1; + } + else if (c == 'u') + { + unsigned_p = 1; + found_suffix = 1; + } else return ERROR; /* Char not a digit */ } @@ -972,44 +995,61 @@ parse_number (p, len, parsed_float, putithere) return ERROR; /* Invalid digit in this base */ /* Portably test for overflow (only works for nonzero values, so make - a second check for zero). */ - if((prevn >= n) && n != 0) - unsigned_p=1; /* Try something unsigned */ - /* If range checking enabled, portably test for unsigned overflow. */ - if(RANGE_CHECK && n!=0) - { - if((unsigned_p && (unsigned)prevn >= (unsigned)n)) - range_error("Overflow on numeric constant."); - } - prevn=n; + a second check for zero). FIXME: Can't we just make n and prevn + unsigned and avoid this? */ + if (c != 'l' && c != 'u' && (prevn >= n) && n != 0) + unsigned_p = 1; /* Try something unsigned */ + + /* Portably test for unsigned overflow. + FIXME: This check is wrong; for example it doesn't find overflow + on 0x123456789 when LONGEST is 32 bits. */ + if (c != 'l' && c != 'u' && n != 0) + { + if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n)) + error ("Numeric constant too large."); + } + prevn = n; + } + + /* An integer constant is an int, a long, or a long long. An L + suffix forces it to be long; an LL suffix forces it to be long + long. If not forced to a larger size, it gets the first type of + 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. */ + + if (long_p == 0 + && (((unsigned LONGEST)n >> 2) >> (TARGET_INT_BIT - 2)) == 0) + { + high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1); + + /* A large decimal (not hex or octal) constant (between INT_MAX + and UINT_MAX) is a long or unsigned long, according to ANSI, + never an unsigned int, but this code treats it as unsigned + int. This probably should be fixed. GCC gives a warning on + such constants. */ + + unsigned_type = builtin_type_unsigned_int; + signed_type = builtin_type_int; + } + else if (long_p <= 1 + && (((unsigned LONGEST)n >> 2) >> (TARGET_LONG_BIT - 2)) == 0) + { + 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; } - - /* If the number is too big to be an int, or it's got an l suffix - then it's a long. Work out if this has to be a long by - shifting right and and seeing if anything remains, and the - target int size is different to the target long size. - - In the expression below, we could have tested - (n >> TARGET_INT_BIT) - to see if it was zero, - but too many compilers warn about that, when ints and longs - 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 - && ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */ - || long_p) - { - 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_INT_BIT-1); - unsigned_type = builtin_type_unsigned_int; - signed_type = builtin_type_int; - } putithere->typed_val.val = n; @@ -1018,11 +1058,11 @@ parse_number (p, len, parsed_float, putithere) if (unsigned_p || (n & high_bit)) { - putithere->typed_val.type = unsigned_type; + putithere->typed_val.type = unsigned_type; } else { - putithere->typed_val.type = signed_type; + putithere->typed_val.type = signed_type; } return INT;