This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Integer constant parsing overhaul
- To: gcc-patches at gcc dot gnu dot org, jsm28 at cam dot ac dot uk
- Subject: Integer constant parsing overhaul
- From: Zack Weinberg <zackw at panix dot com>
- Date: Thu, 23 Aug 2001 00:51:52 -0400
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. */