From: eggert@twinsun.COM (Paul Eggert)
Subject: bugs in GCC 2.2.2 floating point range and suffix checks
Organization: GNUs Not Usenet
Distribution: gnu
Date: Fri, 24 Jul 1992 19:21:07 GMT

1.  GCC 2.2.2 (sparc, SunOS 4.1.2) does not issue a diagnostic for the program:

	double d = 1.0fl;

even though the conflicting suffixes `f' and `l' violate C syntax.

2.  For the program

	float f = 1e400f;

`gcc -pedantic' issues the following redundant diagnostics.

	t.c:1: warning: floating point number exceeds range of `double'
	t.c:1: warning: floating point number exceeds range of `float'

Here is a patch.  This patch affects both the C and the C++ lexers, and
assumes that you've already applied the patch ``gcc 2.2.2 fp constant overflow
check should use REAL_VALUES_LESS'' that I reported on June 15.  The code in
the two 2.2.2 lexers had diverged slightly, because some changes were applied
to the C lexer but not the C++ lexer.  The patch below updates the C++ lexer
to match the C lexer.

Fri Jul 24 19:09:02 1992  Paul Eggert  (eggert@twinsun.com)

	* c-lex.c, cp-lex.c (yylex): Diagnose `1.0fl'.  Issue just one
	diagnostic for `1e1000000f'.

===================================================================
RCS file: c-lex.c,v
retrieving revision 2.2.2.1
diff -c -r2.2.2.1 c-lex.c
*** c-lex.c	1992/06/15 20:45:16	2.2.2.1
--- c-lex.c	1992/07/24 18:54:59
***************
*** 1245,1252 ****
  	if (floatflag != NOT_FLOAT)
  	  {
  	    tree type = double_type_node;
! 	    char f_seen = 0;
! 	    char l_seen = 0;
  	    REAL_VALUE_TYPE value;
  	    jmp_buf handler;
  
--- 1245,1251 ----
  	if (floatflag != NOT_FLOAT)
  	  {
  	    tree type = double_type_node;
! 	    int garbage_chars = 0, exceeds_double = 0;
  	    REAL_VALUE_TYPE value;
  	    jmp_buf handler;
  
***************
*** 1297,1348 ****
  		if (REAL_VALUES_LESS (dconst1, value)
  		    || REAL_VALUES_LESS (value, dconstm1))
  		  pedwarn ("floating point number exceeds range of `double'");
  	      }
  #endif
  
  	    /* Read the suffixes to choose a data type.  */
! 	    while (1)
  	      {
! 		if (c == 'f' || c == 'F')
! 		  {
! 		    if (f_seen)
! 		      error ("two `f's in floating constant");
! 		    else
! 		      {
! 			f_seen = 1;
! 			type = float_type_node;
! 			value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value);
! 			if (REAL_VALUE_ISINF (value) && pedantic)
! 			  pedwarn ("floating point number exceeds range of `float'");
! 		      }
! 		  }
! 		else if (c == 'l' || c == 'L')
! 		  {
! 		    if (l_seen)
! 		      error ("two `l's in floating constant");
! 		    l_seen = 1;
! 		    type = long_double_type_node;
! 		  }
! 		else
! 		  {
! 		    if (isalnum (c))
! 		      {
! 			error ("garbage at end of number");
! 			while (isalnum (c))
! 			  {
! 			    if (p >= token_buffer + maxtoken - 3)
! 			      p = extend_token_buffer (p);
! 			    *p++ = c;
! 			    c = getc (finput);
! 			  }
! 		      }
! 		    break;
! 		  }
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
  		*p++ = c;
  		c = getc (finput);
  	      }
  
  	    /* Create a node with determined type and value.  */
  	    yylval.ttype = build_real (type, value);
--- 1296,1331 ----
  		if (REAL_VALUES_LESS (dconst1, value)
  		    || REAL_VALUES_LESS (value, dconstm1))
  		  pedwarn ("floating point number exceeds range of `double'");
+ 		exceeds_double = 1;
  	      }
  #endif
  
  	    /* Read the suffixes to choose a data type.  */
! 	    switch (c)
  	      {
! 	      case 'f': case 'F':
! 		type = float_type_node;
! 		value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value);
! 		if (REAL_VALUE_ISINF (value) && ! exceeds_double && pedantic)
! 		  pedwarn ("floating point number exceeds range of `float'");
! 		garbage_chars = -1;
! 		break;
! 
! 	      case 'l': case 'L':
! 		type = long_double_type_node;
! 		garbage_chars = -1;
! 		break;
! 	      }
! 	    while (isalnum (c))
! 	      {
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
  		*p++ = c;
  		c = getc (finput);
+ 		garbage_chars++;
  	      }
+ 	    if (garbage_chars > 0)
+ 	      error ("garbage at end of number");
  
  	    /* Create a node with determined type and value.  */
  	    yylval.ttype = build_real (type, value);
===================================================================
RCS file: cp-lex.c,v
retrieving revision 2.2.2.1
diff -c -r2.2.2.1 cp-lex.c
*** cp-lex.c	1992/06/15 20:45:16	2.2.2.1
--- cp-lex.c	1992/07/24 18:55:24
***************
*** 2887,2894 ****
  	if (floatflag != NOT_FLOAT)
  	  {
  	    tree type = double_type_node;
! 	    char f_seen = 0;
! 	    char l_seen = 0;
  	    REAL_VALUE_TYPE value;
  	    jmp_buf handler;
  
--- 2887,2893 ----
  	if (floatflag != NOT_FLOAT)
  	  {
  	    tree type = double_type_node;
! 	    int garbage_chars = 0, exceeds_double = 0;
  	    REAL_VALUE_TYPE value;
  	    jmp_buf handler;
  
***************
*** 2932,2985 ****
  		set_float_handler (0);
  	      }
  #ifdef ERANGE
! 	    if (errno == ERANGE && !flag_traditional)
  	      {
  		/* ERANGE is also reported for underflow,
  		   so test the value to distinguish overflow from that.  */
! 		  if (REAL_VALUES_LESS (dconst1, value)
! 		      || REAL_VALUES_LESS (value, dconstm1))
! 		  warning ("floating point number exceeds range of `double'");
  	      }
  #endif
  
  	    /* Read the suffixes to choose a data type.  */
! 	    while (1)
  	      {
! 		if (c == 'f' || c == 'F')
! 		  {
! 		    if (f_seen)
! 		      error ("two `f's in floating constant");
! 		    f_seen = 1;
! 		    type = float_type_node;
! 		    value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value);
! 		  }
! 		else if (c == 'l' || c == 'L')
! 		  {
! 		    if (l_seen)
! 		      error ("two `l's in floating constant");
! 		    l_seen = 1;
! 		    type = long_double_type_node;
! 		  }
! 		else
! 		  {
! 		    if (isalnum (c))
! 		      {
! 			error ("garbage at end of number");
! 			while (isalnum (c))
! 			  {
! 			    if (p >= token_buffer + maxtoken - 3)
! 			      p = extend_token_buffer (p);
! 			    *p++ = c;
! 			    c = getch ();
! 			  }
! 		      }
! 		    break;
! 		  }
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
  		*p++ = c;
  		c = getch ();
  	      }
  
  	    /* Create a node with determined type and value.  */
  	    yylval.ttype = build_real (type, value);
--- 2931,2973 ----
  		set_float_handler (0);
  	      }
  #ifdef ERANGE
! 	    if (errno == ERANGE && !flag_traditional && pedantic)
  	      {
  		/* ERANGE is also reported for underflow,
  		   so test the value to distinguish overflow from that.  */
! 		if (REAL_VALUES_LESS (dconst1, value)
! 		    || REAL_VALUES_LESS (value, dconstm1))
! 		  pedwarn ("floating point number exceeds range of `double'");
! 		exceeds_double = 1;
  	      }
  #endif
  
  	    /* Read the suffixes to choose a data type.  */
! 	    switch (c)
  	      {
! 	      case 'f': case 'F':
! 		type = float_type_node;
! 		value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value);
! 		if (REAL_VALUE_ISINF (value) && ! exceeds_double && pedantic)
! 		  pedwarn ("floating point number exceeds range of `float'");
! 		garbage_chars = -1;
! 		break;
! 
! 	      case 'l': case 'L':
! 		type = long_double_type_node;
! 		garbage_chars = -1;
! 		break;
! 	      }
! 	    while (isalnum (c))
! 	      {
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
  		*p++ = c;
  		c = getch ();
+ 		garbage_chars++;
  	      }
+ 	    if (garbage_chars > 0)
+ 	      error ("garbage at end of number");
  
  	    /* Create a node with determined type and value.  */
  	    yylval.ttype = build_real (type, value);

Xref: sparky gnu.gcc.bug:2020 gnu.gdb.bug:919