This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Integer constant parsing overhaul


This is a major overhaul of the integer parsing routines in the
C-family front ends.  I have unified the cpplib version of this logic
with the c-lex.c version, rewritten it for readability and efficiency,
and implemented the C99 type selection rules.

I am not certain that I have correctly (re)implemented traditional-
mode type selection.  In particular, there was a warning, "width of
integer constant changes with -traditional", which I could not see any
way it could trigger; it's definitely impossible with the new code and
has been removed.  I am more confident about C89 and C99 type
selection.

Since this change affects standard conformance I would appreciate it
if a kind soul with access to such a thing, could run it through a
C or C++ conformance suite.

This code may issue different warnings than the old ones; I'd also
appreciate feedback on those changes.

Bootstrapped i686-linux with no regressions in the test suite.  However,
please note the changes to the test suite, especially wtr-int-type-1.c,
which I may have misunderstood.

zw

	* cpplex.c (hex_digit_value): Inline.
	(interpret_float_suffix, interpret_int_suffix): New internal routines.
	(cpp_classify_number, cpp_interpret_integer): New interfaces.
	Some code cannibalized from wreckage of c-lex.c::parse_number().
	* cpplib.h: Prototype new interfaces.  Define symbolic constants
	for result of cpp_classify_number.
	(struct cpp_options): Add warn_long_long.
	* cppinit.c (cpp_handle_option): Recognize -W(no-)long-long.
	Set warn_long_long also if -pedantic.

	* cppexp.c (struct suffix, vsuf_1, vsuf_2, vsuf_3): Kill.
	(parse_number): Gutted.  Just call cpp_classify_number and
	then cpp_interpret_integer.
	(parse_name): New, broken out of lex.
	(parse_defined): Issue warning about "defined" in macro
	expansion here.
	(_cpp_parse_expr): Issue -Wundef warning here.
	(lex): Don't issue either of those warnings here.  No need
	to know whether we are skipping evaluation.

	* c-lex.c (narrowest_unsigned_type, narrowest_signed_type,
	lex_integer, lex_float): New functions.  Some code from
	wreckage of lex_number.  Use new cpplib interfaces.
	Implement C99's integer constant type rules.
	(parse_float): Rename to convert_float, rearrange so that all
	and only those operations which can trap are done here.

testsuite:
	* gcc.dg/c90-hexfloat-1.c, gcc.dg/cpp/c++98-pedantic.c,
	gcc.dg/cpp/c89-pedantic.c, gcc.dg/cpp/c94-pedantic.c,
	gcc.dg/cpp/gnuc89-pedantic.c, gcc.dg/cpp/if-1.c:
	Adjust warning matchers.
	* gcc.dg/cpp/sysmac2.c: Add -fno-show-column to dg-options.

	* gcc.dg/wtr-int-type-1.c: Adjust warning matchers.  Add -std=c99
	to dg-options.


===================================================================
Index: cpplex.c
*** cpplex.c	2001/08/22 20:37:18	1.157
--- cpplex.c	2001/08/23 04:16:45
*************** static void lex_dot PARAMS ((cpp_reader 
*** 100,109 ****
  static int name_p PARAMS ((cpp_reader *, const cpp_string *));
  static int maybe_read_ucs PARAMS ((cpp_reader *, const unsigned char **,
  				   const unsigned char *, unsigned int *));
  
  static cpp_chunk *new_chunk PARAMS ((unsigned int));
  static int chunk_suitable PARAMS ((cpp_pool *, cpp_chunk *, unsigned int));
! static unsigned int hex_digit_value PARAMS ((unsigned int));
  
  /* Utility routine:
  
--- 100,111 ----
  static int name_p PARAMS ((cpp_reader *, const cpp_string *));
  static int maybe_read_ucs PARAMS ((cpp_reader *, const unsigned char **,
  				   const unsigned char *, unsigned int *));
+ static unsigned int interpret_float_suffix PARAMS ((const U_CHAR *, int));
+ static unsigned int interpret_int_suffix PARAMS ((const U_CHAR *, int));
  
  static cpp_chunk *new_chunk PARAMS ((unsigned int));
  static int chunk_suitable PARAMS ((cpp_pool *, cpp_chunk *, unsigned int));
! static inline unsigned int hex_digit_value PARAMS ((unsigned int));
  
  /* Utility routine:
  
*************** cpp_output_line (pfile, fp)
*** 1683,1689 ****
  }
  
  /* Returns the value of a hexadecimal digit.  */
! static unsigned int
  hex_digit_value (c)
       unsigned int c;
  {
--- 1685,1691 ----
  }
  
  /* Returns the value of a hexadecimal digit.  */
! static inline unsigned int
  hex_digit_value (c)
       unsigned int c;
  {
*************** cpp_interpret_charconst (pfile, token, w
*** 2022,2027 ****
--- 2024,2339 ----
  
    *pchars_seen = chars_seen;
    return result;
+ }
+ 
+ /* cpplib provides two interfaces for interpretation of preprocessing
+    numbers.
+ 
+    cpp_classify_number categorizes numeric constants according to
+    their field (integer, floating point, or invalid), radix (decimal,
+    octal, hexadecimal), and type suffixes.
+ 
+    cpp_interpret_integer converts an integer constant into a
+    HOST_WIDEST_INT.  You are responsible for truncating it to
+    the appropriate width.
+ 
+    We do not provide any interface for decimal->float conversion,
+    because the preprocessor doesn't need it and the floating point
+    handling in GCC proper is too ugly to speak of.  */
+ 
+ /* subroutine of classify_number.  S points to a float suffix of
+    length N.  Returns 0 for an invalid suffix, or a flag vector
+    describing the suffix.  */
+ static unsigned int
+ interpret_float_suffix (s, n)
+      const U_CHAR *s;
+      int n;
+ {
+   int f, l, i;
+ 
+   if (n > 2)
+     return 0;
+ 
+   f = l = i = 0;
+ 
+   for (; n > 0; n--)
+     switch (s[n-1])
+       {
+       case 'f': case 'F':	f++; break;
+       case 'l': case 'L':	l++; break;
+       case 'i': case 'I':
+       case 'j': case 'J':	i++; break;
+       default:
+ 	return 0;
+       }
+ 
+   if ((f && l) || f > 1 || l > 1 || i > 1)
+     return 0;
+ 
+   return ((i ? CPP_N_IMAGINARY : 0)
+ 	  | (f ? CPP_N_SMALL :
+ 	     l ? CPP_N_LARGE : CPP_N_MEDIUM));
+ }
+ 
+ /* subroutine of classify_number.  S points to an integer suffix of
+    length N. Returns 0 for an invalid suffix, or a flag vector
+    describing the suffix.  */
+ static unsigned int
+ interpret_int_suffix (s, n)
+      const U_CHAR *s;
+      int n;
+ {
+   int u, l, i;
+   int save_n = n;
+ 
+   if (n > 4)
+     return 0;
+ 
+   u = l = i = 0;
+ 
+   for (; n > 0; n--)
+     switch (s[n-1])
+       {
+       case 'l': case 'L':	l++; break;
+       case 'u': case 'U':	u++; break;
+       case 'i': case 'I':
+       case 'j': case 'J':	i++; break;
+       default: return 0;
+       }
+ 
+   if (l > 2 || u > 1 || i > 1)
+     return 0;
+ 
+   /* If there are two Ls, they must be adjacent and the same case.  */
+   if (l == 2)
+     for (n = save_n; n > 1; n--)
+       {
+ 	if (s[n-1] == 'l' || s[n-1] == 'L')
+ 	  {
+ 	    if (s[n-2] == s[n-1])
+ 	      break;
+ 	    return 0;
+ 	  }
+       }
+ 
+   return ((i ? CPP_N_IMAGINARY : 0)
+ 	  | (u ? CPP_N_UNSIGNED : 0)
+ 	  | ((l == 0) ? CPP_N_SMALL
+ 	     : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
+ }
+ 
+ #define ERROR(msgid) \
+     do { cpp_error (pfile, msgid); return CPP_N_INVALID; } while (0)
+ #define ERROR2(msgid, a, b) \
+     do { cpp_error (pfile, msgid, a, b); return CPP_N_INVALID; } while (0)
+ 
+ unsigned int
+ cpp_classify_number (pfile, token)
+      cpp_reader *pfile;
+      const cpp_token *token;
+ {
+   const unsigned char *str = token->val.str.text;
+   const unsigned char *limit = str + token->val.str.len;
+ 
+   unsigned int result;
+ 
+   enum float_state {
+     NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON
+   } floatflag = NOT_FLOAT;
+ 
+   int max_digit = 0;
+   int ndigits = 0;
+   int radix = 10;
+ 
+   /* First, interpret the radix.  */
+   if (*str == '0')
+     {
+       if (str + 1 == limit)
+ 	/* Literal zero gets its own category, because it is treated
+ 	   specially in C++'s grammar.  */
+ 	return CPP_N_ZERO;
+ 
+       radix = 8;
+ 
+       if (str[1] == 'x' || str[1] == 'X')
+ 	{
+ 	  radix = 16;
+ 	  str += 2;
+ 	}
+     }
+ 
+   /* Now scan for a well-formed integer or float.  */
+   while (str < limit)
+     {
+       unsigned char c = *str++;
+       if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
+ 	{
+ 	  c = hex_digit_value (c);
+ 	  max_digit = MAX (c, max_digit);
+ 	  ndigits++;
+ 	}
+       else if (c == '.')
+ 	{
+ 	  if (floatflag == NOT_FLOAT)
+ 	    floatflag = AFTER_POINT;
+ 	  else
+ 	    ERROR ("too many decimal points in floating constant");
+ 	}
+       else if (c == '_')
+ 	/* Possible future extension: silently ignore _ in numbers,
+ 	   permitting cosmetic grouping - e.g. 0x8000_0000 == 0x80000000
+ 	   but somewhat easier to read.  Ada has this?  */
+ 	ERROR ("underscore in number");
+       else if ((radix <= 10 && (c == 'e' || c == 'E'))
+ 	       || (radix == 16 && (c == 'p' || c == 'P')))
+ 	{
+ 	  floatflag = AFTER_EXPON;
+ 	  break;
+ 	}
+       else
+ 	{
+ 	  /* start of suffix.  */
+ 	  str--;
+ 	  break;
+ 	}
+     }
+ 
+   if (floatflag != NOT_FLOAT && radix == 8)
+     radix = 10;
+ 
+   /* This can happen on input like `int i = 0x;' */
+   if (ndigits == 0)
+     ERROR ("numeric constant with no digits");
+ 
+   if (max_digit >= radix)
+     ERROR ("numeric constant contains digits beyond the radix");
+ 
+   if (floatflag != NOT_FLOAT)
+     {
+       if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
+ 	cpp_pedwarn (pfile,
+ 		     "ISO C89 does not include hexadecimal floating constants");
+ 
+       if (radix == 16 && floatflag != AFTER_EXPON)
+ 	ERROR ("hexadecimal floating constant has no exponent");
+ 
+       if (floatflag == AFTER_EXPON)
+ 	{
+ 	  if (*str == '+' || *str == '-')
+ 	    str++;
+ 	  ndigits = 0;
+ 	  /* Exponent is decimal, even if string is a hex float.  */
+ 	  while (ISDIGIT (*str) && str < limit)
+ 	    {
+ 	      str++;
+ 	      ndigits++;
+ 	    }
+ 
+ 	  if (ndigits == 0)
+ 	    ERROR ("floating constant exponent has no digits");
+ 	}
+ 
+       result = interpret_float_suffix (str, limit - str);
+       if (result == 0)
+ 	ERROR2 ("invalid suffix \"%.*s\" on floating constant",
+ 		limit - str, str);
+ 
+       if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
+ 	{
+ 	  if ((result & CPP_N_WIDTH) == CPP_N_SMALL)
+ 	    cpp_warning (pfile, "traditional C rejects the 'f' suffix");
+ 	  else if ((result & CPP_N_WIDTH) == CPP_N_LARGE)
+ 	    cpp_warning (pfile, "traditional C rejects the 'l' suffix");
+ 	}
+ 
+       result |= CPP_N_FLOATING;
+     }
+   else
+     {
+       result = interpret_int_suffix (str, limit - str);
+       if (result == 0)
+ 	ERROR2 ("invalid suffix \"%.*s\" on integer constant",
+ 		limit - str, str);
+ 
+       if (CPP_WTRADITIONAL (pfile)
+ 	  && (result & CPP_N_UNSIGNED)
+ 	  && ! cpp_sys_macro_p (pfile))
+ 	cpp_warning (pfile, "traditional C rejects the 'u' suffix");
+ 
+       if ((result & CPP_N_WIDTH) == CPP_N_LARGE
+ 	  && ! CPP_OPTION (pfile, c99)
+ 	  && CPP_OPTION (pfile, warn_long_long))
+ 	cpp_pedwarn (pfile,
+ 		     "ISO C89 does not include long long integer constants");
+ 
+       result |= CPP_N_INTEGER;
+     }
+ 
+   if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
+     cpp_pedwarn (pfile, "ISO C does not include imaginary numeric constants");
+ 
+   if (radix == 10) result |= CPP_N_DECIMAL;
+   else if (radix == 16) result |= CPP_N_HEX;
+   else result |= CPP_N_OCTAL;
+ 
+   return result;
+ }
+ #undef ERROR
+ #undef ERROR2
+ 
+ unsigned HOST_WIDEST_INT
+ cpp_interpret_integer (pfile, tok, flags)
+      cpp_reader *pfile;
+      const cpp_token *tok;
+      unsigned int flags;
+ {
+   const U_CHAR *start = tok->val.str.text;
+   const U_CHAR *end = start + tok->val.str.len;
+   const U_CHAR *p = start;
+   int c = 0;
+   unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
+   int base = 10;
+   int overflow = 0;
+   int digit;
+ 
+   if ((flags & CPP_N_RADIX) == CPP_N_OCTAL)
+     {
+       base = 8;
+       p++;
+     }
+   else if ((flags & CPP_N_RADIX) == CPP_N_HEX)
+     {
+       base = 16;
+       p += 2;
+     }
+ 
+   /* Some buggy compilers (e.g. MPW C) seem to need both casts.  */
+   MAX_over_base = (((unsigned HOST_WIDEST_INT) -1)
+ 		   / ((unsigned HOST_WIDEST_INT) base));
+ 
+   for(; p < end; p++)
+     {
+       c = *p;
+ 
+       if (c >= '0' && c <= '9')
+ 	digit = c - '0';
+       /* We believe that in all live character sets, a-f are
+ 	 consecutive, and so are A-F.  */
+       else if (base == 16 && c >= 'a' && c <= 'f')
+ 	digit = c - 'a' + 10;
+       else if (base == 16 && c >= 'A' && c <= 'F')
+ 	digit = c - 'A' + 10;
+       else
+ 	break;
+ 
+       nd = n * base + digit;
+       overflow |= MAX_over_base < n || nd < n;
+       n = nd;
+     }
+   
+   if (overflow)
+     cpp_pedwarn (pfile, "integer constant out of maximum supported range");
+   return n;
  }
  
  /* Memory pools.  */
===================================================================
Index: cpplib.h
--- cpplib.h	2001/08/22 20:37:20	1.187
+++ cpplib.h	2001/08/23 04:17:06
@@ -328,6 +328,9 @@ struct cpp_options
      traditional C.  */
   unsigned char warn_traditional;
 
+  /* Nonzero means warn about 'long long' integer constants.  */
+  unsigned char warn_long_long;
+
   /* Nonzero means turn warnings into errors.  */
   unsigned char warnings_are_errors;
 
@@ -529,6 +532,36 @@ extern const unsigned char *cpp_macro_de
 extern HOST_WIDE_INT
 cpp_interpret_charconst PARAMS ((cpp_reader *, const cpp_token *,
 				 int, int, unsigned int *));
+
+/* Classify a CPP_NUMBER token.  The return value is a combination of the
+   flags from these sets:  */
+#define CPP_N_CATEGORY  0x000F
+#define CPP_N_INVALID	0x0000
+#define CPP_N_ZERO	0x0001	/* exactly "0" - treated specially in C++ */
+#define CPP_N_INTEGER	0x0002
+#define CPP_N_FLOATING	0x0003
+
+#define CPP_N_WIDTH	0x00F0
+#define CPP_N_SMALL	0x0010	/* int, float */
+#define CPP_N_MEDIUM	0x0020	/* long, double */
+#define CPP_N_LARGE	0x0030	/* long long, long double */
+
+#define CPP_N_RADIX	0x0F00
+#define CPP_N_DECIMAL	0x0100
+#define CPP_N_HEX	0x0200
+#define CPP_N_OCTAL	0x0400
+
+#define CPP_N_UNSIGNED	0x1000	/* properties */
+#define CPP_N_IMAGINARY	0x2000
+
+extern unsigned int
+cpp_classify_number	PARAMS ((cpp_reader *, const cpp_token *));
+
+/* Evaluate an integer CPP_NUMBER to its value.  The third argument is
+   the flag word returned by cpp_classify_number.  */
+extern unsigned HOST_WIDEST_INT
+cpp_interpret_integer	PARAMS ((cpp_reader *, const cpp_token *,
+				 unsigned int));
 
 extern void cpp_define PARAMS ((cpp_reader *, const char *));
 extern void cpp_assert PARAMS ((cpp_reader *, const char *));
===================================================================
Index: cppinit.c
--- cppinit.c	2001/08/22 20:37:18	1.176
+++ cppinit.c	2001/08/23 04:17:18
@@ -1398,6 +1398,7 @@ cpp_handle_option (pfile, argc, argv)
 	  /* fall through */
 	case OPT_pedantic:
  	  CPP_OPTION (pfile, pedantic) = 1;
+	  CPP_OPTION (pfile, warn_long_long) = 1;
 	  break;
 	case OPT_trigraphs:
  	  CPP_OPTION (pfile, trigraphs) = 1;
@@ -1660,6 +1661,8 @@ cpp_handle_option (pfile, argc, argv)
 	    CPP_OPTION (pfile, warn_undef) = 1;
 	  else if (!strcmp (argv[i], "-Wimport"))
 	    CPP_OPTION (pfile, warn_import) = 1;
+	  else if (!strcmp (argv[i], "-Wlong-long"))
+	    CPP_OPTION (pfile, warn_long_long) = 1;
 	  else if (!strcmp (argv[i], "-Werror"))
 	    CPP_OPTION (pfile, warnings_are_errors) = 1;
 	  else if (!strcmp (argv[i], "-Wsystem-headers"))
@@ -1676,6 +1679,8 @@ cpp_handle_option (pfile, argc, argv)
 	    CPP_OPTION (pfile, warn_undef) = 0;
 	  else if (!strcmp (argv[i], "-Wno-import"))
 	    CPP_OPTION (pfile, warn_import) = 0;
+	  else if (!strcmp (argv[i], "-Wno-long-long"))
+	    CPP_OPTION (pfile, warn_long_long) = 0;
 	  else if (!strcmp (argv[i], "-Wno-error"))
 	    CPP_OPTION (pfile, warnings_are_errors) = 0;
 	  else if (!strcmp (argv[i], "-Wno-system-headers"))
===================================================================
Index: cppexp.c
*** cppexp.c	2001/08/09 13:14:57	1.95
--- cppexp.c	2001/08/23 04:16:50
*************** static HOST_WIDEST_INT right_shift PARAM
*** 35,42 ****
  					    unsigned int,
  					    unsigned HOST_WIDEST_INT));
  static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
  static struct op parse_defined PARAMS ((cpp_reader *));
! static struct op lex PARAMS ((cpp_reader *, int, cpp_token *));
  static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
  
  struct op
--- 35,43 ----
  					    unsigned int,
  					    unsigned HOST_WIDEST_INT));
  static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
+ static struct op parse_name PARAMS ((cpp_reader *, const cpp_token *));
  static struct op parse_defined PARAMS ((cpp_reader *));
! static struct op lex PARAMS ((cpp_reader *, cpp_token *));
  static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
  
  struct op
*************** struct op
*** 61,214 ****
  #define SYNTAX_ERROR2(msgid, arg) \
    do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0)
  
- struct suffix
- {
-   unsigned char s[4];
-   unsigned char u;
-   unsigned char l;
- };
- 
- const struct suffix vsuf_1[] = {
-   { "u", 1, 0 }, { "U", 1, 0 },
-   { "l", 0, 1 }, { "L", 0, 1 }
- };
- 
- const struct suffix vsuf_2[] = {
-   { "ul", 1, 1 }, { "UL", 1, 1 }, { "uL", 1, 1 }, { "Ul", 1, 1 },
-   { "lu", 1, 1 }, { "LU", 1, 1 }, { "Lu", 1, 1 }, { "lU", 1, 1 },
-   { "ll", 0, 2 }, { "LL", 0, 2 }
- };
- 
- const struct suffix vsuf_3[] = {
-   { "ull", 1, 2 }, { "ULL", 1, 2 }, { "uLL", 1, 2 }, { "Ull", 1, 2 },
-   { "llu", 1, 2 }, { "LLU", 1, 2 }, { "LLu", 1, 2 }, { "llU", 1, 2 }
- };
- #define Nsuff(tab) (sizeof tab / sizeof (struct suffix))
  
  /* Parse and convert an integer for #if.  Accepts decimal, hex, or
     octal with or without size suffixes.  Returned op is CPP_ERROR on
     error, otherwise it is a CPP_NUMBER.  */
- 
  static struct op
! parse_number (pfile, tok)
       cpp_reader *pfile;
!      const cpp_token *tok;
  {
    struct op op;
!   const U_CHAR *start = tok->val.str.text;
!   const U_CHAR *end = start + tok->val.str.len;
!   const U_CHAR *p = start;
!   int c = 0, i, nsuff;
!   unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
!   int base = 10;
!   int overflow = 0;
!   int digit, largest_digit = 0;
!   const struct suffix *sufftab;
  
!   op.unsignedp = 0;
  
!   if (p[0] == '0')
      {
!       if (end - start >= 3 && (p[1] == 'x' || p[1] == 'X'))
! 	{
! 	  p += 2;
! 	  base = 16;
! 	}
!       else
! 	{
! 	  p += 1;
! 	  base = 8;
! 	}
!     }
  
!   /* Some buggy compilers (e.g. MPW C) seem to need both casts.  */
!   MAX_over_base = (((unsigned HOST_WIDEST_INT) -1)
! 		   / ((unsigned HOST_WIDEST_INT) base));
  
!   for(; p < end; p++)
!     {
!       c = *p;
  
!       if (c >= '0' && c <= '9')
! 	digit = c - '0';
!       /* We believe that in all live character sets, a-f are
! 	 consecutive, and so are A-F.  */
!       else if (base == 16 && c >= 'a' && c <= 'f')
! 	digit = c - 'a' + 10;
!       else if (base == 16 && c >= 'A' && c <= 'F')
! 	digit = c - 'A' + 10;
!       else
! 	break;
! 
!       if (largest_digit < digit)
! 	largest_digit = digit;
!       nd = n * base + digit;
!       overflow |= MAX_over_base < n || nd < n;
!       n = nd;
!     }
  
!   if (p < end)
!     {
!       /* Check for a floating point constant.  Note that float constants
! 	 with an exponent or suffix but no decimal point are technically
! 	 invalid (C99 6.4.4.2) but accepted elsewhere.  */
!       if ((c == '.' || c == 'F' || c == 'f')
! 	  || (base == 10 && (c == 'E' || c == 'e')
! 	      && p+1 < end && (p[1] == '+' || p[1] == '-'))
! 	  || (base == 16 && (c == 'P' || c == 'p')
! 	      && p+1 < end && (p[1] == '+' || p[1] == '-')))
! 	SYNTAX_ERROR ("floating point numbers are not valid in #if");
!   
!       /* Determine the suffix. l means long, and u means unsigned.
! 	 See the suffix tables, above.  */
!       switch (end - p)
  	{
! 	case 1: sufftab = vsuf_1; nsuff = Nsuff(vsuf_1); break;
! 	case 2: sufftab = vsuf_2; nsuff = Nsuff(vsuf_2); break;
! 	case 3: sufftab = vsuf_3; nsuff = Nsuff(vsuf_3); break;
! 	default: goto invalid_suffix;
  	}
! 
!       for (i = 0; i < nsuff; i++)
! 	if (memcmp (p, sufftab[i].s, end - p) == 0)
! 	  break;
!       if (i == nsuff)
! 	goto invalid_suffix;
!       op.unsignedp = sufftab[i].u;
! 
!       if (CPP_WTRADITIONAL (pfile)
! 	  && sufftab[i].u
! 	  && ! cpp_sys_macro_p (pfile))
! 	cpp_warning (pfile, "traditional C rejects the `U' suffix");
!       if (sufftab[i].l == 2 && CPP_OPTION (pfile, pedantic)
! 	  && ! CPP_OPTION (pfile, c99))
! 	cpp_pedwarn (pfile, "too many 'l' suffixes in integer constant");
      }
!   
!   if (base <= largest_digit)
!     cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
  
!   if (overflow)
!     cpp_pedwarn (pfile, "integer constant out of range");
  
!   /* If too big to be signed, consider it unsigned.  */
!   else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp)
      {
!       if (base == 10)
! 	cpp_warning (pfile, "integer constant is so large that it is unsigned");
!       op.unsignedp = 1;
      }
  
-   op.value = n;
-   op.op = CPP_NUMBER;
    return op;
- 
-  invalid_suffix:
-   cpp_error (pfile, "invalid suffix '%.*s' on integer constant",
- 	     (int) (end - p), p);
-  syntax_error:
-   op.op = CPP_ERROR;
-   return op;
  }
  
  static struct op
--- 62,148 ----
  #define SYNTAX_ERROR2(msgid, arg) \
    do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0)
  
  
  /* Parse and convert an integer for #if.  Accepts decimal, hex, or
     octal with or without size suffixes.  Returned op is CPP_ERROR on
     error, otherwise it is a CPP_NUMBER.  */
  static struct op
! parse_number (pfile, token)
       cpp_reader *pfile;
!      const cpp_token *token;
  {
    struct op op;
!   unsigned int flags = cpp_classify_number (pfile, token);
  
!   op.op = CPP_NUMBER;
!   op.unsignedp = !!(flags & CPP_N_UNSIGNED);
  
!   switch (flags & CPP_N_CATEGORY)
      {
!     case CPP_N_ZERO:
!       op.value = 0; return op;
  
!     case CPP_N_FLOATING:
!       SYNTAX_ERROR ("floating point constants are not valid in #if");
  
!     case CPP_N_INVALID:
!       /* error has already issued.  */
!       goto syntax_error;
  
!     case CPP_N_INTEGER:
!       if (flags & CPP_N_IMAGINARY)
! 	SYNTAX_ERROR ("imaginary numbers are not valid in #if");
  
!       op.value = cpp_interpret_integer (pfile, token, flags);
! 	    
!       /* If too big to be signed, consider it unsigned.  */
!       if (op.value < 0 && ! op.unsignedp)
  	{
! 	  /* If the number is not in decimal, assume it's a bit
! 	     pattern and the programmer meant what they wrote.  */
! 	  if ((flags & CPP_N_RADIX) == CPP_N_DECIMAL)
! 	    cpp_warning (pfile,
! 			 "decimal constant is so large that it is unsigned");
! 	  op.unsignedp = 1;
  	}
!       return op;
      }
! 
!   cpp_fatal (pfile, "impossible number category %x in #if",
! 	     (flags & CPP_N_CATEGORY));
! 
!  syntax_error:
!   op.op = CPP_ERROR;
!   return op;
! }
! 
! static struct op
! parse_name (pfile, token)
!      cpp_reader *pfile;
!      const cpp_token *token;
! {
!   struct op op;
  
!   op.op = CPP_NAME;
!   op.unsignedp = 0;
!   op.value = 0;
  
!   if (CPP_OPTION (pfile, cplusplus)
!       && (token->val.node == pfile->spec_nodes.n_true
! 	  || token->val.node == pfile->spec_nodes.n_false))
      {
!       op.op = CPP_NUMBER;
!       op.value = (token->val.node == pfile->spec_nodes.n_true);
! 
!       /* Warn about use of true or false in #if when pedantic
! 	 and stdbool.h has not been included.  */
!       if (CPP_PEDANTIC (pfile)
! 	  && ! cpp_defined (pfile, DSC("__bool_true_false_are_defined")))
! 	cpp_pedwarn (pfile, "ISO C++ does not permit \"%s\" in #if",
! 		     NODE_NAME (token->val.node));
      }
  
    return op;
  }
  
  static struct op
*************** parse_defined (pfile)
*** 220,225 ****
--- 154,162 ----
    cpp_token token;
    struct op op;
  
+   if (pfile->context->prev && CPP_PEDANTIC (pfile))
+     cpp_pedwarn (pfile, "\"defined\" operator appears during macro expansion");
+ 
    /* Don't expand macros.  */
    pfile->state.prevent_expansion++;
  
*************** parse_defined (pfile)
*** 282,290 ****
     CPP_EOF, or the type of an operator token.  */
  
  static struct op
! lex (pfile, skip_evaluation, token)
       cpp_reader *pfile;
-      int skip_evaluation;
       cpp_token *token;
  {
    struct op op;
--- 219,226 ----
     CPP_EOF, or the type of an operator token.  */
  
  static struct op
! lex (pfile, token)
       cpp_reader *pfile;
       cpp_token *token;
  {
    struct op op;
*************** lex (pfile, skip_evaluation, token)
*** 320,358 ****
  
      case CPP_NAME:
        if (token->val.node == pfile->spec_nodes.n_defined)
! 	{
! 	  if (pfile->context->prev && CPP_PEDANTIC (pfile))
! 	    cpp_pedwarn (pfile, "\"defined\" operator appears during macro expansion");
! 
! 	  return parse_defined (pfile);
! 	}
!       else if (CPP_OPTION (pfile, cplusplus)
! 	       && (token->val.node == pfile->spec_nodes.n_true
! 		   || token->val.node == pfile->spec_nodes.n_false))
! 	{
! 	  op.op = CPP_NUMBER;
! 	  op.unsignedp = 0;
! 	  op.value = (token->val.node == pfile->spec_nodes.n_true);
! 
! 	  /* Warn about use of true or false in #if when pedantic
! 	     and stdbool.h has not been included.  */
! 	  if (CPP_PEDANTIC (pfile)
! 	      && ! cpp_defined (pfile, DSC("__bool_true_false_are_defined")))
! 	    cpp_pedwarn (pfile, "ISO C++ does not permit \"%s\" in #if",
! 			 NODE_NAME (token->val.node));
! 	  return op;
! 	}
        else
! 	{
! 	  op.op = CPP_NUMBER;
! 	  op.unsignedp = 0;
! 	  op.value = 0;
! 
! 	  if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
! 	    cpp_warning (pfile, "\"%s\" is not defined",
! 			 NODE_NAME (token->val.node));
! 	  return op;
! 	}
  
      case CPP_HASH:
        {
--- 256,264 ----
  
      case CPP_NAME:
        if (token->val.node == pfile->spec_nodes.n_defined)
! 	return parse_defined (pfile);
        else
! 	return parse_name (pfile, token);
  
      case CPP_HASH:
        {
*************** _cpp_parse_expr (pfile)
*** 603,609 ****
        struct op op;
  
        /* Read a token */
!       op = lex (pfile, skip_evaluation, &token);
        lex_count++;
  
        /* If the token is an operand, push its value and get next
--- 509,515 ----
        struct op op;
  
        /* Read a token */
!       op = lex (pfile, &token);
        lex_count++;
  
        /* If the token is an operand, push its value and get next
*************** _cpp_parse_expr (pfile)
*** 613,618 ****
--- 519,531 ----
  	{
  	case CPP_ERROR:
  	  goto syntax_error;
+ 
+ 	case CPP_NAME:
+ 	    if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
+ 	      cpp_warning (pfile, "\"%s\" is not defined",
+ 			   NODE_NAME (token.val.node));
+ 	    /* fall through */
+ 
  	push_immediate:
  	case CPP_NUMBER:
  	  /* Push a value onto the stack.  */
===================================================================
Index: c-lex.c
*** c-lex.c	2001/08/22 14:34:45	1.150
--- c-lex.c	2001/08/23 04:16:48
*************** int c_header_level;	 /* depth in C heade
*** 83,90 ****
  /* Nonzero tells yylex to ignore \ in string constants.  */
  static int ignore_escape_flag;
  
! static void parse_float		PARAMS ((PTR));
! static tree lex_number		PARAMS ((const char *, unsigned int));
  static tree lex_string		PARAMS ((const char *, unsigned int, int));
  static tree lex_charconst	PARAMS ((const cpp_token *));
  static void update_header_times	PARAMS ((const char *));
--- 83,96 ----
  /* Nonzero tells yylex to ignore \ in string constants.  */
  static int ignore_escape_flag;
  
! static enum integer_type_kind
! narrowest_unsigned_type		PARAMS ((tree, unsigned int));
! static enum integer_type_kind
! narrowest_signed_type		PARAMS ((tree, unsigned int));
! static void convert_float	PARAMS ((PTR));
! 
! static tree lex_integer		PARAMS ((const cpp_token *, unsigned int));
! static tree lex_float		PARAMS ((const cpp_token *, unsigned int));
  static tree lex_string		PARAMS ((const char *, unsigned int, int));
  static tree lex_charconst	PARAMS ((const cpp_token *));
  static void update_header_times	PARAMS ((const char *));
*************** utf8_extend_token (c)
*** 665,752 ****
    while (shift);
  }
  #endif
- 
- #if 0
- struct try_type
- {
-   tree *node_var;
-   char unsigned_flag;
-   char long_flag;
-   char long_long_flag;
- };
- 
- struct try_type type_sequence[] =
- {
-   { &integer_type_node, 0, 0, 0},
-   { &unsigned_type_node, 1, 0, 0},
-   { &long_integer_type_node, 0, 1, 0},
-   { &long_unsigned_type_node, 1, 1, 0},
-   { &long_long_integer_type_node, 0, 1, 1},
-   { &long_long_unsigned_type_node, 1, 1, 1}
- };
- #endif /* 0 */
- 
- struct pf_args
- {
-   /* Input */
-   const char *str;
-   int fflag;
-   int lflag;
-   int base;
-   /* Output */
-   int conversion_errno;
-   REAL_VALUE_TYPE value;
-   tree type;
- };
   
- static void
- parse_float (data)
-   PTR data;
- {
-   struct pf_args * args = (struct pf_args *) data;
-   const char *typename;
- 
-   args->conversion_errno = 0;
-   args->type = double_type_node;
-   typename = "double";
- 
-   /* The second argument, machine_mode, of REAL_VALUE_ATOF
-      tells the desired precision of the binary result
-      of decimal-to-binary conversion.  */
- 
-   if (args->fflag)
-     {
-       if (args->lflag)
- 	error ("both 'f' and 'l' suffixes on floating constant");
- 
-       args->type = float_type_node;
-       typename = "float";
-     }
-   else if (args->lflag)
-     {
-       args->type = long_double_type_node;
-       typename = "long double";
-     }
-   else if (flag_single_precision_constant)
-     {
-       args->type = float_type_node;
-       typename = "float";
-     }
- 
-   errno = 0;
-   if (args->base == 16)
-     args->value = REAL_VALUE_HTOF (args->str, TYPE_MODE (args->type));
-   else
-     args->value = REAL_VALUE_ATOF (args->str, TYPE_MODE (args->type));
- 
-   args->conversion_errno = errno;
-   /* A diagnostic is required here by some ISO C testsuites.
-      This is not pedwarn, because some people don't want
-      an error for this.  */
-   if (REAL_VALUE_ISINF (args->value) && pedantic)
-     warning ("floating point number exceeds range of '%s'", typename);
- }
-  
  int
  c_lex (value)
       tree *value;
--- 671,677 ----
*************** c_lex (value)
*** 784,790 ****
        break;
  
      case CPP_NUMBER:
!       *value = lex_number ((const char *)tok.val.str.text, tok.val.str.len);
        break;
  
      case CPP_CHAR:
--- 709,737 ----
        break;
  
      case CPP_NUMBER:
!       {
! 	unsigned int flags = cpp_classify_number (parse_in, &tok);
! 
! 	switch (flags & CPP_N_CATEGORY)
! 	  {
! 	  case CPP_N_INVALID:
! 	    /* cpplib has issued an error.  */
! 	  case CPP_N_ZERO:
! 	    *value = integer_zero_node;
! 	    break;
! 
! 	  case CPP_N_INTEGER:
! 	    *value = lex_integer (&tok, flags);
! 	    break;
! 
! 	  case CPP_N_FLOATING:
! 	    *value = lex_float (&tok, flags);
! 	    break;
! 
! 	  default:
! 	    abort ();
! 	  }
!       }
        break;
  
      case CPP_CHAR:
*************** c_lex (value)
*** 809,1292 ****
  
    return type;
  }
- 
- #define ERROR(msgid) do { error(msgid); goto syntax_error; } while(0)
  
! static tree
! lex_number (str, len)
!      const char *str;
!      unsigned int len;
  {
!   int base = 10;
!   int count = 0;
!   int largest_digit = 0;
!   int numdigits = 0;
!   int overflow = 0;
!   int c;
!   tree value;
!   const char *p;
!   enum anon1 { NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON } floatflag = NOT_FLOAT;
    
!   /* 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];
    
!   /* Optimize for most frequent case.  */
!   if (len == 1)
!     {
!       if (*str == '0')
! 	return integer_zero_node;
!       else if (*str == '1')
! 	return integer_one_node;
!       else
! 	return build_int_2 (*str - '0', 0);
!     }
  
!   for (count = 0; count < TOTAL_PARTS; count++)
!     parts[count] = 0;
  
!   /* len is known to be >1 at this point.  */
!   p = str;
  
!   if (len > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
!     {
!       base = 16;
!       p = str + 2;
!     }
!   /* The ISDIGIT check is so we are not confused by a suffix on 0.  */
!   else if (str[0] == '0' && ISDIGIT (str[1]))
!     {
!       base = 8;
!       p = str + 1;
!     }
  
!   do
      {
!       c = *p++;
! 
!       if (c == '.')
! 	{
! 	  if (floatflag == AFTER_POINT)
! 	    ERROR ("too many decimal points in floating constant");
! 	  else if (floatflag == AFTER_EXPON)
! 	    ERROR ("decimal point in exponent - impossible!");
! 	  else
! 	    floatflag = AFTER_POINT;
! 
! 	  if (base == 8)
! 	    base = 10;
! 	}
!       else if (c == '_')
! 	/* Possible future extension: silently ignore _ in numbers,
! 	   permitting cosmetic grouping - e.g. 0x8000_0000 == 0x80000000
! 	   but somewhat easier to read.  Ada has this?  */
! 	ERROR ("underscore in number");
!       else
  	{
! 	  int n;
! 	  /* It is not a decimal point.
! 	     It should be a digit (perhaps a hex digit).  */
! 
! 	  if (ISDIGIT (c))
! 	    {
! 	      n = c - '0';
! 	    }
! 	  else if (base <= 10 && (c == 'e' || c == 'E'))
! 	    {
! 	      base = 10;
! 	      floatflag = AFTER_EXPON;
! 	      break;
! 	    }
! 	  else if (base == 16 && (c == 'p' || c == 'P'))
  	    {
! 	      floatflag = AFTER_EXPON;
! 	      break;   /* start of exponent */
  	    }
- 	  else if (base == 16 && c >= 'a' && c <= 'f')
- 	    {
- 	      n = c - 'a' + 10;
- 	    }
- 	  else if (base == 16 && c >= 'A' && c <= 'F')
- 	    {
- 	      n = c - 'A' + 10;
- 	    }
  	  else
- 	    {
- 	      p--;
- 	      break;  /* start of suffix */
- 	    }
- 
- 	  if (n >= largest_digit)
- 	    largest_digit = n;
- 	  numdigits++;
- 
- 	  for (count = 0; count < TOTAL_PARTS; count++)
- 	    {
- 	      parts[count] *= base;
- 	      if (count)
- 		{
- 		  parts[count]
- 		    += (parts[count-1] >> HOST_BITS_PER_CHAR);
- 		  parts[count-1]
- 		    &= (1 << HOST_BITS_PER_CHAR) - 1;
- 		}
- 	      else
- 		parts[0] += n;
- 	    }
- 
- 	  /* 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;
  	    }
  	}
      }
-   while (p < str + len);
- 
-   /* This can happen on input like `int i = 0x;' */
-   if (numdigits == 0)
-     ERROR ("numeric constant with no digits");
- 
-   if (largest_digit >= base)
-     ERROR ("numeric constant contains digits beyond the radix");
- 
-   if (floatflag != NOT_FLOAT)
-     {
-       tree type;
-       int imag, fflag, lflag, conversion_errno;
-       REAL_VALUE_TYPE real;
-       struct pf_args args;
-       char *copy;
- 
-       if (base == 16 && pedantic && !flag_isoc99)
- 	pedwarn ("floating constant may not be in radix 16");
- 
-       if (base == 16 && floatflag != AFTER_EXPON)
- 	ERROR ("hexadecimal floating constant has no exponent");
- 
-       /* Read explicit exponent if any, and put it in tokenbuf.  */
-       if ((base == 10 && ((c == 'e') || (c == 'E')))
- 	  || (base == 16 && (c == 'p' || c == 'P')))
- 	{
- 	  if (p < str + len)
- 	    c = *p++;
- 	  if (p < str + len && (c == '+' || c == '-'))
- 	    c = *p++;
- 	  /* Exponent is decimal, even if string is a hex float.  */
- 	  if (! ISDIGIT (c))
- 	    ERROR ("floating constant exponent has no digits");
- 	  while (p < str + len && ISDIGIT (c))
- 	    c = *p++;
- 	  if (! ISDIGIT (c))
- 	    p--;
- 	}
- 
-       /* Copy the float constant now; we don't want any suffixes in the
- 	 string passed to parse_float.  */
-       copy = alloca (p - str + 1);
-       memcpy (copy, str, p - str);
-       copy[p - str] = '\0';
- 
-       /* Now parse suffixes.  */
-       fflag = lflag = imag = 0;
-       while (p < str + len)
- 	switch (*p++)
- 	  {
- 	  case 'f': case 'F':
- 	    if (fflag)
- 	      ERROR ("more than one 'f' suffix on floating constant");
- 	    else if (warn_traditional && !in_system_header
- 		     && ! cpp_sys_macro_p (parse_in))
- 	      warning ("traditional C rejects the 'f' suffix");
  
! 	    fflag = 1;
! 	    break;
  
! 	  case 'l': case 'L':
! 	    if (lflag)
! 	      ERROR ("more than one 'l' suffix on floating constant");
! 	    else if (warn_traditional && !in_system_header
! 		     && ! cpp_sys_macro_p (parse_in))
! 	      warning ("traditional C rejects the 'l' suffix");
  
! 	    lflag = 1;
! 	    break;
  
! 	  case 'i': case 'I':
! 	  case 'j': case 'J':
! 	    if (imag)
! 	      ERROR ("more than one 'i' or 'j' suffix on floating constant");
! 	    else if (pedantic)
! 	      pedwarn ("ISO C forbids imaginary numeric constants");
! 	    imag = 1;
! 	    break;
  
! 	  default:
! 	    ERROR ("invalid suffix on floating constant");
! 	  }
  
!       /* Setup input for parse_float() */
!       args.str = copy;
!       args.fflag = fflag;
!       args.lflag = lflag;
!       args.base = base;
  
!       /* Convert string to a double, checking for overflow.  */
!       if (do_float_handler (parse_float, (PTR) &args))
! 	{
! 	  /* Receive output from parse_float() */
! 	  real = args.value;
! 	}
!       else
! 	  /* We got an exception from parse_float() */
! 	  ERROR ("floating constant out of range");
  
-       /* Receive output from parse_float() */
-       conversion_errno = args.conversion_errno;
-       type = args.type;
- 	    
  #ifdef ERANGE
!       /* ERANGE is also reported for underflow,
! 	 so test the value to distinguish overflow from that.  */
!       if (conversion_errno == ERANGE && !flag_traditional && pedantic
! 	  && (REAL_VALUES_LESS (dconst1, real)
! 	      || REAL_VALUES_LESS (real, dconstm1)))
! 	warning ("floating point number exceeds range of 'double'");
  #endif
  
!       /* Create a node with determined type and value.  */
!       if (imag)
! 	value = build_complex (NULL_TREE, convert (type, integer_zero_node),
! 			       build_real (type, real));
!       else
! 	value = build_real (type, real);
      }
    else
      {
!       tree trad_type, ansi_type, type;
!       HOST_WIDE_INT high, low;
!       int spec_unsigned = 0;
!       int spec_long = 0;
!       int spec_long_long = 0;
!       int spec_imag = 0;
!       int suffix_lu = 0;
!       int warn = 0, i;
! 
!       trad_type = ansi_type = type = NULL_TREE;
!       while (p < str + len)
! 	{
! 	  c = *p++;
! 	  switch (c)
! 	    {
! 	    case 'u': case 'U':
! 	      if (spec_unsigned)
! 		error ("two 'u' suffixes on integer constant");
! 	      else if (warn_traditional && !in_system_header
! 		       && ! cpp_sys_macro_p (parse_in))
! 		warning ("traditional C rejects the 'u' suffix");
! 
! 	      spec_unsigned = 1;
! 	      if (spec_long)
! 		suffix_lu = 1;
! 	      break;
! 
! 	    case 'l': case 'L':
! 	      if (spec_long)
! 		{
! 		  if (spec_long_long)
! 		    error ("three 'l' suffixes on integer constant");
! 		  else if (suffix_lu)
! 		    error ("'lul' is not a valid integer suffix");
! 		  else if (c != spec_long)
! 		    error ("'Ll' and 'lL' are not valid integer suffixes");
! 		  else if (pedantic && ! flag_isoc99
! 			   && ! in_system_header && warn_long_long)
! 		    pedwarn ("ISO C89 forbids long long integer constants");
! 		  spec_long_long = 1;
! 		}
! 	      spec_long = c;
! 	      break;
! 
! 	    case 'i': case 'I': case 'j': case 'J':
! 	      if (spec_imag)
! 		error ("more than one 'i' or 'j' suffix on integer constant");
! 	      else if (pedantic)
! 		pedwarn ("ISO C forbids imaginary numeric constants");
! 	      spec_imag = 1;
! 	      break;
! 
! 	    default:
! 	      ERROR ("invalid suffix on integer constant");
! 	    }
! 	}
! 
!       /* 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.  */
! 
!       high = low = 0;
! 
!       for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
! 	{
! 	  high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT
! 					      / HOST_BITS_PER_CHAR)]
! 		   << (i * HOST_BITS_PER_CHAR));
! 	  low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
! 	}
! 
!       value = build_int_2 (low, high);
!       TREE_TYPE (value) = long_long_unsigned_type_node;
! 
!       /* If warn_traditional, calculate both the ISO type and the
! 	 traditional type, then see if they disagree.
! 	 Otherwise, calculate only the type for the dialect in use.  */
!       if (warn_traditional || flag_traditional)
! 	{
! 	  /* Calculate the traditional type.  */
! 	  /* Traditionally, any constant is signed; but if unsigned is
! 	     specified explicitly, obey that.  Use the smallest size
! 	     with the right number of bits, except for one special
! 	     case with decimal constants.  */
! 	  if (! spec_long && base != 10
! 	      && int_fits_type_p (value, unsigned_type_node))
! 	    trad_type = spec_unsigned ? unsigned_type_node : integer_type_node;
! 	  /* A decimal constant must be long if it does not fit in
! 	     type int.  I think this is independent of whether the
! 	     constant is signed.  */
! 	  else if (! spec_long && base == 10
! 		   && int_fits_type_p (value, integer_type_node))
! 	    trad_type = spec_unsigned ? unsigned_type_node : integer_type_node;
! 	  else if (! spec_long_long)
! 	    trad_type = (spec_unsigned
! 			 ? long_unsigned_type_node
! 			 : long_integer_type_node);
! 	  else if (int_fits_type_p (value,
! 				    spec_unsigned 
! 				    ? long_long_unsigned_type_node
! 				    : long_long_integer_type_node)) 
! 	    trad_type = (spec_unsigned
! 			 ? long_long_unsigned_type_node
! 			 : long_long_integer_type_node);
! 	  else
! 	    trad_type = (spec_unsigned
! 			 ? widest_unsigned_literal_type_node
! 			 : widest_integer_literal_type_node);
! 	}
!       if (warn_traditional || ! flag_traditional)
! 	{
! 	  /* Calculate the ISO type.  */
! 	  if (! spec_long && ! spec_unsigned
! 	      && int_fits_type_p (value, integer_type_node))
! 	    ansi_type = integer_type_node;
! 	  else if (! spec_long && (base != 10 || spec_unsigned)
! 		   && int_fits_type_p (value, unsigned_type_node))
! 	    ansi_type = unsigned_type_node;
! 	  else if (! spec_unsigned && !spec_long_long
! 		   && int_fits_type_p (value, long_integer_type_node))
! 	    ansi_type = long_integer_type_node;
! 	  else if (! spec_long_long
! 		   && int_fits_type_p (value, long_unsigned_type_node))
! 	    ansi_type = long_unsigned_type_node;
! 	  else if (! spec_unsigned
! 		   && int_fits_type_p (value, long_long_integer_type_node))
! 	    ansi_type = long_long_integer_type_node;
! 	  else if (int_fits_type_p (value, long_long_unsigned_type_node))
! 	    ansi_type = long_long_unsigned_type_node;
! 	  else if (! spec_unsigned
! 		   && int_fits_type_p (value, widest_integer_literal_type_node))
! 	    ansi_type = widest_integer_literal_type_node;
! 	  else
! 	    ansi_type = widest_unsigned_literal_type_node;
! 	}
! 
!       type = flag_traditional ? trad_type : ansi_type;
! 
!       /* We assume that constants specified in a non-decimal
! 	 base are bit patterns, and that the programmer really
! 	 meant what they wrote.  */
!       if (warn_traditional && !in_system_header
! 	  && base == 10 && trad_type != ansi_type)
! 	{
! 	  if (TYPE_PRECISION (trad_type) != TYPE_PRECISION (ansi_type))
! 	    warning ("width of integer constant changes with -traditional");
! 	  else if (TREE_UNSIGNED (trad_type) != TREE_UNSIGNED (ansi_type))
! 	    warning ("integer constant is unsigned in ISO C, signed with -traditional");
! 	  else
! 	    warning ("width of integer constant may change on other systems with -traditional");
! 	}
! 
!       if (pedantic && !flag_traditional && (flag_isoc99 || !spec_long_long)
! 	  && !warn
! 	  && ((flag_isoc99
! 	       ? TYPE_PRECISION (long_long_integer_type_node)
! 	       : TYPE_PRECISION (long_integer_type_node)) < TYPE_PRECISION (type)))
! 	{
! 	  warn = 1;
! 	  pedwarn ("integer constant larger than the maximum value of %s",
! 		   (flag_isoc99
! 		    ? (TREE_UNSIGNED (type)
! 		       ? "an unsigned long long int"
! 		       : "a long long int")
! 		    : "an unsigned long int"));
! 	}
! 
!       if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
! 	warning ("decimal constant is so large that it is unsigned");
! 
!       if (spec_imag)
! 	{
! 	  if (TYPE_PRECISION (type)
! 	      <= TYPE_PRECISION (integer_type_node))
! 	    value = build_complex (NULL_TREE, integer_zero_node,
! 				   convert (integer_type_node, value));
! 	  else
! 	    ERROR ("complex integer constant is too wide for 'complex int'");
! 	}
!       else if (flag_traditional && !int_fits_type_p (value, type))
! 	/* The traditional constant 0x80000000 is signed
! 	   but doesn't fit in the range of int.
! 	   This will change it to -0x80000000, which does fit.  */
! 	{
! 	  TREE_TYPE (value) = unsigned_type (type);
! 	  value = convert (type, value);
! 	  TREE_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (value) = 0;
! 	}
!       else
! 	TREE_TYPE (value) = type;
! 
!       /* If it's still an integer (not a complex), and it doesn't
! 	 fit in the type we choose for it, then pedwarn.  */
! 
!       if (! warn
! 	  && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
! 	  && ! int_fits_type_p (value, TREE_TYPE (value)))
! 	pedwarn ("integer constant is larger than the maximum value for its type");
      }
  
!   if (p < str + len)
!     error ("missing white space after number '%.*s'", (int) (p - str), str);
  
    return value;
- 
-  syntax_error:
-   return integer_zero_node;
  }
  
  static tree
--- 756,1027 ----
  
    return type;
  }
  
! /* Returns the narrowest C-visible unsigned type, starting with the
!    minimum specified by FLAGS, that can fit VALUE, or itk_none if
!    there isn't one.  */
! static enum integer_type_kind
! narrowest_unsigned_type (value, flags)
!      tree value;
!      unsigned int flags;
  {
!   enum integer_type_kind itk;
    
!   if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
!     itk = itk_unsigned_int;
!   else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
!     itk = itk_unsigned_long;
!   else
!     itk = itk_unsigned_long_long;
! 
!   for (; itk < itk_none; itk += 2 /* skip signed types */)
!     if (int_fits_type_p (value, integer_types[itk]))
!       return itk;
    
!   return itk_none;
! }
  
! /* Ditto, but narrowest signed type.  */
! static enum integer_type_kind
! narrowest_signed_type (value, flags)
!      tree value;
!      unsigned int flags;
! {
!   enum integer_type_kind itk;
  
!   if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
!     itk = itk_int;
!   else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
!     itk = itk_long;
!   else
!     itk = itk_long_long;
  
!   for (; itk < itk_none; itk += 2 /* skip signed types */)
!     if (int_fits_type_p (value, integer_types[itk]))
!       return itk;
!   return itk_none;
! }
  
! static tree
! lex_integer (tok, flags)
!      const cpp_token *tok;
!      unsigned int flags;
! {
!   tree value, type;
!   enum integer_type_kind itk;
!   unsigned HOST_WIDE_INT low, high;
!   unsigned HOST_WIDEST_INT integer;
! 
!   integer = cpp_interpret_integer (parse_in, tok, flags);
!   low = integer & (unsigned HOST_WIDEST_INT) (unsigned HOST_WIDE_INT) -1;
!   high = integer >> HOST_BITS_PER_WIDE_INT;
!   value = build_int_2_wide (low, high);
!   /* int_fits_type_p must think the type of its first argument is
!      wider than its second argument, or it won't do the proper check.  */
!   TREE_TYPE (value) = widest_unsigned_literal_type_node;
! 
!   if (flags & CPP_N_UNSIGNED)
!     /* The type of a constant with a U suffix is straightforward.  */
!     itk = narrowest_unsigned_type (value, flags);
!   else
      {
!       /* The type of a potentially-signed integer constant varies
! 	 depending on the base it's in, the standard in use, and the
! 	 length suffixes.  */
!       enum integer_type_kind itk_u = narrowest_unsigned_type (value, flags);
!       enum integer_type_kind itk_s = narrowest_signed_type (value, flags);
! 
!       /* Traditionally, all constants are signed.  One quirk: a
! 	 non-decimal constant gets type int if it fits in unsigned
! 	 int, even if it doesn't fit in int.  (Standard C assigns
! 	 this case type unsigned int.) */
!       if (flag_traditional)
! 	{
! 	  itk = itk_s;
! 	  if ((flags & CPP_N_RADIX) != CPP_N_DECIMAL
! 	      && itk_u == itk_unsigned_int)
! 	    itk = itk_int;
! 
! 	  if (warn_traditional
! 	      && (flags & CPP_N_RADIX) == CPP_N_DECIMAL
! 	      && itk_s > itk_u && itk_u >= itk_unsigned_long)
! 	    warning ("this decimal constant would be unsigned in ISO C89");
! 	}
! 
!       /* In both C89 and C99, octal and hex constants may be signed or
! 	 unsigned, whichever fits tighter.  We do not warn about this
! 	 choice differing from the traditional choice, as the constant
! 	 is probably a bit pattern and either way will work.  */
!       else if ((flags & CPP_N_RADIX) != CPP_N_DECIMAL)
! 	itk = MIN (itk_u, itk_s);
! 
!       /* In C99, decimal constants are always signed.
! 	 In C89, decimal constants that don't fit in long may have
! 	 type unsigned long.
! 	 In GCC's extended C89, that last is true of decimal constants
! 	 that don't fit in long long, too.  */
!       else if (itk_s > itk_u && itk_u >= itk_unsigned_long)
  	{
! 	  if (!flag_isoc99)
  	    {
! 	      itk = itk_u;
! 	      warning ("this decimal constant is unsigned only in ISO C89");
  	    }
  	  else
  	    {
! 	      itk = itk_s;
! 	      if (warn_traditional)
! 		warning ("this decimal constant would be unsigned in ISO C89");
  	    }
  	}
+       else
+ 	itk = itk_s;
      }
  
!   if (itk == itk_none)
!     /* cpplib has already issued a warning for overflow.  */
!     type = ((flags & CPP_N_UNSIGNED)
! 	    ? widest_unsigned_literal_type_node
! 	    : widest_integer_literal_type_node);
!   else
!     type = integer_types[itk];
  
!   if (itk > itk_unsigned_long
!       && (flags & CPP_N_WIDTH) != CPP_N_LARGE
!       && ! in_system_header && ! flag_isoc99)
!     pedwarn ("integer constant is too large for '%s'",
! 	     (flags & CPP_N_UNSIGNED) ? "unsigned long" : "long");
! 
!   /* Traditionally, a "number so large that it is unsigned" is silently
!      negated; e.g. 0x8000 0000 -> -0x8000 0000.  */
!   if (flag_traditional
!       && !int_fits_type_p (value, type)
!       && int_fits_type_p (value, unsigned_type (type)))
!     {
!       TREE_TYPE (value) = unsigned_type (type);
!       value = convert (type, value);
!       TREE_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (value) = 0;
!     }
! 
!   TREE_TYPE (value) = type;
! 
!   /* Convert imaginary to a complex type.  */
!   if (flags & CPP_N_IMAGINARY)
!     value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);
  
!   return value;
! }
  
! /* Helper routine for lex_float, called via do_float_handler.  */
! struct cf_args
! {
!   /* Input */
!   const char *str;
!   enum machine_mode conversion_mode;
!   int hex_flag;
!   /* Output */
!   REAL_VALUE_TYPE value;
!   int overflow;
! };
!  
! static void
! convert_float (data)
!   PTR data;
! {
!   struct cf_args * args = (struct cf_args *) data;
  
!   errno = 0;
!   if (args->hex_flag)
!     args->value = REAL_VALUE_HTOF (args->str, args->conversion_mode);
!   else
!     args->value = REAL_VALUE_ATOF (args->str, args->conversion_mode);
  
!   args->overflow = 0;
  
!   if (REAL_VALUE_ISINF (args->value))
!     args->overflow = 1;
  
  #ifdef ERANGE
!   /* ERANGE is also reported for underflow, so make sure the value is
!      outside (-1.0, 1.0) before setting overflow.  */
!   else if (errno == ERANGE
! 	   && (REAL_VALUES_LESS (dconst1, args->value)
! 	       || REAL_VALUES_LESS (args->value, dconstm1)))
!     args->overflow = 1;
  #endif
+ }
  
! static tree
! lex_float (token, flags)
!      const cpp_token *token;
!      unsigned int flags;
! {
!   tree type;
!   tree value;
!   struct cf_args args;
!   char *copy;
!   size_t copylen;
!   const char *typename;
! 
!   /* FIXME: make %T work in error/warning, then we don't need typename.  */
!   if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
!     {
!       type = long_double_type_node;
!       typename = "long double";
!     }
!   else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
! 	   || flag_single_precision_constant)
!     {
!       type = float_type_node;
!       typename = "float";
      }
    else
      {
!       type = double_type_node;
!       typename = "double";
      }
+       
+   /* Copy the constant to a nul-terminated buffer.  If the constant
+      has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF
+      can't handle them.  */
+   copylen = token->val.str.len;
+   if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM)
+     /* must be an F or L suffix */
+     copylen--;
+   if (flags & CPP_N_IMAGINARY)
+     /* I or J suffix */
+     copylen--;
+   
+   copy = alloca (copylen + 1);
+   memcpy (copy, token->val.str.text, copylen);
+   copy[copylen] = '\0';
+ 
+   /* Setup for convert_float. */
+   args.str = copy;
+   args.conversion_mode = TYPE_MODE (type);
+   args.hex_flag = (flags & CPP_N_HEX);
+ 
+   if (do_float_handler (convert_float, (PTR) &args) == 0)
+     {
+       /* convert_float trapped.  Treat that as a hard error.  */
+       error ("floating constant out of range");
+       return convert (type, integer_zero_node);
+     }
+ 
+   /* A diagnostic is required for "soft" overflow by some ISO C
+      testsuites.  This is not pedwarn, because some people don't want
+      an error for this.
+      ??? That's a dubious reason... is this a mandatory diagnostic or
+      isn't it?   -- zw, 2001-08-21 */
+   if (pedantic && !flag_traditional && args.overflow)
+     warning ("floating point number exceeds range of '%s'", typename);
  
!   /* Create a node with determined type and value.  */
!   value = build_real (type, args.value);
!   if (flags & CPP_N_IMAGINARY)
!     value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);
  
    return value;
  }
  
  static tree
===================================================================
Index: testsuite/gcc.dg/c90-hexfloat-1.c
--- testsuite/gcc.dg/c90-hexfloat-1.c	2001/05/22 11:02:17	1.2
+++ testsuite/gcc.dg/c90-hexfloat-1.c	2001/08/23 04:17:18
@@ -4,8 +4,8 @@
 /* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
 
 double d = 0x1.2p2; /* { dg-bogus "warning" "warning in place of error" } */
-/* { dg-error "radix 16" "hex float error" { target *-*-* } 6 } */
+/* { dg-error "hexadecimal floating" "hex float error" { target *-*-* } 6 } */
 double d1 = 0x1p2; /* { dg-bogus "warning" "warning in place of error" } */
-/* { dg-error "radix 16" "hex float error" { target *-*-* } 8 } */
+/* { dg-error "hexadecimal floating" "hex float error" { target *-*-* } 8 } */
 double d2 = 0x1...p2; /* { dg-bogus "warning" "warning in place of error" } */
 /* { dg-error "too many decimal points" "bad hex float" { target *-*-* } 10 } */
===================================================================
Index: testsuite/gcc.dg/wtr-int-type-1.c
--- testsuite/gcc.dg/wtr-int-type-1.c	2000/12/07 23:21:09	1.4
+++ testsuite/gcc.dg/wtr-int-type-1.c	2001/08/23 04:17:18
@@ -2,7 +2,7 @@
    Note, gcc should omit these warnings in system header files.
    By Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 8/22/2000.  */
 /* { dg-do compile } */
-/* { dg-options "-Wtraditional" } */
+/* { dg-options "-std=c99 -Wtraditional" } */
 
 void
 testfunc (void)
@@ -18,12 +18,14 @@ testfunc (void)
   i = 0xFFFFFFFFFFFFFFFF;
   i = 01777777777777777777777;
 
-  /* We expect to get either a "width of integer constant changes with
-     -traditional" warning or an "integer constant is unsigned in ISO
-     C, signed with -traditional" warning depending on whether we are
-     testing on a 32 or 64 bit platform.  Either warning means the
-     test passes and both matched by checking for "integer constant".  */
-  i = 18446744073709551615; /* { dg-warning "integer constant" "integer constant" } */
+  /* Nor should values outside the range of (32-bit) unsigned long but
+     inside the range of long long.  [since -traditional has no long long,
+     we can pretend it worked the way it does in C99.]  */
+  i = 9223372036854775807;
+
+  /* But this one should, since it doesn't fit in long (long), but
+     does fit in unsigned long (long).  */
+  i = 18446744073709551615; /* { dg-warning "decimal constant" "decimal constant" } */
   
 # 29 "sys-header.h" 3
 /* We are in system headers now, no -Wtraditional warnings should issue.  */
@@ -35,10 +37,7 @@ testfunc (void)
   i = 0x8000000000000000;
   i = 0xFFFFFFFFFFFFFFFF;
   i = 01777777777777777777777;
-  
+
   i = 9223372036854775807;
   i = 18446744073709551615;
 }
-
-/* Ignore "decimal constant is so large that it is unsigned" warnings.  */
-/* { dg-warning "decimal constant" "decimal constant" { target *-*-* } 26 } */
===================================================================
Index: testsuite/gcc.dg/cpp/c++98-pedantic.c
--- testsuite/gcc.dg/cpp/c++98-pedantic.c	2000/12/02 10:16:01	1.1
+++ testsuite/gcc.dg/cpp/c++98-pedantic.c	2001/08/23 04:17:18
@@ -6,5 +6,5 @@
 /* This file is for testing the preprocessor in -std=c++98 -pedantic mode.
    Neil Booth, 2 Dec 2000.  */
 
-#if 1LL				/* { dg-warning "too many" } */
+#if 1LL				/* { dg-warning "long long integer const" } */
 #endif
===================================================================
Index: testsuite/gcc.dg/cpp/c89-pedantic.c
--- testsuite/gcc.dg/cpp/c89-pedantic.c	2000/12/02 10:16:01	1.1
+++ testsuite/gcc.dg/cpp/c89-pedantic.c	2001/08/23 04:17:18
@@ -6,5 +6,5 @@
 /* This file is for testing the preprocessor in -std=c89 -pedantic mode.
    Neil Booth, 2 Dec 2000.  */
 
-#if 1LL				/* { dg-warning "too many" } */
+#if 1LL				/* { dg-warning "long long integer const" } */
 #endif
===================================================================
Index: testsuite/gcc.dg/cpp/c94-pedantic.c
--- testsuite/gcc.dg/cpp/c94-pedantic.c	2000/12/02 10:16:01	1.1
+++ testsuite/gcc.dg/cpp/c94-pedantic.c	2001/08/23 04:17:18
@@ -6,5 +6,5 @@
 /* This file is for testing the preprocessor in -std=iso9899:199409
    -pedantic mode.  Neil Booth, 2 Dec 2000.  */
 
-#if 1LL				/* { dg-warning "too many" } */
+#if 1LL				/* { dg-warning "long long integer const" } */
 #endif
===================================================================
Index: testsuite/gcc.dg/cpp/gnuc89-pedantic.c
--- testsuite/gcc.dg/cpp/gnuc89-pedantic.c	2000/12/02 10:16:01	1.1
+++ testsuite/gcc.dg/cpp/gnuc89-pedantic.c	2001/08/23 04:17:18
@@ -6,5 +6,5 @@
 /* This file is for testing the preprocessor in -std=gnu89 -pedantic mode.
    Neil Booth, 2 Dec 2000.  */
 
-#if 1LL				/* { dg-warning "too many" } */
+#if 1LL				/* { dg-warning "long long integer const" } */
 #endif
===================================================================
Index: testsuite/gcc.dg/cpp/if-1.c
--- testsuite/gcc.dg/cpp/if-1.c	2000/07/08 02:33:00	1.2
+++ testsuite/gcc.dg/cpp/if-1.c	2001/08/23 04:17:18
@@ -22,7 +22,7 @@
 #error 0xabc	/* { dg-bogus "#error" "normal conversion" } */
 #endif
 
-#if 1.2 /* { dg-error "loating point numbers" "floating point in #if" } */
+#if 1.2 /* { dg-error "loating point" "floating point in #if" } */
 #endif
 
 #if 4uu /* { dg-error "invalid suffix" "too many suffixes" } */
@@ -37,5 +37,5 @@
 #if 099 /* { dg-error "digits beyond the radix" "decimal in octal constant" } */
 #endif
 
-#if 0xfffffffffffffffff /* { dg-error "integer constant out of range" "range error" } */
+#if 0xfffffffffffffffff /* { dg-error "integer constant out" "range error" } */
 #endif
===================================================================
Index: testsuite/gcc.dg/cpp/sysmac2.c
--- testsuite/gcc.dg/cpp/sysmac2.c	2001/05/06 09:48:28	1.3
+++ testsuite/gcc.dg/cpp/sysmac2.c	2001/08/23 04:17:18
@@ -1,7 +1,7 @@
 /* Copyright (C) 2001 Free Software Foundation, Inc.  */
 
 /* { dg-do compile } */
-/* { dg-options "-std=gnu99 -pedantic -Wtraditional" } */
+/* { dg-options "-std=gnu99 -pedantic -Wtraditional -fno-show-column" } */
 
 /* Tests diagnostics are suppressed for some macros defined in system
    headers.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]