diff options
-rw-r--r-- | contrib/gcc/c-lex.c | 856 |
1 files changed, 243 insertions, 613 deletions
diff --git a/contrib/gcc/c-lex.c b/contrib/gcc/c-lex.c index 3659872..30f89ab 100644 --- a/contrib/gcc/c-lex.c +++ b/contrib/gcc/c-lex.c @@ -1,6 +1,6 @@ -/* Lexical analyzer for C and Objective C. +/* Mainly the interface between cpplib and the C front ends. Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997 - 1998, 1999, 2000 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GCC. @@ -24,13 +24,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" +#include "real.h" #include "rtl.h" #include "tree.h" #include "expr.h" #include "input.h" #include "output.h" -#include "c-lex.h" #include "c-tree.h" +#include "c-common.h" #include "flags.h" #include "timevar.h" #include "cpplib.h" @@ -41,20 +42,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "splay-tree.h" #include "debug.h" -/* MULTIBYTE_CHARS support only works for native compilers. - ??? Ideally what we want is to model widechar support after - the current floating point support. */ -#ifdef CROSS_COMPILE -#undef MULTIBYTE_CHARS -#endif - #ifdef MULTIBYTE_CHARS #include "mbchar.h" #include <locale.h> #endif /* MULTIBYTE_CHARS */ -#ifndef GET_ENVIRONMENT -#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ((ENV_VALUE) = getenv (ENV_NAME)) -#endif /* The current line map. */ static const struct line_map *map; @@ -66,9 +57,6 @@ static unsigned int src_lineno; static int header_time, body_time; static splay_tree file_info_tree; -/* Cause the `yydebug' variable to be defined. */ -#define YYDEBUG 1 - /* File used for outputting assembler code. */ extern FILE *asm_out_file; @@ -78,15 +66,18 @@ extern FILE *asm_out_file; /* Number of bytes in a wide character. */ #define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT) -int indent_level; /* Number of { minus number of }. */ int pending_lang_change; /* If we need to switch languages - C++ only */ int c_header_level; /* depth in C headers - C++ only */ /* 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 interpret_integer PARAMS ((const cpp_token *, unsigned int)); +static tree interpret_float PARAMS ((const cpp_token *, unsigned int)); +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 tree lex_string PARAMS ((const unsigned char *, unsigned int, int)); static tree lex_charconst PARAMS ((const cpp_token *)); @@ -146,9 +137,6 @@ init_c_lex (filename) /* Start it at 0. */ lineno = 0; - if (filename == NULL || !strcmp (filename, "-")) - filename = ""; - return cpp_read_main_file (parse_in, filename, ident_hash); } @@ -157,13 +145,21 @@ init_c_lex (filename) Also, make sure the start_source_file debug hook gets called for the primary source file. */ -int -yyparse() +void +c_common_parse_file (set_yydebug) + int set_yydebug ATTRIBUTE_UNUSED; { +#if YYDEBUG != 0 + yydebug = set_yydebug; +#else + warning ("YYDEBUG not defined"); +#endif + (*debug_hooks->start_source_file) (lineno, input_filename); cpp_finish_options (parse_in); - return yyparse_1(); + yyparse (); + free_parser_stacks (); } struct c_fileinfo * @@ -229,9 +225,6 @@ dump_time_statistics () splay_tree_foreach (file_info_tree, dump_one_header, 0); } -/* Not yet handled: #pragma, #define, #undef. - No need to deal with linemarkers under normal conditions. */ - static void cb_ident (pfile, line, str) cpp_reader *pfile ATTRIBUTE_UNUSED; @@ -278,7 +271,6 @@ cb_file_change (pfile, new_map) lineno = included_at; push_srcloc (new_map->to_file, 1); - input_file_stack->indent_level = indent_level; (*debug_hooks->start_source_file) (included_at, new_map->to_file); #ifndef NO_IMPLICIT_EXTERN_C if (c_header_level) @@ -301,16 +293,6 @@ cb_file_change (pfile, new_map) --pending_lang_change; } #endif -#if 0 - if (indent_level != input_file_stack->indent_level) - { - warning_with_file_and_line - (input_filename, lineno, - "this file contains more '%c's than '%c's", - indent_level > input_file_stack->indent_level ? '{' : '}', - indent_level > input_file_stack->indent_level ? '}' : '{'); - } -#endif pop_srcloc (); (*debug_hooks->end_source_file) (to_line); @@ -688,88 +670,7 @@ utf8_extend_token (c) while (shift); } #endif - -#if 0 -struct try_type -{ - tree *const node_var; - const char unsigned_flag; - const char long_flag; - const 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; @@ -791,9 +692,6 @@ c_lex (value) *value = NULL_TREE; switch (tok->type) { - case CPP_OPEN_BRACE: indent_level++; break; - case CPP_CLOSE_BRACE: indent_level--; break; - /* Issue this error here, where we can get at tok->val.c. */ case CPP_OTHER: if (ISGRAPH (tok->val.c)) @@ -807,7 +705,28 @@ c_lex (value) break; case CPP_NUMBER: - *value = lex_number ((const char *)tok->val.str.text, tok->val.str.len); + { + unsigned int flags = cpp_classify_number (parse_in, tok); + + switch (flags & CPP_N_CATEGORY) + { + case CPP_N_INVALID: + /* cpplib has issued an error. */ + *value = error_mark_node; + break; + + case CPP_N_INTEGER: + *value = interpret_integer (tok, flags); + break; + + case CPP_N_FLOATING: + *value = interpret_float (tok, flags); + break; + + default: + abort (); + } + } break; case CPP_CHAR: @@ -833,476 +752,203 @@ c_lex (value) return tok->type; } -#define ERROR(msgid) do { error(msgid); goto syntax_error; } while(0) - -static tree -lex_number (str, len) - const char *str; - unsigned int len; +/* 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; { - 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); - } + enum integer_type_kind itk; - 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) - || (base == 16 && ISXDIGIT (c))) - { - n = hex_value (c); - } - 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 - { - 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--; - } + 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; - /* 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'; + /* 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; - /* 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; + for (; itk < itk_none; itk += 2 /* skip unsigned types */) + if (int_fits_type_p (value, integer_types[itk])) + return itk; - 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"); + return itk_none; +} - lflag = 1; - break; +/* 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; - 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; + 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; - default: - ERROR ("invalid suffix on floating constant"); - } + /* 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; - /* Setup input for parse_float() */ - args.str = copy; - args.fflag = fflag; - args.lflag = lflag; - args.base = base; + for (; itk < itk_none; itk += 2 /* skip signed types */) + if (int_fits_type_p (value, integer_types[itk])) + return itk; - /* 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 + return itk_none; +} - /* 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); - } +/* Interpret TOKEN, an integer with FLAGS as classified by cpplib. */ +static tree +interpret_integer (token, flags) + const cpp_token *token; + unsigned int flags; +{ + tree value, type; + enum integer_type_kind itk; + cpp_num integer; + cpp_options *options = cpp_get_options (parse_in); + + integer = cpp_interpret_integer (parse_in, token, flags); + integer = cpp_num_sign_extend (integer, options->precision); + value = build_int_2_wide (integer.low, integer.high); + + /* The type of a constant with a U suffix is straightforward. */ + if (flags & CPP_N_UNSIGNED) + itk = narrowest_unsigned_type (value, flags); 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) + /* 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); + + /* 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. */ + if ((flags & CPP_N_RADIX) != CPP_N_DECIMAL) + itk = MIN (itk_u, itk_s); + else { - c = *p++; - switch (c) + /* In C99, decimal constants are always signed. + In C89, decimal constants that don't fit in long have + undefined behavior; we try to make them unsigned long. + In GCC's extended C89, that last is true of decimal + constants that don't fit in long long, too. */ + + itk = itk_s; + if (itk_s > itk_u && itk_s > itk_long) { - 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 (!flag_isoc99) { - 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; + if (itk_u < itk_unsigned_long) + itk_u = itk_unsigned_long; + itk = itk_u; + warning ("this decimal constant is unsigned only in ISO C90"); } - 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"); + else if (warn_traditional) + warning ("this decimal constant would be unsigned in ISO C90"); } } + } - /* 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; + 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]; - /* 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 (itk > itk_unsigned_long + && (flags & CPP_N_WIDTH) != CPP_N_LARGE + && ! in_system_header && ! flag_isoc99) + pedwarn ("integer constant is too large for \"%s\" type", + (flags & CPP_N_UNSIGNED) ? "unsigned long" : "long"); - 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"))); - } + TREE_TYPE (value) = type; - if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) - warning ("decimal constant is so large that it is unsigned"); + /* Convert imaginary to a complex type. */ + if (flags & CPP_N_IMAGINARY) + value = build_complex (NULL_TREE, convert (type, integer_zero_node), value); - 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; + return value; +} - /* If it's still an integer (not a complex), and it doesn't - fit in the type we choose for it, then pedwarn. */ +/* Interpret TOKEN, a floating point number with FLAGS as classified + by cpplib. */ +static tree +interpret_float (token, flags) + const cpp_token *token; + unsigned int flags; +{ + tree type; + tree value; + REAL_VALUE_TYPE real; + char *copy; + size_t copylen; + const char *typename; - 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"); + /* 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"; } - if (p < str + len) - error ("missing white space after number '%.*s'", (int) (p - str), str); + /* 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'; + + real_from_string (&real, copy); + real_convert (&real, TYPE_MODE (type), &real); + + /* 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 (REAL_VALUE_ISINF (real) && pedantic) + warning ("floating constant exceeds range of \"%s\"", typename); + + /* Create a node with determined type and value. */ + value = build_real (type, real); + if (flags & CPP_N_IMAGINARY) + value = build_complex (NULL_TREE, convert (type, integer_zero_node), value); return value; - - syntax_error: - return integer_zero_node; } static tree @@ -1315,9 +961,7 @@ lex_string (str, len, wide) char *buf = alloca ((len + 1) * (wide ? WCHAR_BYTES : 1)); char *q = buf; const unsigned char *p = str, *limit = str + len; - unsigned int c; - unsigned width = wide ? WCHAR_TYPE_SIZE - : TYPE_PRECISION (char_type_node); + cppchar_t c; #ifdef MULTIBYTE_CHARS /* Reset multibyte conversion state. */ @@ -1347,19 +991,10 @@ lex_string (str, len, wide) #endif if (c == '\\' && !ignore_escape_flag) - { - unsigned int mask; - - if (width < HOST_BITS_PER_INT) - mask = ((unsigned int) 1 << width) - 1; - else - mask = ~0; - c = cpp_parse_escape (parse_in, &p, limit, - mask, flag_traditional); - } + c = cpp_parse_escape (parse_in, &p, limit, wide); - /* Add this single character into the buffer either as a wchar_t - or as a single byte. */ + /* Add this single character into the buffer either as a wchar_t, + a multibyte sequence, or as a single byte. */ if (wide) { unsigned charwidth = TYPE_PRECISION (char_type_node); @@ -1380,6 +1015,16 @@ lex_string (str, len, wide) } q += WCHAR_BYTES; } +#ifdef MULTIBYTE_CHARS + else if (char_len > 1) + { + /* We're dealing with a multibyte character. */ + for ( ; char_len >0; --char_len) + { + *q++ = *(p - char_len); + } + } +#endif else { *q++ = c; @@ -1413,45 +1058,30 @@ static tree lex_charconst (token) const cpp_token *token; { - HOST_WIDE_INT result; + cppchar_t result; tree type, value; unsigned int chars_seen; - - result = cpp_interpret_charconst (parse_in, token, warn_multichar, - flag_traditional, &chars_seen); - if (token->type == CPP_WCHAR) - { - value = build_int_2 (result, 0); - type = wchar_type_node; - } - else - { - if (result < 0) - value = build_int_2 (result, -1); - else - value = build_int_2 (result, 0); - - /* In C, a character constant has type 'int'. - In C++ 'char', but multi-char charconsts have type 'int'. */ - if (c_language == clk_cplusplus && chars_seen <= 1) - type = char_type_node; - else - type = integer_type_node; - } + int unsignedp; - /* cpp_interpret_charconst issues a warning if the constant - overflows, but if the number fits in HOST_WIDE_INT anyway, it - will return it un-truncated, which may cause problems down the - line. So set the type to widest_integer_literal_type, call - convert to truncate it to the proper type, then clear - TREE_OVERFLOW so we don't get a second warning. + result = cpp_interpret_charconst (parse_in, token, + &chars_seen, &unsignedp); - FIXME: cpplib's assessment of overflow may not be accurate on a - platform where the final type can change at (compiler's) runtime. */ + /* Cast to cppchar_signed_t to get correct sign-extension of RESULT + before possibly widening to HOST_WIDE_INT for build_int_2. */ + if (unsignedp || (cppchar_signed_t) result >= 0) + value = build_int_2 (result, 0); + else + value = build_int_2 ((cppchar_signed_t) result, -1); - TREE_TYPE (value) = widest_integer_literal_type_node; - value = convert (type, value); - TREE_OVERFLOW (value) = 0; + if (token->type == CPP_WCHAR) + type = wchar_type_node; + /* In C, a character constant has type 'int'. + In C++ 'char', but multi-char charconsts have type 'int'. */ + else if ((c_language == clk_c) || chars_seen > 1) + type = integer_type_node; + else + type = char_type_node; + TREE_TYPE (value) = type; return value; } |