Article View: gnu.gdb.bug
Article #8832GDB 4.7 ignores numeric suffixes in constants
From: Paul Eggert
Date: Sun, 25 Oct 1992 18:54
Date: Sun, 25 Oct 1992 18:54
549 lines
15477 bytes
15477 bytes
GDB 4.7 discards numeric suffixes in numbers like 0L and 1.3f. This can cause
subtle errors when cutting and pasting from source code to GDB. For example,
on a sparc, ``print 1.1 == 1.1f'' prints 1, where it should print 0 because
the numbers differ in C. Here is a patch that causes GDB to parse such
suffixes. This patch shortens the code somewhat.
This patch also fixes another bug: some overflows aren't caught when
parsing large integer constants.
I submitted this bug report for GDB 4.6, but it wasn't incorporated in GDB
4.7, so I'm resubmitting it in case it got lost.
===================================================================
RCS file: gdb/defs.h,v
retrieving revision 4.7
diff -c -r4.7 gdb/defs.h
*** gdb/defs.h 1992/10/06 00:41:41 4.7
--- gdb/defs.h 1992/10/25 07:29:59
***************
*** 659,664 ****
--- 659,667 ----
extern int
atoi PARAMS ((const char *)); /* 4.10.1.2 */
+ extern double
+ strtod PARAMS ((const char *nptr, char **entptr)); /* 4.10.1.4 */
+
#ifndef MALLOC_INCOMPATIBLE
extern PTR
===================================================================
RCS file: gdb/c-exp.y,v
retrieving revision 4.7
diff -c -r4.7 gdb/c-exp.y
*** gdb/c-exp.y 1992/10/19 21:33:03 4.7
--- gdb/c-exp.y 1992/10/25 07:27:57
***************
*** 96,104 ****
%union
{
! LONGEST lval;
! unsigned LONGEST ulval;
! double dval;
struct symbol *sym;
struct type *tval;
struct stoken sval;
--- 96,104 ----
%union
{
! LONGEST ival;
! struct lval { struct type *type; unsigned LONGEST value; } lval;
! struct dval { struct type *type; double value; } dval;
struct symbol *sym;
struct type *tval;
struct stoken sval;
***************
*** 127,136 ****
/* Fancy type parsing. */
%type <voidval> func_mod direct_abs_decl abs_decl
%type <tval> ptype
! %type <lval> array_mod
! %token <lval> INT CHAR
! %token <ulval> UINT
%token <dval> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
--- 127,135 ----
/* Fancy type parsing. */
%type <voidval> func_mod direct_abs_decl abs_decl
%type <tval> ptype
! %type <ival> array_mod
! %token <lval> INT
%token <dval> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
***************
*** 151,159 ****
/* A NAME_OR_INT is a symbol which is not known in the symbol table,
but which would parse as a valid number in the current input radix.
E.g. "c" when input_radix==16. Depending on the parse, it will be
! turned into a name or into a number. NAME_OR_UINT ditto. */
! %token <ssym> NAME_OR_INT NAME_OR_UINT
%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
%token TEMPLATE
--- 150,158 ----
/* A NAME_OR_INT is a symbol which is not known in the symbol table,
but which would parse as a valid number in the current input radix.
E.g. "c" when input_radix==16. Depending on the parse, it will be
! turned into a name or into a number. */
! %token <ssym> NAME_OR_INT
%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
%token TEMPLATE
***************
*** 163,169 ****
legal basetypes. */
%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
! %token <lval> LAST REGNAME
%token <ivar> VARIABLE
--- 162,168 ----
legal basetypes. */
%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
! %token <ival> LAST REGNAME
%token <ivar> VARIABLE
***************
*** 433,443 ****
exp : INT
{ write_exp_elt_opcode (OP_LONG);
! if ($1 == (int) $1 || $1 == (unsigned int) $1)
! write_exp_elt_type (builtin_type_int);
! else
! write_exp_elt_type (BUILTIN_TYPE_LONGEST);
! write_exp_elt_longcst ((LONGEST) $1);
write_exp_elt_opcode (OP_LONG); }
;
--- 432,439 ----
exp : INT
{ write_exp_elt_opcode (OP_LONG);
! write_exp_elt_type ($1.type);
! write_exp_elt_longcst ((LONGEST) $1.value);
write_exp_elt_opcode (OP_LONG); }
;
***************
*** 445,495 ****
{ YYSTYPE val;
parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
write_exp_elt_opcode (OP_LONG);
! if (val.lval == (int) val.lval ||
! val.lval == (unsigned int) val.lval)
! write_exp_elt_type (builtin_type_int);
! else
! write_exp_elt_type (BUILTIN_TYPE_LONGEST);
! write_exp_elt_longcst (val.lval);
! write_exp_elt_opcode (OP_LONG); }
! ;
!
! exp : UINT
! {
! write_exp_elt_opcode (OP_LONG);
! if ($1 == (unsigned int) $1)
! write_exp_elt_type (builtin_type_unsigned_int);
! else
! write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
! write_exp_elt_longcst ((LONGEST) $1);
! write_exp_elt_opcode (OP_LONG);
! }
! ;
!
! exp : NAME_OR_UINT
! { YYSTYPE val;
! parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
! write_exp_elt_opcode (OP_LONG);
! if (val.ulval == (unsigned int) val.ulval)
! write_exp_elt_type (builtin_type_unsigned_int);
! else
! write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
! write_exp_elt_longcst ((LONGEST)val.ulval);
! write_exp_elt_opcode (OP_LONG);
! }
! ;
!
! exp : CHAR
! { write_exp_elt_opcode (OP_LONG);
! write_exp_elt_type (builtin_type_char);
! write_exp_elt_longcst ((LONGEST) $1);
write_exp_elt_opcode (OP_LONG); }
;
exp : FLOAT
{ write_exp_elt_opcode (OP_DOUBLE);
! write_exp_elt_type (builtin_type_double);
! write_exp_elt_dblcst ($1);
write_exp_elt_opcode (OP_DOUBLE); }
;
--- 441,455 ----
{ YYSTYPE val;
parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
write_exp_elt_opcode (OP_LONG);
! write_exp_elt_type (val.lval.type);
! write_exp_elt_longcst ((LONGEST) val.lval.value);
write_exp_elt_opcode (OP_LONG); }
;
exp : FLOAT
{ write_exp_elt_opcode (OP_DOUBLE);
! write_exp_elt_type ($1.type);
! write_exp_elt_dblcst ($1.value);
write_exp_elt_opcode (OP_DOUBLE); }
;
***************
*** 813,819 ****
array_mod: '[' ']'
{ $$ = -1; }
| '[' INT ']'
! { $$ = $2; }
;
func_mod: '(' ')'
--- 773,779 ----
array_mod: '[' ']'
{ $$ = -1; }
| '[' INT ']'
! { $$ = $2.value; }
;
func_mod: '(' ')'
***************
*** 928,934 ****
| BLOCKNAME { $$ = $1.stoken; }
| TYPENAME { $$ = $1.stoken; }
| NAME_OR_INT { $$ = $1.stoken; }
- | NAME_OR_UINT { $$ = $1.stoken; }
;
name_not_typename : NAME
--- 888,893 ----
***************
*** 939,952 ****
=exp) or just an exp. If name_not_typename was ever used in an lvalue
context where only a name could occur, this might be useful.
| NAME_OR_INT
- | NAME_OR_UINT
*/
;
%%
/* Take care of parsing a number (anything that starts with a digit).
! Set yylval and return the token type; update lexptr.
LEN is the number of characters in it. */
/*** Needs some error checking for the float case ***/
--- 898,910 ----
=exp) or just an exp. If name_not_typename was ever used in an lvalue
context where only a name could occur, this might be useful.
| NAME_OR_INT
*/
;
%%
/* Take care of parsing a number (anything that starts with a digit).
! Set *PUTITHERE and return the token type.
LEN is the number of characters in it. */
/*** Needs some error checking for the float case ***/
***************
*** 958,974 ****
int parsed_float;
YYSTYPE *putithere;
{
! register LONGEST n = 0;
! register LONGEST prevn = 0;
register int i;
register int c;
register int base = input_radix;
! int unsigned_p = 0;
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
! putithere->dval = atof (p);
return FLOAT;
}
--- 916,954 ----
int parsed_float;
YYSTYPE *putithere;
{
! register unsigned LONGEST n = 0;
! register unsigned LONGEST prevn = 0;
register int i;
register int c;
register int base = input_radix;
! int unsigned_p = 0, long_p = 0;
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
! char *pend;
! errno = 0;
! putithere->dval.value = strtod (p, &pend);
! if (putithere->dval.value != 0 && RANGE_CHECK && errno == ERANGE)
! range_error("Overflow on floating point constant.");
! switch (*pend)
! {
! case 'f': case 'F':
! ++pend;
! putithere->dval.type = builtin_type_float;
! break;
!
! case 'l': case 'L':
! ++pend;
! putithere->dval.type = builtin_type_long_double;
! break;
!
! default:
! putithere->dval.type = builtin_type_double;
! break;
! }
! if (pend != p + len)
! return ERROR;
return FLOAT;
}
***************
*** 1009,1053 ****
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
if (c != 'l' && c != 'u')
! n *= base;
if (c >= '0' && c <= '9')
n += i = c - '0';
else
{
if (base > 10 && c >= 'a' && c <= 'f')
n += i = c - 'a' + 10;
- else if (len == 0 && c == 'l')
- ;
- else if (len == 0 && c == 'u')
- unsigned_p = 1;
else
! return ERROR; /* Char not a digit */
}
if (i >= base)
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;
}
! if (unsigned_p)
! {
! putithere->ulval = n;
! return UINT;
! }
! else
! {
! putithere->lval = n;
! return INT;
! }
}
struct token
--- 989,1046 ----
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
if (c != 'l' && c != 'u')
! {
! n *= base;
! if (RANGE_CHECK && n / base != prevn)
! range_error("Overflow on numeric constant.");
! }
if (c >= '0' && c <= '9')
n += i = c - '0';
else
{
if (base > 10 && c >= 'a' && c <= 'f')
n += i = c - 'a' + 10;
else
! {
! for (;;) {
! switch (c)
! {
! case 'l': long_p++; break;
! case 'u': unsigned_p++; break;
! default: return ERROR;
! }
! if (len-- == 0)
! break;
! c = *p++;
! }
! if (1 < unsigned_p || 2 < long_p)
! return ERROR;
! i = 0;
! }
}
if (i >= base)
return ERROR; /* Invalid digit in this base */
/* If range checking enabled, portably test for unsigned overflow. */
! if (RANGE_CHECK && n < prevn)
! range_error("Overflow on numeric constant.");
prevn=n;
}
! putithere->lval.value = n;
! putithere->lval.type =
! !(long_p | unsigned_p) && 0 <= (int)n && n == (int) n
! ? builtin_type_int
! : !long_p && (base != 10 || unsigned_p) && n == (unsigned) n
! ? builtin_type_unsigned_int
! : !unsigned_p && long_p <= 1 && 0 <= (long) n && n == (long) n
! ? builtin_type_long
! : long_p <= 1 && n == (unsigned long) n
! ? builtin_type_unsigned_long
! : !unsigned_p && 0 <= (LONGEST) n
! ? builtin_type_long_long
! : builtin_type_unsigned_long_long;
!
! return INT;
}
struct token
***************
*** 1137,1143 ****
c = *lexptr++;
if (c == '\\')
c = parse_escape (&lexptr);
! yylval.lval = c;
c = *lexptr++;
if (c != '\'')
{
--- 1130,1137 ----
c = *lexptr++;
if (c == '\\')
c = parse_escape (&lexptr);
! yylval.lval.type = builtin_type_char;
! yylval.lval.value = c;
c = *lexptr++;
if (c != '\'')
{
***************
*** 1151,1157 ****
}
error ("Invalid character constant.");
}
! return CHAR;
case '(':
paren_depth++;
--- 1145,1151 ----
}
error ("Invalid character constant.");
}
! return INT;
case '(':
paren_depth++;
***************
*** 1318,1324 ****
if (c == namelen)
{
/* Just dollars (one or two) */
! yylval.lval = - negate;
return LAST;
}
/* Is the rest of the token digits? */
--- 1312,1318 ----
if (c == namelen)
{
/* Just dollars (one or two) */
! yylval.ival = - negate;
return LAST;
}
/* Is the rest of the token digits? */
***************
*** 1327,1335 ****
break;
if (c == namelen)
{
! yylval.lval = atoi (tokstart + 1 + negate);
if (negate)
! yylval.lval = - yylval.lval;
return LAST;
}
}
--- 1321,1329 ----
break;
if (c == namelen)
{
! yylval.ival = atoi (tokstart + 1 + negate);
if (negate)
! yylval.ival = - yylval.ival;
return LAST;
}
}
***************
*** 1342,1355 ****
if (namelen - 1 == strlen (reg_names[c])
&& !strncmp (tokstart + 1, reg_names[c], namelen - 1))
{
! yylval.lval = c;
return REGNAME;
}
for (c = 0; c < num_std_regs; c++)
if (namelen - 1 == strlen (std_regs[c].name)
&& !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
{
! yylval.lval = std_regs[c].regnum;
return REGNAME;
}
}
--- 1336,1349 ----
if (namelen - 1 == strlen (reg_names[c])
&& !strncmp (tokstart + 1, reg_names[c], namelen - 1))
{
! yylval.ival = c;
return REGNAME;
}
for (c = 0; c < num_std_regs; c++)
if (namelen - 1 == strlen (std_regs[c].name)
&& !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
{
! yylval.ival = std_regs[c].regnum;
return REGNAME;
}
}
***************
*** 1464,1475 ****
yylval.ssym.sym = sym;
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
return NAME_OR_INT;
- }
- if (hextype == UINT)
- {
- yylval.ssym.sym = sym;
- yylval.ssym.is_a_field_of_this = is_a_field_of_this;
- return NAME_OR_UINT;
}
}
--- 1458,1463 ----
Technical Details
Message-ID:
<9210251854.AA10979@bi.twinsun.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!bi.TWinsun.COM!eggertShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: f5053,7df2e4ace45882fb,start X-Google-Attributes: gidf5053,public X-Google-ArrivalTime: 1992-10-25 14:12:16 PST Newsgroups: gnu.gdb.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!bi.TWinsun.COM!eggert From: eggert@bi.TWinsun.COM (Paul Eggert) Subject: GDB 4.7 ignores numeric suffixes in constants Message-ID: <9210251854.AA10979@bi.twinsun.com> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet Distribution: gnu Date: Sun, 25 Oct 1992 18:54:16 GMT Approved: bug-gdb@prep.ai.mit.edu Lines: 550