Mercurial > hg > CbC > CbC_gcc
diff libcpp/expr.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/libcpp/expr.c Sun Aug 21 07:07:55 2011 +0900 +++ b/libcpp/expr.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,6 +1,5 @@ /* Parse C expressions for cpplib. - Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001, - 2002, 2004, 2008, 2009, 2010 Free Software Foundation. + Copyright (C) 1987-2017 Free Software Foundation, Inc. Contributed by Per Bothner, 1994. This program is free software; you can redistribute it and/or modify it @@ -59,12 +58,14 @@ static cpp_num append_digit (cpp_num, int, int, size_t); static cpp_num parse_defined (cpp_reader *); -static cpp_num eval_token (cpp_reader *, const cpp_token *); +static cpp_num eval_token (cpp_reader *, const cpp_token *, source_location); static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype); -static unsigned int interpret_float_suffix (const uchar *, size_t); -static unsigned int interpret_int_suffix (const uchar *, size_t); +static unsigned int interpret_float_suffix (cpp_reader *, const uchar *, size_t); +static unsigned int interpret_int_suffix (cpp_reader *, const uchar *, size_t); static void check_promotion (cpp_reader *, const struct op *); +static cpp_num parse_has_include (cpp_reader *, enum include_type); + /* Token type abuse to create unary plus and minus operators. */ #define CPP_UPLUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 1)) #define CPP_UMINUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 2)) @@ -76,18 +77,61 @@ #define SYNTAX_ERROR2(msgid, arg) \ do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \ while(0) +#define SYNTAX_ERROR_AT(loc, msgid) \ + do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid); goto syntax_error; } \ + while(0) +#define SYNTAX_ERROR2_AT(loc, msgid, arg) \ + do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid, arg); goto syntax_error; } \ + while(0) /* Subroutine of cpp_classify_number. S points to a float suffix of length LEN, possibly zero. Returns 0 for an invalid suffix, or a - flag vector describing the suffix. */ + flag vector (of CPP_N_* bits) describing the suffix. */ static unsigned int -interpret_float_suffix (const uchar *s, size_t len) +interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len) { size_t flags; - size_t f, d, l, w, q, i; + size_t f, d, l, w, q, i, fn, fnx, fn_bits; flags = 0; - f = d = l = w = q = i = 0; + f = d = l = w = q = i = fn = fnx = fn_bits = 0; + + /* The following decimal float suffixes, from TR 24732:2009 and TS + 18661-2:2015, are supported: + + df, DF - _Decimal32. + dd, DD - _Decimal64. + dl, DL - _Decimal128. + + The dN and DN suffixes for _DecimalN, and dNx and DNx for + _DecimalNx, defined in TS 18661-3:2015, are not supported. + + Fixed-point suffixes, from TR 18037:2008, are supported. They + consist of three parts, in order: + + (i) An optional u or U, for unsigned types. + + (ii) An optional h or H, for short types, or l or L, for long + types, or ll or LL, for long long types. Use of ll or LL is a + GNU extension. + + (iii) r or R, for _Fract types, or k or K, for _Accum types. + + Otherwise the suffix is for a binary or standard floating-point + type. Such a suffix, or the absence of a suffix, may be preceded + or followed by i, I, j or J, to indicate an imaginary number with + the corresponding complex type. The following suffixes for + binary or standard floating-point types are supported: + + f, F - float (ISO C and C++). + l, L - long double (ISO C and C++). + d, D - double, even with the FLOAT_CONST_DECIMAL64 pragma in + operation (from TR 24732:2009; the pragma and the suffix + are not included in TS 18661-2:2015). + w, W - machine-specific type such as __float80 (GNU extension). + q, Q - machine-specific type such as __float128 (GNU extension). + fN, FN - _FloatN (TS 18661-3:2015). + fNx, FNx - _FloatNx (TS 18661-3:2015). */ /* Process decimal float suffixes, which are two letters starting with d or D. Order and case are significant. */ @@ -109,72 +153,126 @@ } } - /* Recognize a fixed-point suffix. */ - switch (s[len-1]) + if (CPP_OPTION (pfile, ext_numeric_literals)) { - case 'k': case 'K': flags = CPP_N_ACCUM; break; - case 'r': case 'R': flags = CPP_N_FRACT; break; - default: break; - } + /* Recognize a fixed-point suffix. */ + if (len != 0) + switch (s[len-1]) + { + case 'k': case 'K': flags = CPP_N_ACCUM; break; + case 'r': case 'R': flags = CPP_N_FRACT; break; + default: break; + } - /* Continue processing a fixed-point suffix. The suffix is case - insensitive except for ll or LL. Order is significant. */ - if (flags) - { - if (len == 1) - return flags; - len--; - - if (*s == 'u' || *s == 'U') + /* Continue processing a fixed-point suffix. The suffix is case + insensitive except for ll or LL. Order is significant. */ + if (flags) { - flags |= CPP_N_UNSIGNED; if (len == 1) return flags; len--; - s++; - } + + if (*s == 'u' || *s == 'U') + { + flags |= CPP_N_UNSIGNED; + if (len == 1) + return flags; + len--; + s++; + } - switch (*s) - { - case 'h': case 'H': - if (len == 1) - return flags |= CPP_N_SMALL; - break; - case 'l': - if (len == 1) - return flags |= CPP_N_MEDIUM; - if (len == 2 && s[1] == 'l') - return flags |= CPP_N_LARGE; - break; - case 'L': - if (len == 1) - return flags |= CPP_N_MEDIUM; - if (len == 2 && s[1] == 'L') - return flags |= CPP_N_LARGE; - break; - default: - break; - } - /* Anything left at this point is invalid. */ - return 0; + switch (*s) + { + case 'h': case 'H': + if (len == 1) + return flags |= CPP_N_SMALL; + break; + case 'l': + if (len == 1) + return flags |= CPP_N_MEDIUM; + if (len == 2 && s[1] == 'l') + return flags |= CPP_N_LARGE; + break; + case 'L': + if (len == 1) + return flags |= CPP_N_MEDIUM; + if (len == 2 && s[1] == 'L') + return flags |= CPP_N_LARGE; + break; + default: + break; + } + /* Anything left at this point is invalid. */ + return 0; + } } /* In any remaining valid suffix, the case and order don't matter. */ while (len--) - switch (s[len]) - { - case 'f': case 'F': f++; break; - case 'd': case 'D': d++; break; - case 'l': case 'L': l++; break; - case 'w': case 'W': w++; break; - case 'q': case 'Q': q++; break; - case 'i': case 'I': - case 'j': case 'J': i++; break; - default: - return 0; - } + { + switch (s[0]) + { + case 'f': case 'F': + f++; + if (len > 0 + && !CPP_OPTION (pfile, cplusplus) + && s[1] >= '1' + && s[1] <= '9' + && fn_bits == 0) + { + f--; + while (len > 0 + && s[1] >= '0' + && s[1] <= '9' + && fn_bits < CPP_FLOATN_MAX) + { + fn_bits = fn_bits * 10 + (s[1] - '0'); + len--; + s++; + } + if (len > 0 && s[1] == 'x') + { + fnx++; + len--; + s++; + } + else + fn++; + } + break; + case 'd': case 'D': d++; break; + case 'l': case 'L': l++; break; + case 'w': case 'W': w++; break; + case 'q': case 'Q': q++; break; + case 'i': case 'I': + case 'j': case 'J': i++; break; + default: + return 0; + } + s++; + } - if (f + d + l + w + q > 1 || i > 1) + /* Reject any case of multiple suffixes specifying types, multiple + suffixes specifying an imaginary constant, _FloatN or _FloatNx + suffixes for invalid values of N, and _FloatN suffixes for values + of N larger than can be represented in the return value. The + caller is responsible for rejecting _FloatN suffixes where + _FloatN is not supported on the chosen target. */ + if (f + d + l + w + q + fn + fnx > 1 || i > 1) + return 0; + if (fn_bits > CPP_FLOATN_MAX) + return 0; + if (fnx && fn_bits != 32 && fn_bits != 64 && fn_bits != 128) + return 0; + if (fn && fn_bits != 16 && fn_bits % 32 != 0) + return 0; + if (fn && fn_bits == 96) + return 0; + + if (i && !CPP_OPTION (pfile, ext_numeric_literals)) + return 0; + + if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals)) return 0; return ((i ? CPP_N_IMAGINARY : 0) @@ -182,14 +280,24 @@ d ? CPP_N_MEDIUM : l ? CPP_N_LARGE : w ? CPP_N_MD_W : - q ? CPP_N_MD_Q : CPP_N_DEFAULT)); + q ? CPP_N_MD_Q : + fn ? CPP_N_FLOATN | (fn_bits << CPP_FLOATN_SHIFT) : + fnx ? CPP_N_FLOATNX | (fn_bits << CPP_FLOATN_SHIFT) : + CPP_N_DEFAULT)); +} + +/* Return the classification flags for a float suffix. */ +unsigned int +cpp_interpret_float_suffix (cpp_reader *pfile, const char *s, size_t len) +{ + return interpret_float_suffix (pfile, (const unsigned char *)s, len); } /* Subroutine of cpp_classify_number. S points to an integer suffix of length LEN, possibly zero. Returns 0 for an invalid suffix, or a flag vector describing the suffix. */ static unsigned int -interpret_int_suffix (const uchar *s, size_t len) +interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len) { size_t u, l, i; @@ -213,23 +321,174 @@ if (l > 2 || u > 1 || i > 1) return 0; + if (i && !CPP_OPTION (pfile, ext_numeric_literals)) + 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)); } +/* Return the classification flags for an int suffix. */ +unsigned int +cpp_interpret_int_suffix (cpp_reader *pfile, const char *s, size_t len) +{ + return interpret_int_suffix (pfile, (const unsigned char *)s, len); +} + +/* Return the string type corresponding to the the input user-defined string + literal type. If the input type is not a user-defined string literal + type return the input type. */ +enum cpp_ttype +cpp_userdef_string_remove_type (enum cpp_ttype type) +{ + if (type == CPP_STRING_USERDEF) + return CPP_STRING; + else if (type == CPP_WSTRING_USERDEF) + return CPP_WSTRING; + else if (type == CPP_STRING16_USERDEF) + return CPP_STRING16; + else if (type == CPP_STRING32_USERDEF) + return CPP_STRING32; + else if (type == CPP_UTF8STRING_USERDEF) + return CPP_UTF8STRING; + else + return type; +} + +/* Return the user-defined string literal type corresponding to the input + string type. If the input type is not a string type return the input + type. */ +enum cpp_ttype +cpp_userdef_string_add_type (enum cpp_ttype type) +{ + if (type == CPP_STRING) + return CPP_STRING_USERDEF; + else if (type == CPP_WSTRING) + return CPP_WSTRING_USERDEF; + else if (type == CPP_STRING16) + return CPP_STRING16_USERDEF; + else if (type == CPP_STRING32) + return CPP_STRING32_USERDEF; + else if (type == CPP_UTF8STRING) + return CPP_UTF8STRING_USERDEF; + else + return type; +} + +/* Return the char type corresponding to the the input user-defined char + literal type. If the input type is not a user-defined char literal + type return the input type. */ +enum cpp_ttype +cpp_userdef_char_remove_type (enum cpp_ttype type) +{ + if (type == CPP_CHAR_USERDEF) + return CPP_CHAR; + else if (type == CPP_WCHAR_USERDEF) + return CPP_WCHAR; + else if (type == CPP_CHAR16_USERDEF) + return CPP_CHAR16; + else if (type == CPP_CHAR32_USERDEF) + return CPP_CHAR32; + else if (type == CPP_UTF8CHAR_USERDEF) + return CPP_UTF8CHAR; + else + return type; +} + +/* Return the user-defined char literal type corresponding to the input + char type. If the input type is not a char type return the input + type. */ +enum cpp_ttype +cpp_userdef_char_add_type (enum cpp_ttype type) +{ + if (type == CPP_CHAR) + return CPP_CHAR_USERDEF; + else if (type == CPP_WCHAR) + return CPP_WCHAR_USERDEF; + else if (type == CPP_CHAR16) + return CPP_CHAR16_USERDEF; + else if (type == CPP_CHAR32) + return CPP_CHAR32_USERDEF; + else if (type == CPP_UTF8CHAR) + return CPP_UTF8CHAR_USERDEF; + else + return type; +} + +/* Return true if the token type is a user-defined string literal. */ +bool +cpp_userdef_string_p (enum cpp_ttype type) +{ + if (type == CPP_STRING_USERDEF + || type == CPP_WSTRING_USERDEF + || type == CPP_STRING16_USERDEF + || type == CPP_STRING32_USERDEF + || type == CPP_UTF8STRING_USERDEF) + return true; + else + return false; +} + +/* Return true if the token type is a user-defined char literal. */ +bool +cpp_userdef_char_p (enum cpp_ttype type) +{ + if (type == CPP_CHAR_USERDEF + || type == CPP_WCHAR_USERDEF + || type == CPP_CHAR16_USERDEF + || type == CPP_CHAR32_USERDEF + || type == CPP_UTF8CHAR_USERDEF) + return true; + else + return false; +} + +/* Extract the suffix from a user-defined literal string or char. */ +const char * +cpp_get_userdef_suffix (const cpp_token *tok) +{ + unsigned int len = tok->val.str.len; + const char *text = (const char *)tok->val.str.text; + char delim; + unsigned int i; + for (i = 0; i < len; ++i) + if (text[i] == '\'' || text[i] == '"') + break; + if (i == len) + return text + len; + delim = text[i]; + for (i = len; i > 0; --i) + if (text[i - 1] == delim) + break; + return text + i; +} + /* Categorize numeric constants according to their field (integer, floating point, or invalid), radix (decimal, octal, hexadecimal), - and type suffixes. */ + and type suffixes. + + TOKEN is the token that represents the numeric constant to + classify. + + In C++0X if UD_SUFFIX is non null it will be assigned + any unrecognized suffix for a user-defined literal. + + VIRTUAL_LOCATION is the virtual location for TOKEN. */ unsigned int -cpp_classify_number (cpp_reader *pfile, const cpp_token *token) +cpp_classify_number (cpp_reader *pfile, const cpp_token *token, + const char **ud_suffix, source_location virtual_location) { const uchar *str = token->val.str.text; const uchar *limit; unsigned int max_digit, result, radix; enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag; bool seen_digit; + bool seen_digit_sep; + + if (ud_suffix) + *ud_suffix = NULL; /* If the lexer has done its job, length one can only be a single digit. Fast-path this very common case. */ @@ -241,6 +500,7 @@ max_digit = 0; radix = 10; seen_digit = false; + seen_digit_sep = false; /* First, interpret the radix. */ if (*str == '0') @@ -249,16 +509,27 @@ str++; /* Require at least one hex digit to classify it as hex. */ - if ((*str == 'x' || *str == 'X') - && (str[1] == '.' || ISXDIGIT (str[1]))) + if (*str == 'x' || *str == 'X') { - radix = 16; - str++; + if (str[1] == '.' || ISXDIGIT (str[1])) + { + radix = 16; + str++; + } + else if (DIGIT_SEP (str[1])) + SYNTAX_ERROR_AT (virtual_location, + "digit separator after base indicator"); } - else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1')) + else if (*str == 'b' || *str == 'B') { - radix = 2; - str++; + if (str[1] == '0' || str[1] == '1') + { + radix = 2; + str++; + } + else if (DIGIT_SEP (str[1])) + SYNTAX_ERROR_AT (virtual_location, + "digit separator after base indicator"); } } @@ -269,21 +540,36 @@ if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16)) { + seen_digit_sep = false; seen_digit = true; c = hex_value (c); if (c > max_digit) max_digit = c; } + else if (DIGIT_SEP (c)) + { + if (seen_digit_sep) + SYNTAX_ERROR_AT (virtual_location, "adjacent digit separators"); + seen_digit_sep = true; + } else if (c == '.') { + if (seen_digit_sep || DIGIT_SEP (*str)) + SYNTAX_ERROR_AT (virtual_location, + "digit separator adjacent to decimal point"); + seen_digit_sep = false; if (float_flag == NOT_FLOAT) float_flag = AFTER_POINT; else - SYNTAX_ERROR ("too many decimal points in number"); + SYNTAX_ERROR_AT (virtual_location, + "too many decimal points in number"); } else if ((radix <= 10 && (c == 'e' || c == 'E')) || (radix == 16 && (c == 'p' || c == 'P'))) { + if (seen_digit_sep || DIGIT_SEP (*str)) + SYNTAX_ERROR_AT (virtual_location, + "digit separator adjacent to exponent"); float_flag = AFTER_EXPON; break; } @@ -295,10 +581,14 @@ } } + if (seen_digit_sep && float_flag != AFTER_EXPON) + SYNTAX_ERROR_AT (virtual_location, + "digit separator outside digit sequence"); + /* The suffix may be for decimal fixed-point constants without exponent. */ if (radix != 16 && float_flag == NOT_FLOAT) { - result = interpret_float_suffix (str, limit - str); + result = interpret_float_suffix (pfile, str, limit - str); if ((result & CPP_N_FRACT) || (result & CPP_N_ACCUM)) { result |= CPP_N_FLOATING; @@ -307,8 +597,8 @@ radix = 10; if (CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_PEDWARN, - "fixed-point constants are a GCC extension"); + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + "fixed-point constants are a GCC extension"); goto syntax_ok; } else @@ -321,26 +611,36 @@ if (max_digit >= radix) { if (radix == 2) - SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit); + SYNTAX_ERROR2_AT (virtual_location, + "invalid digit \"%c\" in binary constant", '0' + max_digit); else - SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit); + SYNTAX_ERROR2_AT (virtual_location, + "invalid digit \"%c\" in octal constant", '0' + max_digit); } if (float_flag != NOT_FLOAT) { if (radix == 2) { - cpp_error (pfile, CPP_DL_ERROR, - "invalid prefix \"0b\" for floating constant"); + cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0, + "invalid prefix \"0b\" for floating constant"); return CPP_N_INVALID; } if (radix == 16 && !seen_digit) - SYNTAX_ERROR ("no digits in hexadecimal floating constant"); + SYNTAX_ERROR_AT (virtual_location, + "no digits in hexadecimal floating constant"); - if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99)) - cpp_error (pfile, CPP_DL_PEDWARN, - "use of C99 hexadecimal floating constant"); + if (radix == 16 && CPP_PEDANTIC (pfile) + && !CPP_OPTION (pfile, extended_numbers)) + { + if (CPP_OPTION (pfile, cplusplus)) + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + "use of C++17 hexadecimal floating constant"); + else + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + "use of C99 hexadecimal floating constant"); + } if (float_flag == AFTER_EXPON) { @@ -349,67 +649,98 @@ /* Exponent is decimal, even if string is a hex float. */ if (!ISDIGIT (*str)) - SYNTAX_ERROR ("exponent has no digits"); - + { + if (DIGIT_SEP (*str)) + SYNTAX_ERROR_AT (virtual_location, + "digit separator adjacent to exponent"); + else + SYNTAX_ERROR_AT (virtual_location, "exponent has no digits"); + } do - str++; - while (ISDIGIT (*str)); + { + seen_digit_sep = DIGIT_SEP (*str); + str++; + } + while (ISDIGIT (*str) || DIGIT_SEP (*str)); } else if (radix == 16) - SYNTAX_ERROR ("hexadecimal floating constants require an exponent"); + SYNTAX_ERROR_AT (virtual_location, + "hexadecimal floating constants require an exponent"); - result = interpret_float_suffix (str, limit - str); + if (seen_digit_sep) + SYNTAX_ERROR_AT (virtual_location, + "digit separator outside digit sequence"); + + result = interpret_float_suffix (pfile, str, limit - str); if (result == 0) { - cpp_error (pfile, CPP_DL_ERROR, - "invalid suffix \"%.*s\" on floating constant", - (int) (limit - str), str); - return CPP_N_INVALID; + if (CPP_OPTION (pfile, user_literals)) + { + if (ud_suffix) + *ud_suffix = (const char *) str; + result = CPP_N_LARGE | CPP_N_USERDEF; + } + else + { + cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0, + "invalid suffix \"%.*s\" on floating constant", + (int) (limit - str), str); + return CPP_N_INVALID; + } } /* Traditional C didn't accept any floating suffixes. */ if (limit != str && CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile)) - cpp_warning (pfile, CPP_W_TRADITIONAL, - "traditional C rejects the \"%.*s\" suffix", - (int) (limit - str), str); + cpp_warning_with_line (pfile, CPP_W_TRADITIONAL, virtual_location, 0, + "traditional C rejects the \"%.*s\" suffix", + (int) (limit - str), str); /* A suffix for double is a GCC extension via decimal float support. If the suffix also specifies an imaginary value we'll catch that later. */ if ((result == CPP_N_MEDIUM) && CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_PEDWARN, - "suffix for double constant is a GCC extension"); + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + "suffix for double constant is a GCC extension"); /* Radix must be 10 for decimal floats. */ if ((result & CPP_N_DFLOAT) && radix != 10) { - cpp_error (pfile, CPP_DL_ERROR, - "invalid suffix \"%.*s\" with hexadecimal floating constant", - (int) (limit - str), str); + cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0, + "invalid suffix \"%.*s\" with hexadecimal floating constant", + (int) (limit - str), str); return CPP_N_INVALID; } if ((result & (CPP_N_FRACT | CPP_N_ACCUM)) && CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_PEDWARN, - "fixed-point constants are a GCC extension"); + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + "fixed-point constants are a GCC extension"); if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_PEDWARN, - "decimal float constants are a GCC extension"); + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + "decimal float constants are a GCC extension"); result |= CPP_N_FLOATING; } else { - result = interpret_int_suffix (str, limit - str); + result = interpret_int_suffix (pfile, str, limit - str); if (result == 0) { - cpp_error (pfile, CPP_DL_ERROR, - "invalid suffix \"%.*s\" on integer constant", - (int) (limit - str), str); - return CPP_N_INVALID; + if (CPP_OPTION (pfile, user_literals)) + { + if (ud_suffix) + *ud_suffix = (const char *) str; + result = CPP_N_UNSIGNED | CPP_N_LARGE | CPP_N_USERDEF; + } + else + { + cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0, + "invalid suffix \"%.*s\" on integer constant", + (int) (limit - str), str); + return CPP_N_INVALID; + } } /* Traditional C only accepted the 'L' suffix. @@ -421,22 +752,25 @@ && CPP_OPTION (pfile, cpp_warn_long_long); if (u_or_i || large) - cpp_warning (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL, - "traditional C rejects the \"%.*s\" suffix", - (int) (limit - str), str); + cpp_warning_with_line (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL, + virtual_location, 0, + "traditional C rejects the \"%.*s\" suffix", + (int) (limit - str), str); } if ((result & CPP_N_WIDTH) == CPP_N_LARGE && CPP_OPTION (pfile, cpp_warn_long_long)) { const char *message = CPP_OPTION (pfile, cplusplus) - ? N_("use of C++0x long long integer constant") + ? N_("use of C++11 long long integer constant") : N_("use of C99 long long integer constant"); if (CPP_OPTION (pfile, c99)) - cpp_warning (pfile, CPP_W_LONG_LONG, message); + cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location, + 0, message); else - cpp_pedwarning (pfile, CPP_W_LONG_LONG, message); + cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG, + virtual_location, 0, message); } result |= CPP_N_INTEGER; @@ -444,11 +778,16 @@ syntax_ok: if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_PEDWARN, - "imaginary constants are a GCC extension"); - if (radix == 2 && CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_PEDWARN, - "binary constants are a GCC extension"); + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + "imaginary constants are a GCC extension"); + if (radix == 2 + && !CPP_OPTION (pfile, binary_constants) + && CPP_PEDANTIC (pfile)) + cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, + CPP_OPTION (pfile, cplusplus) + ? N_("binary constants are a C++14 feature " + "or GCC extension") + : N_("binary constants are a GCC extension")); if (radix == 10) result |= CPP_N_DECIMAL; @@ -525,6 +864,8 @@ if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c))) c = hex_value (c); + else if (DIGIT_SEP (c)) + continue; else break; @@ -539,7 +880,7 @@ } } - if (overflow) + if (overflow && !(type & CPP_N_USERDEF)) cpp_error (pfile, CPP_DL_PEDWARN, "integer constant is too large for its type"); /* If too big to be signed, consider it unsigned. Only warn for @@ -690,9 +1031,11 @@ if (node) { - if (pfile->context != initial_context && CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_WARNING, - "this use of \"defined\" may not be portable"); + if ((pfile->context != initial_context + || initial_context != &pfile->base_context) + && CPP_OPTION (pfile, warn_expansion_to_defined)) + cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED, + "this use of \"defined\" may not be portable"); _cpp_mark_macro_used (node); if (!(node->flags & NODE_USED)) @@ -720,10 +1063,15 @@ pfile->state.prevent_expansion--; + /* Do not treat conditional macros as being defined. This is due to the + powerpc and spu ports using conditional macros for 'vector', 'bool', and + 'pixel' to act as conditional keywords. This messes up tests like #ifndef + bool. */ result.unsignedp = false; result.high = 0; result.overflow = false; - result.low = node && node->type == NT_MACRO; + result.low = (node && node->type == NT_MACRO + && (node->flags & NODE_CONDITIONAL) == 0); return result; } @@ -731,7 +1079,8 @@ number or character constant, or the result of the "defined" or "#" operators). */ static cpp_num -eval_token (cpp_reader *pfile, const cpp_token *token) +eval_token (cpp_reader *pfile, const cpp_token *token, + source_location virtual_location) { cpp_num result; unsigned int temp; @@ -743,18 +1092,21 @@ switch (token->type) { case CPP_NUMBER: - temp = cpp_classify_number (pfile, token); + temp = cpp_classify_number (pfile, token, NULL, virtual_location); + if (temp & CPP_N_USERDEF) + cpp_error (pfile, CPP_DL_ERROR, + "user-defined literal in preprocessor expression"); switch (temp & CPP_N_CATEGORY) { case CPP_N_FLOATING: - cpp_error (pfile, CPP_DL_ERROR, - "floating constant in preprocessor expression"); + cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0, + "floating constant in preprocessor expression"); break; case CPP_N_INTEGER: if (!(temp & CPP_N_IMAGINARY)) return cpp_interpret_integer (pfile, token, temp); - cpp_error (pfile, CPP_DL_ERROR, - "imaginary number in preprocessor expression"); + cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0, + "imaginary number in preprocessor expression"); break; case CPP_N_INVALID: @@ -768,6 +1120,7 @@ case CPP_CHAR: case CPP_CHAR16: case CPP_CHAR32: + case CPP_UTF8CHAR: { cppchar_t cc = cpp_interpret_charconst (pfile, token, &temp, &unsignedp); @@ -789,6 +1142,10 @@ case CPP_NAME: if (token->val.node.node == pfile->spec_nodes.n_defined) return parse_defined (pfile); + else if (token->val.node.node == pfile->spec_nodes.n__has_include__) + return parse_has_include (pfile, IT_INCLUDE); + else if (token->val.node.node == pfile->spec_nodes.n__has_include_next__) + return parse_has_include (pfile, IT_INCLUDE_NEXT); else if (CPP_OPTION (pfile, cplusplus) && (token->val.node.node == pfile->spec_nodes.n_true || token->val.node.node == pfile->spec_nodes.n_false)) @@ -801,8 +1158,9 @@ result.high = 0; result.low = 0; if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval) - cpp_warning (pfile, CPP_W_UNDEF, "\"%s\" is not defined", - NODE_NAME (token->val.node.node)); + cpp_warning_with_line (pfile, CPP_W_UNDEF, virtual_location, 0, + "\"%s\" is not defined, evaluates to 0", + NODE_NAME (token->val.node.node)); } break; @@ -812,11 +1170,12 @@ /* A pedantic warning takes precedence over a deprecated warning here. */ if (CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_PEDWARN, - "assertions are a GCC extension"); + cpp_error_with_line (pfile, CPP_DL_PEDWARN, + virtual_location, 0, + "assertions are a GCC extension"); else if (CPP_OPTION (pfile, cpp_warn_deprecated)) - cpp_warning (pfile, CPP_W_DEPRECATED, - "assertions are a deprecated extension"); + cpp_warning_with_line (pfile, CPP_W_DEPRECATED, virtual_location, 0, + "assertions are a deprecated extension"); } _cpp_test_assertion (pfile, &temp); result.high = 0; @@ -918,6 +1277,7 @@ struct op *top = pfile->op_stack; unsigned int lex_count; bool saw_leading_not, want_value = true; + source_location virtual_location = 0; pfile->state.skip_eval = 0; @@ -934,9 +1294,9 @@ struct op op; lex_count++; - op.token = cpp_get_token (pfile); + op.token = cpp_get_token_with_location (pfile, &virtual_location); op.op = op.token->type; - op.loc = op.token->src_loc; + op.loc = virtual_location; switch (op.op) { @@ -946,13 +1306,15 @@ case CPP_WCHAR: case CPP_CHAR16: case CPP_CHAR32: + case CPP_UTF8CHAR: case CPP_NAME: case CPP_HASH: if (!want_value) - SYNTAX_ERROR2 ("missing binary operator before token \"%s\"", - cpp_token_as_text (pfile, op.token)); + SYNTAX_ERROR2_AT (op.loc, + "missing binary operator before token \"%s\"", + cpp_token_as_text (pfile, op.token)); want_value = false; - top->value = eval_token (pfile, op.token); + top->value = eval_token (pfile, op.token, op.loc); continue; case CPP_NOT: @@ -969,8 +1331,9 @@ default: if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ) - SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions", - cpp_token_as_text (pfile, op.token)); + SYNTAX_ERROR2_AT (op.loc, + "token \"%s\" is not valid in preprocessor expressions", + cpp_token_as_text (pfile, op.token)); break; } @@ -978,27 +1341,32 @@ if (optab[op.op].flags & NO_L_OPERAND) { if (!want_value) - SYNTAX_ERROR2 ("missing binary operator before token \"%s\"", - cpp_token_as_text (pfile, op.token)); + SYNTAX_ERROR2_AT (op.loc, + "missing binary operator before token \"%s\"", + cpp_token_as_text (pfile, op.token)); } else if (want_value) { /* We want a number (or expression) and haven't got one. Try to emit a specific diagnostic. */ if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN) - SYNTAX_ERROR ("missing expression between '(' and ')'"); + SYNTAX_ERROR_AT (op.loc, + "missing expression between '(' and ')'"); if (op.op == CPP_EOF && top->op == CPP_EOF) - SYNTAX_ERROR2 ("%s with no expression", is_if ? "#if" : "#elif"); + SYNTAX_ERROR2_AT (op.loc, + "%s with no expression", is_if ? "#if" : "#elif"); if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN) - SYNTAX_ERROR2 ("operator '%s' has no right operand", - cpp_token_as_text (pfile, top->token)); + SYNTAX_ERROR2_AT (op.loc, + "operator '%s' has no right operand", + cpp_token_as_text (pfile, top->token)); else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF) /* Complain about missing paren during reduction. */; else - SYNTAX_ERROR2 ("operator '%s' has no left operand", - cpp_token_as_text (pfile, op.token)); + SYNTAX_ERROR2_AT (op.loc, + "operator '%s' has no left operand", + cpp_token_as_text (pfile, op.token)); } top = reduce (pfile, top, op.op); @@ -1023,7 +1391,8 @@ break; case CPP_COLON: if (top->op != CPP_QUERY) - SYNTAX_ERROR (" ':' without preceding '?'"); + SYNTAX_ERROR_AT (op.loc, + " ':' without preceding '?'"); if (!num_zerop (top[-1].value)) /* Was '?' condition true? */ pfile->state.skip_eval++; else @@ -1040,7 +1409,7 @@ top->op = op.op; top->token = op.token; - top->loc = op.token->src_loc; + top->loc = op.loc; } /* The controlling macro expression is only valid if we called lex 3 @@ -1051,8 +1420,9 @@ if (top != pfile->op_stack) { - cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in %s", - is_if ? "#if" : "#elif"); + cpp_error_with_line (pfile, CPP_DL_ICE, top->loc, 0, + "unbalanced stack in %s", + is_if ? "#if" : "#elif"); syntax_error: return false; /* Return false on syntax error. */ } @@ -1572,7 +1942,22 @@ /* Arithmetic. */ case CPP_MINUS: - rhs = num_negate (rhs, precision); + result.low = lhs.low - rhs.low; + result.high = lhs.high - rhs.high; + if (result.low > lhs.low) + result.high--; + result.unsignedp = lhs.unsignedp || rhs.unsignedp; + result.overflow = false; + + result = num_trim (result, precision); + if (!result.unsignedp) + { + bool lhsp = num_positive (lhs, precision); + result.overflow = (lhsp != num_positive (rhs, precision) + && lhsp != num_positive (result, precision)); + } + return result; + case CPP_PLUS: result.low = lhs.low + rhs.low; result.high = lhs.high + rhs.high; @@ -1594,8 +1979,8 @@ default: /* case CPP_COMMA: */ if (CPP_PEDANTIC (pfile) && (!CPP_OPTION (pfile, c99) || !pfile->state.skip_eval)) - cpp_error (pfile, CPP_DL_PEDWARN, - "comma operator in operand of #if"); + cpp_pedwarning (pfile, CPP_W_PEDANTIC, + "comma operator in operand of #if"); lhs = rhs; break; } @@ -1786,3 +2171,72 @@ return lhs; } + +/* Handle meeting "__has_include__" in a preprocessor expression. */ +static cpp_num +parse_has_include (cpp_reader *pfile, enum include_type type) +{ + cpp_num result; + bool paren = false; + cpp_hashnode *node = 0; + const cpp_token *token; + bool bracket = false; + char *fname = 0; + + result.unsignedp = false; + result.high = 0; + result.overflow = false; + result.low = 0; + + pfile->state.in__has_include__++; + + token = cpp_get_token (pfile); + if (token->type == CPP_OPEN_PAREN) + { + paren = true; + token = cpp_get_token (pfile); + } + + if (token->type == CPP_STRING || token->type == CPP_HEADER_NAME) + { + if (token->type == CPP_HEADER_NAME) + bracket = true; + fname = XNEWVEC (char, token->val.str.len - 1); + memcpy (fname, token->val.str.text + 1, token->val.str.len - 2); + fname[token->val.str.len - 2] = '\0'; + node = token->val.node.node; + } + else if (token->type == CPP_LESS) + { + bracket = true; + fname = _cpp_bracket_include (pfile); + } + else + cpp_error (pfile, CPP_DL_ERROR, + "operator \"__has_include__\" requires a header string"); + + if (fname) + { + int angle_brackets = (bracket ? 1 : 0); + + if (_cpp_has_header (pfile, fname, angle_brackets, type)) + result.low = 1; + else + result.low = 0; + + XDELETEVEC (fname); + } + + if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN) + cpp_error (pfile, CPP_DL_ERROR, + "missing ')' after \"__has_include__\""); + + /* A possible controlling macro of the form #if !__has_include__ (). + _cpp_parse_expr checks there was no other junk on the line. */ + if (node) + pfile->mi_ind_cmacro = node; + + pfile->state.in__has_include__--; + + return result; +}