C & C++ PATCH: Correct "overflow" in yylex/real_yylex

Gavin Romig-Koch gavin@cygnus.com
Thu Jul 15 15:38:00 GMT 1999


Ha! Dumb.  I took one last look at this patch before commiting it
and discovered that it introduces a different bug.  I've rewritten
the patch to fix this bug without introducing a new one, and while
I was at it, made the parts array smaller and and added some comments.

The original bug was that the code allows integer literals slightly
larger than two HOST_WIDE_INTs without warning.  (The bug introduced
by my previous patch allowed for any literal as long as certian bits
in it were zero.)

Sorry to ask you to look at this stuff again.

                                            -gavin...


For gcc:
	* c-lex.c (yylex) : Correct the test for overflow when lexing
	integer literals.

For gcc/cp:
	* lex.c (real_yylex) : Correct the test for overflow when lexing
	integer literals.



Index: c-lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-lex.c,v
retrieving revision 1.53
diff -c -p -r1.53 c-lex.c
*** c-lex.c	1999/07/06 10:07:41	1.53
--- c-lex.c	1999/07/15 22:23:06
*************** yylex ()
*** 1477,1492 ****
  	int count = 0;
  	int largest_digit = 0;
  	int numdigits = 0;
- 	/* for multi-precision arithmetic,
- 	   we actually store only HOST_BITS_PER_CHAR bits in each part.
- 	   The number of parts is chosen so as to be sufficient to hold
- 	   the enough bits to fit into the two HOST_WIDE_INTs that contain
- 	   the integer value (this is always at least as many bits as are
- 	   in a target `long long' value, but may be wider).  */
- #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2)
- 	int parts[TOTAL_PARTS];
  	int overflow = 0;
  
  	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON}
  	  floatflag = NOT_FLOAT;
  
--- 1477,1495 ----
  	int count = 0;
  	int largest_digit = 0;
  	int numdigits = 0;
  	int overflow = 0;
  
+ 	/* We actually store only HOST_BITS_PER_CHAR bits in each part.
+ 	   The code below which fills the parts array assumes that a host
+ 	   int is at least twice as wide as a host char, and that 
+ 	   HOST_BITS_PER_WIDE_INT is an even multiple of HOST_BITS_PER_CHAR.
+ 	   Two HOST_WIDE_INTs is the largest int literal we can store.
+ 	   In order to detect overflow below, the number of parts (TOTAL_PARTS)
+ 	   must be exactly the number of parts needed to hold the bits
+ 	   of two HOST_WIDE_INTs. */
+ #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
+ 	unsigned int parts[TOTAL_PARTS];
+ 
  	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON}
  	  floatflag = NOT_FLOAT;
  
*************** yylex ()
*** 1616,1626 ****
  		    else
  		      parts[0] += c;
  		  }
! 
! 		/* If the extra highest-order part ever gets anything in it,
! 		   the number is certainly too big.  */
! 		if (parts[TOTAL_PARTS - 1] != 0)
! 		  overflow = 1;
  
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
--- 1619,1634 ----
  		    else
  		      parts[0] += c;
  		  }
! 		
! 		/* If the highest-order part overflows (gets larger than
! 		   a host char will hold) then the whole number has 
! 		   overflowed.  Record this and truncate the highest-order
! 		   part. */
! 		if (parts[TOTAL_PARTS - 1] >> HOST_BITS_PER_CHAR)
! 		  {
! 		    overflow = 1;
! 		    parts[TOTAL_PARTS - 1] &= (1 << HOST_BITS_PER_CHAR) - 1;
! 		  }
  
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
*************** yylex ()
*** 1772,1783 ****
  		c = GETC();
  	      }
  
! 	    /* If it won't fit in the host's representation for integers,
! 	       then pedwarn. */
! 
! 	    warn = overflow;
! 	    if (warn)
! 	      pedwarn ("integer constant is too large for this configuration of the compiler - truncated to %d bits", HOST_BITS_PER_WIDE_INT * 2);
  
  	    /* This is simplified by the fact that our constant
  	       is always positive.  */
--- 1780,1791 ----
  		c = GETC();
  	      }
  
! 	    /* If the literal overflowed, pedwarn about it now. */
! 	    if (overflow)
! 	      {
! 		warn = 1;
! 		pedwarn ("integer constant is too large for this configuration of the compiler - truncated to %d bits", HOST_BITS_PER_WIDE_INT * 2);
! 	      }
  
  	    /* This is simplified by the fact that our constant
  	       is always positive.  */
Index: cp/lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.119
diff -c -p -r1.119 lex.c
*** lex.c	1999/07/09 12:44:35	1.119
--- lex.c	1999/07/15 22:23:09
*************** real_yylex ()
*** 3687,3702 ****
  	int count = 0;
  	int largest_digit = 0;
  	int numdigits = 0;
- 	/* for multi-precision arithmetic,
- 	   we actually store only HOST_BITS_PER_CHAR bits in each part.
- 	   The number of parts is chosen so as to be sufficient to hold
- 	   the enough bits to fit into the two HOST_WIDE_INTs that contain
- 	   the integer value (this is always at least as many bits as are
- 	   in a target `long long' value, but may be wider).  */
- #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2)
- 	int parts[TOTAL_PARTS];
  	int overflow = 0;
  
  	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
  	  = NOT_FLOAT;
  
--- 3687,3705 ----
  	int count = 0;
  	int largest_digit = 0;
  	int numdigits = 0;
  	int overflow = 0;
  
+ 	/* We actually store only HOST_BITS_PER_CHAR bits in each part.
+ 	   The code below which fills the parts array assumes that a host
+ 	   int is at least twice as wide as a host char, and that 
+ 	   HOST_BITS_PER_WIDE_INT is an even multiple of HOST_BITS_PER_CHAR.
+ 	   Two HOST_WIDE_INTs is the largest int literal we can store.
+ 	   In order to detect overflow below, the number of parts (TOTAL_PARTS)
+ 	   must be exactly the number of parts needed to hold the bits
+ 	   of two HOST_WIDE_INTs. */
+ #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
+ 	unsigned int parts[TOTAL_PARTS];
+ 
  	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
  	  = NOT_FLOAT;
  
*************** real_yylex ()
*** 3822,3831 ****
  		      parts[0] += c;
  		  }
  
! 		/* If the extra highest-order part ever gets anything in it,
! 		   the number is certainly too big.  */
! 		if (parts[TOTAL_PARTS - 1] != 0)
! 		  overflow = 1;
  
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
--- 3825,3839 ----
  		      parts[0] += c;
  		  }
  
! 		/* If the highest-order part overflows (gets larger than
! 		   a host char will hold) then the whole number has 
! 		   overflowed.  Record this and truncate the highest-order
! 		   part. */
! 		if (parts[TOTAL_PARTS - 1] >> HOST_BITS_PER_CHAR)
! 		  {
! 		    overflow = 1;
! 		    parts[TOTAL_PARTS - 1] &= (1 << HOST_BITS_PER_CHAR) - 1;
! 		  }
  
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
*************** real_yylex ()
*** 3977,3988 ****
  		c = getch ();
  	      }
  
! 	    /* If it won't fit in the host's representation for integers,
! 	       then pedwarn. */
! 
! 	    warn = overflow;
! 	    if (warn)
! 	      pedwarn ("integer constant is too large for this configuration of the compiler - truncated to %d bits", HOST_BITS_PER_WIDE_INT * 2);
  
  	    /* This is simplified by the fact that our constant
  	       is always positive.  */
--- 3985,3996 ----
  		c = getch ();
  	      }
  
! 	    /* If the literal overflowed, pedwarn about it now. */
! 	    if (overflow)
! 	      {
! 		warn = 1;
! 		pedwarn ("integer constant is too large for this configuration of the compiler - truncated to %d bits", HOST_BITS_PER_WIDE_INT * 2);
! 	      }
  
  	    /* This is simplified by the fact that our constant
  	       is always positive.  */



More information about the Gcc-patches mailing list