|  | /* Parse C expressions for cpplib. | 
|  | Copyright (C) 1987-2020 Free Software Foundation, Inc. | 
|  | Contributed by Per Bothner, 1994. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify it | 
|  | under the terms of the GNU General Public License as published by the | 
|  | Free Software Foundation; either version 3, or (at your option) any | 
|  | later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program; see the file COPYING3.  If not see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include "system.h" | 
|  | #include "cpplib.h" | 
|  | #include "internal.h" | 
|  |  | 
|  | #define PART_PRECISION (sizeof (cpp_num_part) * CHAR_BIT) | 
|  | #define HALF_MASK (~(cpp_num_part) 0 >> (PART_PRECISION / 2)) | 
|  | #define LOW_PART(num_part) (num_part & HALF_MASK) | 
|  | #define HIGH_PART(num_part) (num_part >> (PART_PRECISION / 2)) | 
|  |  | 
|  | struct op | 
|  | { | 
|  | const cpp_token *token;	/* The token forming op (for diagnostics).  */ | 
|  | cpp_num value;		/* The value logically "right" of op.  */ | 
|  | location_t loc;          /* The location of this value.         */ | 
|  | enum cpp_ttype op; | 
|  | }; | 
|  |  | 
|  | /* Some simple utility routines on double integers.  */ | 
|  | #define num_zerop(num) ((num.low | num.high) == 0) | 
|  | #define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high) | 
|  | static bool num_positive (cpp_num, size_t); | 
|  | static bool num_greater_eq (cpp_num, cpp_num, size_t); | 
|  | static cpp_num num_trim (cpp_num, size_t); | 
|  | static cpp_num num_part_mul (cpp_num_part, cpp_num_part); | 
|  |  | 
|  | static cpp_num num_unary_op (cpp_reader *, cpp_num, enum cpp_ttype); | 
|  | static cpp_num num_binary_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype); | 
|  | static cpp_num num_negate (cpp_num, size_t); | 
|  | static cpp_num num_bitwise_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype); | 
|  | static cpp_num num_inequality_op (cpp_reader *, cpp_num, cpp_num, | 
|  | enum cpp_ttype); | 
|  | static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num, | 
|  | enum cpp_ttype); | 
|  | static cpp_num num_mul (cpp_reader *, cpp_num, cpp_num); | 
|  | static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype, | 
|  | location_t); | 
|  | static cpp_num num_lshift (cpp_num, size_t, size_t); | 
|  | static cpp_num num_rshift (cpp_num, size_t, size_t); | 
|  |  | 
|  | 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 *, location_t); | 
|  | static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype); | 
|  | 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 *); | 
|  |  | 
|  | /* 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)) | 
|  |  | 
|  | /* With -O2, gcc appears to produce nice code, moving the error | 
|  | message load and subsequent jump completely out of the main path.  */ | 
|  | #define SYNTAX_ERROR(msgid) \ | 
|  | do { cpp_error (pfile, CPP_DL_ERROR, msgid); goto syntax_error; } while(0) | 
|  | #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 (of CPP_N_* bits) describing the suffix.  */ | 
|  | static unsigned int | 
|  | interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len) | 
|  | { | 
|  | size_t orig_len = len; | 
|  | const uchar *orig_s = s; | 
|  | size_t flags; | 
|  | size_t f, d, l, w, q, i, fn, fnx, fn_bits; | 
|  |  | 
|  | flags = 0; | 
|  | f = d = l = w = q = i = fn = fnx = fn_bits = 0; | 
|  |  | 
|  | /* The following decimal float suffixes, from TR 24732:2009, TS | 
|  | 18661-2:2015 and C2X, 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.  */ | 
|  | if (len == 2 && (*s == 'd' || *s == 'D')) | 
|  | { | 
|  | bool uppercase = (*s == 'D'); | 
|  | switch (s[1]) | 
|  | { | 
|  | case 'f': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_SMALL): 0); break; | 
|  | case 'F': return (uppercase ? (CPP_N_DFLOAT | CPP_N_SMALL) : 0); break; | 
|  | case 'd': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_MEDIUM): 0); break; | 
|  | case 'D': return (uppercase ? (CPP_N_DFLOAT | CPP_N_MEDIUM) : 0); break; | 
|  | case 'l': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_LARGE) : 0); break; | 
|  | case 'L': return (uppercase ? (CPP_N_DFLOAT | CPP_N_LARGE) : 0); break; | 
|  | default: | 
|  | /* Additional two-character suffixes beginning with D are not | 
|  | for decimal float constants.  */ | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (CPP_OPTION (pfile, ext_numeric_literals)) | 
|  | { | 
|  | /* 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') | 
|  | { | 
|  | 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; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* In any remaining valid suffix, the case and order don't matter.  */ | 
|  | while (len--) | 
|  | { | 
|  | 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++; | 
|  | } | 
|  |  | 
|  | /* 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) | 
|  | { | 
|  | if (!CPP_OPTION (pfile, ext_numeric_literals)) | 
|  | return 0; | 
|  |  | 
|  | /* In C++14 and up these suffixes are in the standard library, so treat | 
|  | them as user-defined literals.  */ | 
|  | if (CPP_OPTION (pfile, cplusplus) | 
|  | && CPP_OPTION (pfile, lang) > CLK_CXX11 | 
|  | && orig_s[0] == 'i' | 
|  | && (orig_len == 1 | 
|  | || (orig_len == 2 | 
|  | && (orig_s[1] == 'f' || orig_s[1] == 'l')))) | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals)) | 
|  | return 0; | 
|  |  | 
|  | return ((i ? CPP_N_IMAGINARY : 0) | 
|  | | (f ? CPP_N_SMALL : | 
|  | d ? CPP_N_MEDIUM : | 
|  | l ? CPP_N_LARGE : | 
|  | w ? CPP_N_MD_W : | 
|  | 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 (cpp_reader *pfile, const uchar *s, size_t len) | 
|  | { | 
|  | size_t orig_len = len; | 
|  | size_t u, l, i; | 
|  |  | 
|  | u = l = i = 0; | 
|  |  | 
|  | while (len--) | 
|  | switch (s[len]) | 
|  | { | 
|  | case 'u': case 'U':	u++; break; | 
|  | case 'i': case 'I': | 
|  | case 'j': case 'J':	i++; break; | 
|  | case 'l': case 'L':	l++; | 
|  | /* If there are two Ls, they must be adjacent and the same case.  */ | 
|  | if (l == 2 && s[len] != s[len + 1]) | 
|  | return 0; | 
|  | break; | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (l > 2 || u > 1 || i > 1) | 
|  | return 0; | 
|  |  | 
|  | if (i) | 
|  | { | 
|  | if (!CPP_OPTION (pfile, ext_numeric_literals)) | 
|  | return 0; | 
|  |  | 
|  | /* In C++14 and up these suffixes are in the standard library, so treat | 
|  | them as user-defined literals.  */ | 
|  | if (CPP_OPTION (pfile, cplusplus) | 
|  | && CPP_OPTION (pfile, lang) > CLK_CXX11 | 
|  | && s[0] == 'i' | 
|  | && (orig_len == 1 || (orig_len == 2 && s[1] == 'l'))) | 
|  | 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. | 
|  |  | 
|  | 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, | 
|  | const char **ud_suffix, location_t 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.  */ | 
|  | if (token->val.str.len == 1) | 
|  | return CPP_N_INTEGER | CPP_N_SMALL | CPP_N_DECIMAL; | 
|  |  | 
|  | limit = str + token->val.str.len; | 
|  | float_flag = NOT_FLOAT; | 
|  | max_digit = 0; | 
|  | radix = 10; | 
|  | seen_digit = false; | 
|  | seen_digit_sep = false; | 
|  |  | 
|  | /* First, interpret the radix.  */ | 
|  | if (*str == '0') | 
|  | { | 
|  | radix = 8; | 
|  | str++; | 
|  |  | 
|  | /* Require at least one hex digit to classify it as hex.  */ | 
|  | if (*str == 'x' || *str == 'X') | 
|  | { | 
|  | 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') | 
|  | { | 
|  | 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"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Now scan for a well-formed integer or float.  */ | 
|  | for (;;) | 
|  | { | 
|  | unsigned int c = *str++; | 
|  |  | 
|  | 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_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; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Start of suffix.  */ | 
|  | str--; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | 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 (pfile, str, limit - str); | 
|  | if ((result & CPP_N_FRACT) || (result & CPP_N_ACCUM)) | 
|  | { | 
|  | result |= CPP_N_FLOATING; | 
|  | /* We need to restore the radix to 10, if the radix is 8.  */ | 
|  | if (radix == 8) | 
|  | radix = 10; | 
|  |  | 
|  | if (CPP_PEDANTIC (pfile)) | 
|  | cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, | 
|  | "fixed-point constants are a GCC extension"); | 
|  | goto syntax_ok; | 
|  | } | 
|  | else | 
|  | result = 0; | 
|  | } | 
|  |  | 
|  | if (float_flag != NOT_FLOAT && radix == 8) | 
|  | radix = 10; | 
|  |  | 
|  | if (max_digit >= radix) | 
|  | { | 
|  | if (radix == 2) | 
|  | SYNTAX_ERROR2_AT (virtual_location, | 
|  | "invalid digit \"%c\" in binary constant", '0' + max_digit); | 
|  | else | 
|  | SYNTAX_ERROR2_AT (virtual_location, | 
|  | "invalid digit \"%c\" in octal constant", '0' + max_digit); | 
|  | } | 
|  |  | 
|  | if (float_flag != NOT_FLOAT) | 
|  | { | 
|  | if (radix == 2) | 
|  | { | 
|  | 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_AT (virtual_location, | 
|  | "no digits in 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) | 
|  | { | 
|  | if (*str == '+' || *str == '-') | 
|  | str++; | 
|  |  | 
|  | /* Exponent is decimal, even if string is a hex float.  */ | 
|  | if (!ISDIGIT (*str)) | 
|  | { | 
|  | 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 | 
|  | { | 
|  | seen_digit_sep = DIGIT_SEP (*str); | 
|  | str++; | 
|  | } | 
|  | while (ISDIGIT (*str) || DIGIT_SEP (*str)); | 
|  | } | 
|  | else if (radix == 16) | 
|  | SYNTAX_ERROR_AT (virtual_location, | 
|  | "hexadecimal floating constants require an exponent"); | 
|  |  | 
|  | 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) | 
|  | { | 
|  | 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_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_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_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_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, | 
|  | "fixed-point constants are a GCC extension"); | 
|  |  | 
|  | if (result & CPP_N_DFLOAT) | 
|  | { | 
|  | if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, dfp_constants)) | 
|  | cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, | 
|  | "decimal float constants are a C2X feature"); | 
|  | else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0) | 
|  | cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT, | 
|  | virtual_location, 0, | 
|  | "decimal float constants are a C2X feature"); | 
|  | } | 
|  |  | 
|  | result |= CPP_N_FLOATING; | 
|  | } | 
|  | else | 
|  | { | 
|  | result = interpret_int_suffix (pfile, str, limit - str); | 
|  | if (result == 0) | 
|  | { | 
|  | 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. | 
|  | Suppress warning about 'LL' with -Wno-long-long.  */ | 
|  | if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile)) | 
|  | { | 
|  | int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY)); | 
|  | int large = (result & CPP_N_WIDTH) == CPP_N_LARGE | 
|  | && CPP_OPTION (pfile, cpp_warn_long_long); | 
|  |  | 
|  | if (u_or_i || large) | 
|  | 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++11 long long integer constant") | 
|  | : N_("use of C99 long long integer constant"); | 
|  |  | 
|  | if (CPP_OPTION (pfile, c99)) | 
|  | cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location, | 
|  | 0, message); | 
|  | else | 
|  | cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG, | 
|  | virtual_location, 0, message); | 
|  | } | 
|  |  | 
|  | result |= CPP_N_INTEGER; | 
|  | } | 
|  |  | 
|  | syntax_ok: | 
|  | if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile)) | 
|  | cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0, | 
|  | "imaginary constants are a GCC extension"); | 
|  | if (radix == 2) | 
|  | { | 
|  | if (!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 C2X feature " | 
|  | "or GCC extension")); | 
|  | else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0) | 
|  | cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT, | 
|  | virtual_location, 0, | 
|  | "binary constants are a C2X feature"); | 
|  | } | 
|  |  | 
|  | if (radix == 10) | 
|  | result |= CPP_N_DECIMAL; | 
|  | else if (radix == 16) | 
|  | result |= CPP_N_HEX; | 
|  | else if (radix == 2) | 
|  | result |= CPP_N_BINARY; | 
|  | else | 
|  | result |= CPP_N_OCTAL; | 
|  |  | 
|  | return result; | 
|  |  | 
|  | syntax_error: | 
|  | return CPP_N_INVALID; | 
|  | } | 
|  |  | 
|  | /* cpp_interpret_integer converts an integer constant into a cpp_num, | 
|  | of precision options->precision. | 
|  |  | 
|  | We do not provide any interface for decimal->float conversion, | 
|  | because the preprocessor doesn't need it and we don't want to | 
|  | drag in GCC's floating point emulator.  */ | 
|  | cpp_num | 
|  | cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token, | 
|  | unsigned int type) | 
|  | { | 
|  | const uchar *p, *end; | 
|  | cpp_num result; | 
|  |  | 
|  | result.low = 0; | 
|  | result.high = 0; | 
|  | result.unsignedp = !!(type & CPP_N_UNSIGNED); | 
|  | result.overflow = false; | 
|  |  | 
|  | p = token->val.str.text; | 
|  | end = p + token->val.str.len; | 
|  |  | 
|  | /* Common case of a single digit.  */ | 
|  | if (token->val.str.len == 1) | 
|  | result.low = p[0] - '0'; | 
|  | else | 
|  | { | 
|  | cpp_num_part max; | 
|  | size_t precision = CPP_OPTION (pfile, precision); | 
|  | unsigned int base = 10, c = 0; | 
|  | bool overflow = false; | 
|  |  | 
|  | if ((type & CPP_N_RADIX) == CPP_N_OCTAL) | 
|  | { | 
|  | base = 8; | 
|  | p++; | 
|  | } | 
|  | else if ((type & CPP_N_RADIX) == CPP_N_HEX) | 
|  | { | 
|  | base = 16; | 
|  | p += 2; | 
|  | } | 
|  | else if ((type & CPP_N_RADIX) == CPP_N_BINARY) | 
|  | { | 
|  | base = 2; | 
|  | p += 2; | 
|  | } | 
|  |  | 
|  | /* We can add a digit to numbers strictly less than this without | 
|  | needing the precision and slowness of double integers.  */ | 
|  | max = ~(cpp_num_part) 0; | 
|  | if (precision < PART_PRECISION) | 
|  | max >>= PART_PRECISION - precision; | 
|  | max = (max - base + 1) / base + 1; | 
|  |  | 
|  | for (; p < end; p++) | 
|  | { | 
|  | c = *p; | 
|  |  | 
|  | if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c))) | 
|  | c = hex_value (c); | 
|  | else if (DIGIT_SEP (c)) | 
|  | continue; | 
|  | else | 
|  | break; | 
|  |  | 
|  | /* Strict inequality for when max is set to zero.  */ | 
|  | if (result.low < max) | 
|  | result.low = result.low * base + c; | 
|  | else | 
|  | { | 
|  | result = append_digit (result, c, base, precision); | 
|  | overflow |= result.overflow; | 
|  | max = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | 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 | 
|  | decimal numbers.  Traditional numbers were always signed (but | 
|  | we still honor an explicit U suffix); but we only have | 
|  | traditional semantics in directives.  */ | 
|  | else if (!result.unsignedp | 
|  | && !(CPP_OPTION (pfile, traditional) | 
|  | && pfile->state.in_directive) | 
|  | && !num_positive (result, precision)) | 
|  | { | 
|  | /* This is for constants within the range of uintmax_t but | 
|  | not that of intmax_t.  For such decimal constants, a | 
|  | diagnostic is required for C99 as the selected type must | 
|  | be signed and not having a type is a constraint violation | 
|  | (DR#298, TC3), so this must be a pedwarn.  For C90, | 
|  | unsigned long is specified to be used for a constant that | 
|  | does not fit in signed long; if uintmax_t has the same | 
|  | range as unsigned long this means only a warning is | 
|  | appropriate here.  C90 permits the preprocessor to use a | 
|  | wider range than unsigned long in the compiler, so if | 
|  | uintmax_t is wider than unsigned long no diagnostic is | 
|  | required for such constants in preprocessor #if | 
|  | expressions and the compiler will pedwarn for such | 
|  | constants outside the range of unsigned long that reach | 
|  | the compiler so a diagnostic is not required there | 
|  | either; thus, pedwarn for C99 but use a plain warning for | 
|  | C90.  */ | 
|  | if (base == 10) | 
|  | cpp_error (pfile, (CPP_OPTION (pfile, c99) | 
|  | ? CPP_DL_PEDWARN | 
|  | : CPP_DL_WARNING), | 
|  | "integer constant is so large that it is unsigned"); | 
|  | result.unsignedp = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Append DIGIT to NUM, a number of PRECISION bits being read in base BASE.  */ | 
|  | static cpp_num | 
|  | append_digit (cpp_num num, int digit, int base, size_t precision) | 
|  | { | 
|  | cpp_num result; | 
|  | unsigned int shift; | 
|  | bool overflow; | 
|  | cpp_num_part add_high, add_low; | 
|  |  | 
|  | /* Multiply by 2, 8 or 16.  Catching this overflow here means we don't | 
|  | need to worry about add_high overflowing.  */ | 
|  | switch (base) | 
|  | { | 
|  | case 2: | 
|  | shift = 1; | 
|  | break; | 
|  |  | 
|  | case 16: | 
|  | shift = 4; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | shift = 3; | 
|  | } | 
|  | overflow = !!(num.high >> (PART_PRECISION - shift)); | 
|  | result.high = num.high << shift; | 
|  | result.low = num.low << shift; | 
|  | result.high |= num.low >> (PART_PRECISION - shift); | 
|  | result.unsignedp = num.unsignedp; | 
|  |  | 
|  | if (base == 10) | 
|  | { | 
|  | add_low = num.low << 1; | 
|  | add_high = (num.high << 1) + (num.low >> (PART_PRECISION - 1)); | 
|  | } | 
|  | else | 
|  | add_high = add_low = 0; | 
|  |  | 
|  | if (add_low + digit < add_low) | 
|  | add_high++; | 
|  | add_low += digit; | 
|  |  | 
|  | if (result.low + add_low < result.low) | 
|  | add_high++; | 
|  | if (result.high + add_high < result.high) | 
|  | overflow = true; | 
|  |  | 
|  | result.low += add_low; | 
|  | result.high += add_high; | 
|  | result.overflow = overflow; | 
|  |  | 
|  | /* The above code catches overflow of a cpp_num type.  This catches | 
|  | overflow of the (possibly shorter) target precision.  */ | 
|  | num.low = result.low; | 
|  | num.high = result.high; | 
|  | result = num_trim (result, precision); | 
|  | if (!num_eq (result, num)) | 
|  | result.overflow = true; | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Handle meeting "defined" in a preprocessor expression.  */ | 
|  | static cpp_num | 
|  | parse_defined (cpp_reader *pfile) | 
|  | { | 
|  | cpp_num result; | 
|  | int paren = 0; | 
|  | cpp_hashnode *node = 0; | 
|  | const cpp_token *token; | 
|  | cpp_context *initial_context = pfile->context; | 
|  |  | 
|  | /* Don't expand macros.  */ | 
|  | pfile->state.prevent_expansion++; | 
|  |  | 
|  | token = cpp_get_token (pfile); | 
|  | if (token->type == CPP_OPEN_PAREN) | 
|  | { | 
|  | paren = 1; | 
|  | token = cpp_get_token (pfile); | 
|  | } | 
|  |  | 
|  | if (token->type == CPP_NAME) | 
|  | { | 
|  | node = token->val.node.node; | 
|  | if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN) | 
|  | { | 
|  | cpp_error (pfile, CPP_DL_ERROR, "missing ')' after \"defined\""); | 
|  | node = 0; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | cpp_error (pfile, CPP_DL_ERROR, | 
|  | "operator \"defined\" requires an identifier"); | 
|  | if (token->flags & NAMED_OP) | 
|  | { | 
|  | cpp_token op; | 
|  |  | 
|  | op.flags = 0; | 
|  | op.type = token->type; | 
|  | cpp_error (pfile, CPP_DL_ERROR, | 
|  | "(\"%s\" is an alternative token for \"%s\" in C++)", | 
|  | cpp_token_as_text (pfile, token), | 
|  | cpp_token_as_text (pfile, &op)); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool is_defined = false; | 
|  | if (node) | 
|  | { | 
|  | 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"); | 
|  | is_defined = _cpp_defined_macro_p (node); | 
|  | if (!_cpp_maybe_notify_macro_use (pfile, node, token->src_loc)) | 
|  | /* It wasn't a macro after all.  */ | 
|  | is_defined = false; | 
|  | _cpp_mark_macro_used (node); | 
|  |  | 
|  | /* A possible controlling macro of the form #if !defined (). | 
|  | _cpp_parse_expr checks there was no other junk on the line.  */ | 
|  | pfile->mi_ind_cmacro = node; | 
|  | } | 
|  |  | 
|  | pfile->state.prevent_expansion--; | 
|  |  | 
|  | /* Do not treat conditional macros as being defined.  This is due to the | 
|  | powerpc port 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 = is_defined; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Convert a token into a CPP_NUMBER (an interpreted preprocessing | 
|  | number or character constant, or the result of the "defined" or "#" | 
|  | operators).  */ | 
|  | static cpp_num | 
|  | eval_token (cpp_reader *pfile, const cpp_token *token, | 
|  | location_t virtual_location) | 
|  | { | 
|  | cpp_num result; | 
|  | unsigned int temp; | 
|  | int unsignedp = 0; | 
|  |  | 
|  | result.unsignedp = false; | 
|  | result.overflow = false; | 
|  |  | 
|  | switch (token->type) | 
|  | { | 
|  | case CPP_NUMBER: | 
|  | 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_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_with_line (pfile, CPP_DL_ERROR, virtual_location, 0, | 
|  | "imaginary number in preprocessor expression"); | 
|  | break; | 
|  |  | 
|  | case CPP_N_INVALID: | 
|  | /* Error already issued.  */ | 
|  | break; | 
|  | } | 
|  | result.high = result.low = 0; | 
|  | break; | 
|  |  | 
|  | case CPP_WCHAR: | 
|  | case CPP_CHAR: | 
|  | case CPP_CHAR16: | 
|  | case CPP_CHAR32: | 
|  | case CPP_UTF8CHAR: | 
|  | { | 
|  | cppchar_t cc = cpp_interpret_charconst (pfile, token, | 
|  | &temp, &unsignedp); | 
|  |  | 
|  | result.high = 0; | 
|  | result.low = cc; | 
|  | /* Sign-extend the result if necessary.  */ | 
|  | if (!unsignedp && (cppchar_signed_t) cc < 0) | 
|  | { | 
|  | if (PART_PRECISION > BITS_PER_CPPCHAR_T) | 
|  | result.low |= ~(~(cpp_num_part) 0 | 
|  | >> (PART_PRECISION - BITS_PER_CPPCHAR_T)); | 
|  | result.high = ~(cpp_num_part) 0; | 
|  | result = num_trim (result, CPP_OPTION (pfile, precision)); | 
|  | } | 
|  | } | 
|  | break; | 
|  |  | 
|  | case CPP_NAME: | 
|  | if (token->val.node.node == pfile->spec_nodes.n_defined) | 
|  | return parse_defined (pfile); | 
|  | else if (CPP_OPTION (pfile, cplusplus) | 
|  | && (token->val.node.node == pfile->spec_nodes.n_true | 
|  | || token->val.node.node == pfile->spec_nodes.n_false)) | 
|  | { | 
|  | result.high = 0; | 
|  | result.low = (token->val.node.node == pfile->spec_nodes.n_true); | 
|  | } | 
|  | else | 
|  | { | 
|  | result.high = 0; | 
|  | result.low = 0; | 
|  | if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval) | 
|  | 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; | 
|  |  | 
|  | case CPP_HASH: | 
|  | if (!pfile->state.skipping) | 
|  | { | 
|  | /* A pedantic warning takes precedence over a deprecated | 
|  | warning here.  */ | 
|  | if (CPP_PEDANTIC (pfile)) | 
|  | 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_with_line (pfile, CPP_W_DEPRECATED, virtual_location, 0, | 
|  | "assertions are a deprecated extension"); | 
|  | } | 
|  | _cpp_test_assertion (pfile, &temp); | 
|  | result.high = 0; | 
|  | result.low = temp; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | abort (); | 
|  | } | 
|  |  | 
|  | result.unsignedp = !!unsignedp; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Operator precedence and flags table. | 
|  |  | 
|  | After an operator is returned from the lexer, if it has priority less | 
|  | than the operator on the top of the stack, we reduce the stack by one | 
|  | operator and repeat the test.  Since equal priorities do not reduce, | 
|  | this is naturally right-associative. | 
|  |  | 
|  | We handle left-associative operators by decrementing the priority of | 
|  | just-lexed operators by one, but retaining the priority of operators | 
|  | already on the stack. | 
|  |  | 
|  | The remaining cases are '(' and ')'.  We handle '(' by skipping the | 
|  | reduction phase completely.  ')' is given lower priority than | 
|  | everything else, including '(', effectively forcing a reduction of the | 
|  | parenthesized expression.  If there is a matching '(', the routine | 
|  | reduce() exits immediately.  If the normal exit route sees a ')', then | 
|  | there cannot have been a matching '(' and an error message is output. | 
|  |  | 
|  | The parser assumes all shifted operators require a left operand unless | 
|  | the flag NO_L_OPERAND is set.  These semantics are automatic; any | 
|  | extra semantics need to be handled with operator-specific code.  */ | 
|  |  | 
|  | /* Flags.  If CHECK_PROMOTION, we warn if the effective sign of an | 
|  | operand changes because of integer promotions.  */ | 
|  | #define NO_L_OPERAND	(1 << 0) | 
|  | #define LEFT_ASSOC	(1 << 1) | 
|  | #define CHECK_PROMOTION	(1 << 2) | 
|  |  | 
|  | /* Operator to priority map.  Must be in the same order as the first | 
|  | N entries of enum cpp_ttype.  */ | 
|  | static const struct cpp_operator | 
|  | { | 
|  | uchar prio; | 
|  | uchar flags; | 
|  | } optab[] = | 
|  | { | 
|  | /* EQ */		{0, 0},	/* Shouldn't happen.  */ | 
|  | /* NOT */		{16, NO_L_OPERAND}, | 
|  | /* GREATER */		{12, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* LESS */		{12, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* PLUS */		{14, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* MINUS */		{14, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* MULT */		{15, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* DIV */		{15, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* MOD */		{15, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* AND */		{9, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* OR */		{7, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* XOR */		{8, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* RSHIFT */		{13, LEFT_ASSOC}, | 
|  | /* LSHIFT */		{13, LEFT_ASSOC}, | 
|  |  | 
|  | /* COMPL */		{16, NO_L_OPERAND}, | 
|  | /* AND_AND */		{6, LEFT_ASSOC}, | 
|  | /* OR_OR */		{5, LEFT_ASSOC}, | 
|  | /* Note that QUERY, COLON, and COMMA must have the same precedence. | 
|  | However, there are some special cases for these in reduce().  */ | 
|  | /* QUERY */		{4, 0}, | 
|  | /* COLON */		{4, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* COMMA */		{4, LEFT_ASSOC}, | 
|  | /* OPEN_PAREN */	{1, NO_L_OPERAND}, | 
|  | /* CLOSE_PAREN */	{0, 0}, | 
|  | /* EOF */		{0, 0}, | 
|  | /* EQ_EQ */		{11, LEFT_ASSOC}, | 
|  | /* NOT_EQ */		{11, LEFT_ASSOC}, | 
|  | /* GREATER_EQ */	{12, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* LESS_EQ */		{12, LEFT_ASSOC | CHECK_PROMOTION}, | 
|  | /* UPLUS */		{16, NO_L_OPERAND}, | 
|  | /* UMINUS */		{16, NO_L_OPERAND} | 
|  | }; | 
|  |  | 
|  | /* Parse and evaluate a C expression, reading from PFILE. | 
|  | Returns the truth value of the expression. | 
|  |  | 
|  | The implementation is an operator precedence parser, i.e. a | 
|  | bottom-up parser, using a stack for not-yet-reduced tokens. | 
|  |  | 
|  | The stack base is op_stack, and the current stack pointer is 'top'. | 
|  | There is a stack element for each operator (only), and the most | 
|  | recently pushed operator is 'top->op'.  An operand (value) is | 
|  | stored in the 'value' field of the stack element of the operator | 
|  | that precedes it.  */ | 
|  | bool | 
|  | _cpp_parse_expr (cpp_reader *pfile, bool is_if) | 
|  | { | 
|  | struct op *top = pfile->op_stack; | 
|  | unsigned int lex_count; | 
|  | bool saw_leading_not, want_value = true; | 
|  | location_t virtual_location = 0; | 
|  |  | 
|  | pfile->state.skip_eval = 0; | 
|  |  | 
|  | /* Set up detection of #if ! defined().  */ | 
|  | pfile->mi_ind_cmacro = 0; | 
|  | saw_leading_not = false; | 
|  | lex_count = 0; | 
|  |  | 
|  | /* Lowest priority operator prevents further reductions.  */ | 
|  | top->op = CPP_EOF; | 
|  |  | 
|  | for (;;) | 
|  | { | 
|  | struct op op; | 
|  |  | 
|  | lex_count++; | 
|  | op.token = cpp_get_token_with_location (pfile, &virtual_location); | 
|  | op.op = op.token->type; | 
|  | op.loc = virtual_location; | 
|  |  | 
|  | switch (op.op) | 
|  | { | 
|  | /* These tokens convert into values.  */ | 
|  | case CPP_NUMBER: | 
|  | case CPP_CHAR: | 
|  | case CPP_WCHAR: | 
|  | case CPP_CHAR16: | 
|  | case CPP_CHAR32: | 
|  | case CPP_UTF8CHAR: | 
|  | case CPP_NAME: | 
|  | case CPP_HASH: | 
|  | if (!want_value) | 
|  | 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, op.loc); | 
|  | continue; | 
|  |  | 
|  | case CPP_NOT: | 
|  | saw_leading_not = lex_count == 1; | 
|  | break; | 
|  | case CPP_PLUS: | 
|  | if (want_value) | 
|  | op.op = CPP_UPLUS; | 
|  | break; | 
|  | case CPP_MINUS: | 
|  | if (want_value) | 
|  | op.op = CPP_UMINUS; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ) | 
|  | SYNTAX_ERROR2_AT (op.loc, | 
|  | "token \"%s\" is not valid in preprocessor expressions", | 
|  | cpp_token_as_text (pfile, op.token)); | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* Check we have a value or operator as appropriate.  */ | 
|  | if (optab[op.op].flags & NO_L_OPERAND) | 
|  | { | 
|  | if (!want_value) | 
|  | 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_AT (op.loc, | 
|  | "missing expression between '(' and ')'"); | 
|  |  | 
|  | if (op.op == CPP_EOF && top->op == CPP_EOF) | 
|  | 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_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_AT (op.loc, | 
|  | "operator '%s' has no left operand", | 
|  | cpp_token_as_text (pfile, op.token)); | 
|  | } | 
|  |  | 
|  | top = reduce (pfile, top, op.op); | 
|  | if (!top) | 
|  | goto syntax_error; | 
|  |  | 
|  | if (op.op == CPP_EOF) | 
|  | break; | 
|  |  | 
|  | switch (op.op) | 
|  | { | 
|  | case CPP_CLOSE_PAREN: | 
|  | continue; | 
|  | case CPP_OR_OR: | 
|  | if (!num_zerop (top->value)) | 
|  | pfile->state.skip_eval++; | 
|  | break; | 
|  | case CPP_AND_AND: | 
|  | case CPP_QUERY: | 
|  | if (num_zerop (top->value)) | 
|  | pfile->state.skip_eval++; | 
|  | break; | 
|  | case CPP_COLON: | 
|  | if (top->op != CPP_QUERY) | 
|  | SYNTAX_ERROR_AT (op.loc, | 
|  | " ':' without preceding '?'"); | 
|  | if (!num_zerop (top[-1].value)) /* Was '?' condition true?  */ | 
|  | pfile->state.skip_eval++; | 
|  | else | 
|  | pfile->state.skip_eval--; | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | want_value = true; | 
|  |  | 
|  | /* Check for and handle stack overflow.  */ | 
|  | if (++top == pfile->op_limit) | 
|  | top = _cpp_expand_op_stack (pfile); | 
|  |  | 
|  | top->op = op.op; | 
|  | top->token = op.token; | 
|  | top->loc = op.loc; | 
|  | } | 
|  |  | 
|  | /* The controlling macro expression is only valid if we called lex 3 | 
|  | times: <!> <defined expression> and <EOF>.  push_conditional () | 
|  | checks that we are at top-of-file.  */ | 
|  | if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3)) | 
|  | pfile->mi_ind_cmacro = 0; | 
|  |  | 
|  | if (top != pfile->op_stack) | 
|  | { | 
|  | 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.  */ | 
|  | } | 
|  |  | 
|  | return !num_zerop (top->value); | 
|  | } | 
|  |  | 
|  | /* Reduce the operator / value stack if possible, in preparation for | 
|  | pushing operator OP.  Returns NULL on error, otherwise the top of | 
|  | the stack.  */ | 
|  | static struct op * | 
|  | reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op) | 
|  | { | 
|  | unsigned int prio; | 
|  |  | 
|  | if (top->op <= CPP_EQ || top->op > CPP_LAST_CPP_OP + 2) | 
|  | { | 
|  | bad_op: | 
|  | cpp_error (pfile, CPP_DL_ICE, "impossible operator '%u'", top->op); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (op == CPP_OPEN_PAREN) | 
|  | return top; | 
|  |  | 
|  | /* Decrement the priority of left-associative operators to force a | 
|  | reduction with operators of otherwise equal priority.  */ | 
|  | prio = optab[op].prio - ((optab[op].flags & LEFT_ASSOC) != 0); | 
|  | while (prio < optab[top->op].prio) | 
|  | { | 
|  | if (CPP_OPTION (pfile, warn_num_sign_change) | 
|  | && optab[top->op].flags & CHECK_PROMOTION) | 
|  | check_promotion (pfile, top); | 
|  |  | 
|  | switch (top->op) | 
|  | { | 
|  | case CPP_UPLUS: | 
|  | case CPP_UMINUS: | 
|  | case CPP_NOT: | 
|  | case CPP_COMPL: | 
|  | top[-1].value = num_unary_op (pfile, top->value, top->op); | 
|  | top[-1].loc = top->loc; | 
|  | break; | 
|  |  | 
|  | case CPP_PLUS: | 
|  | case CPP_MINUS: | 
|  | case CPP_RSHIFT: | 
|  | case CPP_LSHIFT: | 
|  | case CPP_COMMA: | 
|  | top[-1].value = num_binary_op (pfile, top[-1].value, | 
|  | top->value, top->op); | 
|  | top[-1].loc = top->loc; | 
|  | break; | 
|  |  | 
|  | case CPP_GREATER: | 
|  | case CPP_LESS: | 
|  | case CPP_GREATER_EQ: | 
|  | case CPP_LESS_EQ: | 
|  | top[-1].value | 
|  | = num_inequality_op (pfile, top[-1].value, top->value, top->op); | 
|  | top[-1].loc = top->loc; | 
|  | break; | 
|  |  | 
|  | case CPP_EQ_EQ: | 
|  | case CPP_NOT_EQ: | 
|  | top[-1].value | 
|  | = num_equality_op (pfile, top[-1].value, top->value, top->op); | 
|  | top[-1].loc = top->loc; | 
|  | break; | 
|  |  | 
|  | case CPP_AND: | 
|  | case CPP_OR: | 
|  | case CPP_XOR: | 
|  | top[-1].value | 
|  | = num_bitwise_op (pfile, top[-1].value, top->value, top->op); | 
|  | top[-1].loc = top->loc; | 
|  | break; | 
|  |  | 
|  | case CPP_MULT: | 
|  | top[-1].value = num_mul (pfile, top[-1].value, top->value); | 
|  | top[-1].loc = top->loc; | 
|  | break; | 
|  |  | 
|  | case CPP_DIV: | 
|  | case CPP_MOD: | 
|  | top[-1].value = num_div_op (pfile, top[-1].value, | 
|  | top->value, top->op, top->loc); | 
|  | top[-1].loc = top->loc; | 
|  | break; | 
|  |  | 
|  | case CPP_OR_OR: | 
|  | top--; | 
|  | if (!num_zerop (top->value)) | 
|  | pfile->state.skip_eval--; | 
|  | top->value.low = (!num_zerop (top->value) | 
|  | || !num_zerop (top[1].value)); | 
|  | top->value.high = 0; | 
|  | top->value.unsignedp = false; | 
|  | top->value.overflow = false; | 
|  | top->loc = top[1].loc; | 
|  | continue; | 
|  |  | 
|  | case CPP_AND_AND: | 
|  | top--; | 
|  | if (num_zerop (top->value)) | 
|  | pfile->state.skip_eval--; | 
|  | top->value.low = (!num_zerop (top->value) | 
|  | && !num_zerop (top[1].value)); | 
|  | top->value.high = 0; | 
|  | top->value.unsignedp = false; | 
|  | top->value.overflow = false; | 
|  | top->loc = top[1].loc; | 
|  | continue; | 
|  |  | 
|  | case CPP_OPEN_PAREN: | 
|  | if (op != CPP_CLOSE_PAREN) | 
|  | { | 
|  | cpp_error_with_line (pfile, CPP_DL_ERROR, | 
|  | top->token->src_loc, | 
|  | 0, "missing ')' in expression"); | 
|  | return 0; | 
|  | } | 
|  | top--; | 
|  | top->value = top[1].value; | 
|  | top->loc = top[1].loc; | 
|  | return top; | 
|  |  | 
|  | case CPP_COLON: | 
|  | top -= 2; | 
|  | if (!num_zerop (top->value)) | 
|  | { | 
|  | pfile->state.skip_eval--; | 
|  | top->value = top[1].value; | 
|  | top->loc = top[1].loc; | 
|  | } | 
|  | else | 
|  | { | 
|  | top->value = top[2].value; | 
|  | top->loc = top[2].loc; | 
|  | } | 
|  | top->value.unsignedp = (top[1].value.unsignedp | 
|  | || top[2].value.unsignedp); | 
|  | continue; | 
|  |  | 
|  | case CPP_QUERY: | 
|  | /* COMMA and COLON should not reduce a QUERY operator.  */ | 
|  | if (op == CPP_COMMA || op == CPP_COLON) | 
|  | return top; | 
|  | cpp_error (pfile, CPP_DL_ERROR, "'?' without following ':'"); | 
|  | return 0; | 
|  |  | 
|  | default: | 
|  | goto bad_op; | 
|  | } | 
|  |  | 
|  | top--; | 
|  | if (top->value.overflow && !pfile->state.skip_eval) | 
|  | cpp_error (pfile, CPP_DL_PEDWARN, | 
|  | "integer overflow in preprocessor expression"); | 
|  | } | 
|  |  | 
|  | if (op == CPP_CLOSE_PAREN) | 
|  | { | 
|  | cpp_error (pfile, CPP_DL_ERROR, "missing '(' in expression"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | return top; | 
|  | } | 
|  |  | 
|  | /* Returns the position of the old top of stack after expansion.  */ | 
|  | struct op * | 
|  | _cpp_expand_op_stack (cpp_reader *pfile) | 
|  | { | 
|  | size_t old_size = (size_t) (pfile->op_limit - pfile->op_stack); | 
|  | size_t new_size = old_size * 2 + 20; | 
|  |  | 
|  | pfile->op_stack = XRESIZEVEC (struct op, pfile->op_stack, new_size); | 
|  | pfile->op_limit = pfile->op_stack + new_size; | 
|  |  | 
|  | return pfile->op_stack + old_size; | 
|  | } | 
|  |  | 
|  | /* Emits a warning if the effective sign of either operand of OP | 
|  | changes because of integer promotions.  */ | 
|  | static void | 
|  | check_promotion (cpp_reader *pfile, const struct op *op) | 
|  | { | 
|  | if (op->value.unsignedp == op[-1].value.unsignedp) | 
|  | return; | 
|  |  | 
|  | if (op->value.unsignedp) | 
|  | { | 
|  | if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision))) | 
|  | cpp_error_with_line (pfile, CPP_DL_WARNING, op[-1].loc, 0, | 
|  | "the left operand of \"%s\" changes sign when promoted", | 
|  | cpp_token_as_text (pfile, op->token)); | 
|  | } | 
|  | else if (!num_positive (op->value, CPP_OPTION (pfile, precision))) | 
|  | cpp_error_with_line (pfile, CPP_DL_WARNING, op->loc, 0, | 
|  | "the right operand of \"%s\" changes sign when promoted", | 
|  | cpp_token_as_text (pfile, op->token)); | 
|  | } | 
|  |  | 
|  | /* Clears the unused high order bits of the number pointed to by PNUM.  */ | 
|  | static cpp_num | 
|  | num_trim (cpp_num num, size_t precision) | 
|  | { | 
|  | if (precision > PART_PRECISION) | 
|  | { | 
|  | precision -= PART_PRECISION; | 
|  | if (precision < PART_PRECISION) | 
|  | num.high &= ((cpp_num_part) 1 << precision) - 1; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (precision < PART_PRECISION) | 
|  | num.low &= ((cpp_num_part) 1 << precision) - 1; | 
|  | num.high = 0; | 
|  | } | 
|  |  | 
|  | return num; | 
|  | } | 
|  |  | 
|  | /* True iff A (presumed signed) >= 0.  */ | 
|  | static bool | 
|  | num_positive (cpp_num num, size_t precision) | 
|  | { | 
|  | if (precision > PART_PRECISION) | 
|  | { | 
|  | precision -= PART_PRECISION; | 
|  | return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0; | 
|  | } | 
|  |  | 
|  | return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0; | 
|  | } | 
|  |  | 
|  | /* Sign extend a number, with PRECISION significant bits and all | 
|  | others assumed clear, to fill out a cpp_num structure.  */ | 
|  | cpp_num | 
|  | cpp_num_sign_extend (cpp_num num, size_t precision) | 
|  | { | 
|  | if (!num.unsignedp) | 
|  | { | 
|  | if (precision > PART_PRECISION) | 
|  | { | 
|  | precision -= PART_PRECISION; | 
|  | if (precision < PART_PRECISION | 
|  | && (num.high & (cpp_num_part) 1 << (precision - 1))) | 
|  | num.high |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision)); | 
|  | } | 
|  | else if (num.low & (cpp_num_part) 1 << (precision - 1)) | 
|  | { | 
|  | if (precision < PART_PRECISION) | 
|  | num.low |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision)); | 
|  | num.high = ~(cpp_num_part) 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | return num; | 
|  | } | 
|  |  | 
|  | /* Returns the negative of NUM.  */ | 
|  | static cpp_num | 
|  | num_negate (cpp_num num, size_t precision) | 
|  | { | 
|  | cpp_num copy; | 
|  |  | 
|  | copy = num; | 
|  | num.high = ~num.high; | 
|  | num.low = ~num.low; | 
|  | if (++num.low == 0) | 
|  | num.high++; | 
|  | num = num_trim (num, precision); | 
|  | num.overflow = (!num.unsignedp && num_eq (num, copy) && !num_zerop (num)); | 
|  |  | 
|  | return num; | 
|  | } | 
|  |  | 
|  | /* Returns true if A >= B.  */ | 
|  | static bool | 
|  | num_greater_eq (cpp_num pa, cpp_num pb, size_t precision) | 
|  | { | 
|  | bool unsignedp; | 
|  |  | 
|  | unsignedp = pa.unsignedp || pb.unsignedp; | 
|  |  | 
|  | if (!unsignedp) | 
|  | { | 
|  | /* Both numbers have signed type.  If they are of different | 
|  | sign, the answer is the sign of A.  */ | 
|  | unsignedp = num_positive (pa, precision); | 
|  |  | 
|  | if (unsignedp != num_positive (pb, precision)) | 
|  | return unsignedp; | 
|  |  | 
|  | /* Otherwise we can do an unsigned comparison.  */ | 
|  | } | 
|  |  | 
|  | return (pa.high > pb.high) || (pa.high == pb.high && pa.low >= pb.low); | 
|  | } | 
|  |  | 
|  | /* Returns LHS OP RHS, where OP is a bit-wise operation.  */ | 
|  | static cpp_num | 
|  | num_bitwise_op (cpp_reader *pfile ATTRIBUTE_UNUSED, | 
|  | cpp_num lhs, cpp_num rhs, enum cpp_ttype op) | 
|  | { | 
|  | lhs.overflow = false; | 
|  | lhs.unsignedp = lhs.unsignedp || rhs.unsignedp; | 
|  |  | 
|  | /* As excess precision is zeroed, there is no need to num_trim () as | 
|  | these operations cannot introduce a set bit there.  */ | 
|  | if (op == CPP_AND) | 
|  | { | 
|  | lhs.low &= rhs.low; | 
|  | lhs.high &= rhs.high; | 
|  | } | 
|  | else if (op == CPP_OR) | 
|  | { | 
|  | lhs.low |= rhs.low; | 
|  | lhs.high |= rhs.high; | 
|  | } | 
|  | else | 
|  | { | 
|  | lhs.low ^= rhs.low; | 
|  | lhs.high ^= rhs.high; | 
|  | } | 
|  |  | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* Returns LHS OP RHS, where OP is an inequality.  */ | 
|  | static cpp_num | 
|  | num_inequality_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, | 
|  | enum cpp_ttype op) | 
|  | { | 
|  | bool gte = num_greater_eq (lhs, rhs, CPP_OPTION (pfile, precision)); | 
|  |  | 
|  | if (op == CPP_GREATER_EQ) | 
|  | lhs.low = gte; | 
|  | else if (op == CPP_LESS) | 
|  | lhs.low = !gte; | 
|  | else if (op == CPP_GREATER) | 
|  | lhs.low = gte && !num_eq (lhs, rhs); | 
|  | else /* CPP_LESS_EQ.  */ | 
|  | lhs.low = !gte || num_eq (lhs, rhs); | 
|  |  | 
|  | lhs.high = 0; | 
|  | lhs.overflow = false; | 
|  | lhs.unsignedp = false; | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* Returns LHS OP RHS, where OP is == or !=.  */ | 
|  | static cpp_num | 
|  | num_equality_op (cpp_reader *pfile ATTRIBUTE_UNUSED, | 
|  | cpp_num lhs, cpp_num rhs, enum cpp_ttype op) | 
|  | { | 
|  | /* Work around a 3.0.4 bug; see PR 6950.  */ | 
|  | bool eq = num_eq (lhs, rhs); | 
|  | if (op == CPP_NOT_EQ) | 
|  | eq = !eq; | 
|  | lhs.low = eq; | 
|  | lhs.high = 0; | 
|  | lhs.overflow = false; | 
|  | lhs.unsignedp = false; | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* Shift NUM, of width PRECISION, right by N bits.  */ | 
|  | static cpp_num | 
|  | num_rshift (cpp_num num, size_t precision, size_t n) | 
|  | { | 
|  | cpp_num_part sign_mask; | 
|  | bool x = num_positive (num, precision); | 
|  |  | 
|  | if (num.unsignedp || x) | 
|  | sign_mask = 0; | 
|  | else | 
|  | sign_mask = ~(cpp_num_part) 0; | 
|  |  | 
|  | if (n >= precision) | 
|  | num.high = num.low = sign_mask; | 
|  | else | 
|  | { | 
|  | /* Sign-extend.  */ | 
|  | if (precision < PART_PRECISION) | 
|  | num.high = sign_mask, num.low |= sign_mask << precision; | 
|  | else if (precision < 2 * PART_PRECISION) | 
|  | num.high |= sign_mask << (precision - PART_PRECISION); | 
|  |  | 
|  | if (n >= PART_PRECISION) | 
|  | { | 
|  | n -= PART_PRECISION; | 
|  | num.low = num.high; | 
|  | num.high = sign_mask; | 
|  | } | 
|  |  | 
|  | if (n) | 
|  | { | 
|  | num.low = (num.low >> n) | (num.high << (PART_PRECISION - n)); | 
|  | num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n)); | 
|  | } | 
|  | } | 
|  |  | 
|  | num = num_trim (num, precision); | 
|  | num.overflow = false; | 
|  | return num; | 
|  | } | 
|  |  | 
|  | /* Shift NUM, of width PRECISION, left by N bits.  */ | 
|  | static cpp_num | 
|  | num_lshift (cpp_num num, size_t precision, size_t n) | 
|  | { | 
|  | if (n >= precision) | 
|  | { | 
|  | num.overflow = !num.unsignedp && !num_zerop (num); | 
|  | num.high = num.low = 0; | 
|  | } | 
|  | else | 
|  | { | 
|  | cpp_num orig, maybe_orig; | 
|  | size_t m = n; | 
|  |  | 
|  | orig = num; | 
|  | if (m >= PART_PRECISION) | 
|  | { | 
|  | m -= PART_PRECISION; | 
|  | num.high = num.low; | 
|  | num.low = 0; | 
|  | } | 
|  | if (m) | 
|  | { | 
|  | num.high = (num.high << m) | (num.low >> (PART_PRECISION - m)); | 
|  | num.low <<= m; | 
|  | } | 
|  | num = num_trim (num, precision); | 
|  |  | 
|  | if (num.unsignedp) | 
|  | num.overflow = false; | 
|  | else | 
|  | { | 
|  | maybe_orig = num_rshift (num, precision, n); | 
|  | num.overflow = !num_eq (orig, maybe_orig); | 
|  | } | 
|  | } | 
|  |  | 
|  | return num; | 
|  | } | 
|  |  | 
|  | /* The four unary operators: +, -, ! and ~.  */ | 
|  | static cpp_num | 
|  | num_unary_op (cpp_reader *pfile, cpp_num num, enum cpp_ttype op) | 
|  | { | 
|  | switch (op) | 
|  | { | 
|  | case CPP_UPLUS: | 
|  | if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval) | 
|  | cpp_warning (pfile, CPP_W_TRADITIONAL, | 
|  | "traditional C rejects the unary plus operator"); | 
|  | num.overflow = false; | 
|  | break; | 
|  |  | 
|  | case CPP_UMINUS: | 
|  | num = num_negate (num, CPP_OPTION (pfile, precision)); | 
|  | break; | 
|  |  | 
|  | case CPP_COMPL: | 
|  | num.high = ~num.high; | 
|  | num.low = ~num.low; | 
|  | num = num_trim (num, CPP_OPTION (pfile, precision)); | 
|  | num.overflow = false; | 
|  | break; | 
|  |  | 
|  | default: /* case CPP_NOT: */ | 
|  | num.low = num_zerop (num); | 
|  | num.high = 0; | 
|  | num.overflow = false; | 
|  | num.unsignedp = false; | 
|  | break; | 
|  | } | 
|  |  | 
|  | return num; | 
|  | } | 
|  |  | 
|  | /* The various binary operators.  */ | 
|  | static cpp_num | 
|  | num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op) | 
|  | { | 
|  | cpp_num result; | 
|  | size_t precision = CPP_OPTION (pfile, precision); | 
|  | size_t n; | 
|  |  | 
|  | switch (op) | 
|  | { | 
|  | /* Shifts.  */ | 
|  | case CPP_LSHIFT: | 
|  | case CPP_RSHIFT: | 
|  | if (!rhs.unsignedp && !num_positive (rhs, precision)) | 
|  | { | 
|  | /* A negative shift is a positive shift the other way.  */ | 
|  | if (op == CPP_LSHIFT) | 
|  | op = CPP_RSHIFT; | 
|  | else | 
|  | op = CPP_LSHIFT; | 
|  | rhs = num_negate (rhs, precision); | 
|  | } | 
|  | if (rhs.high) | 
|  | n = ~0;			/* Maximal.  */ | 
|  | else | 
|  | n = rhs.low; | 
|  | if (op == CPP_LSHIFT) | 
|  | lhs = num_lshift (lhs, precision, n); | 
|  | else | 
|  | lhs = num_rshift (lhs, precision, n); | 
|  | break; | 
|  |  | 
|  | /* Arithmetic.  */ | 
|  | case CPP_MINUS: | 
|  | 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; | 
|  | 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; | 
|  |  | 
|  | /* Comma.  */ | 
|  | default: /* case CPP_COMMA: */ | 
|  | if (CPP_PEDANTIC (pfile) && (!CPP_OPTION (pfile, c99) | 
|  | || !pfile->state.skip_eval)) | 
|  | cpp_pedwarning (pfile, CPP_W_PEDANTIC, | 
|  | "comma operator in operand of #if"); | 
|  | lhs = rhs; | 
|  | break; | 
|  | } | 
|  |  | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* Multiplies two unsigned cpp_num_parts to give a cpp_num.  This | 
|  | cannot overflow.  */ | 
|  | static cpp_num | 
|  | num_part_mul (cpp_num_part lhs, cpp_num_part rhs) | 
|  | { | 
|  | cpp_num result; | 
|  | cpp_num_part middle[2], temp; | 
|  |  | 
|  | result.low = LOW_PART (lhs) * LOW_PART (rhs); | 
|  | result.high = HIGH_PART (lhs) * HIGH_PART (rhs); | 
|  |  | 
|  | middle[0] = LOW_PART (lhs) * HIGH_PART (rhs); | 
|  | middle[1] = HIGH_PART (lhs) * LOW_PART (rhs); | 
|  |  | 
|  | temp = result.low; | 
|  | result.low += LOW_PART (middle[0]) << (PART_PRECISION / 2); | 
|  | if (result.low < temp) | 
|  | result.high++; | 
|  |  | 
|  | temp = result.low; | 
|  | result.low += LOW_PART (middle[1]) << (PART_PRECISION / 2); | 
|  | if (result.low < temp) | 
|  | result.high++; | 
|  |  | 
|  | result.high += HIGH_PART (middle[0]); | 
|  | result.high += HIGH_PART (middle[1]); | 
|  | result.unsignedp = true; | 
|  | result.overflow = false; | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Multiply two preprocessing numbers.  */ | 
|  | static cpp_num | 
|  | num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs) | 
|  | { | 
|  | cpp_num result, temp; | 
|  | bool unsignedp = lhs.unsignedp || rhs.unsignedp; | 
|  | bool overflow, negate = false; | 
|  | size_t precision = CPP_OPTION (pfile, precision); | 
|  |  | 
|  | /* Prepare for unsigned multiplication.  */ | 
|  | if (!unsignedp) | 
|  | { | 
|  | if (!num_positive (lhs, precision)) | 
|  | negate = !negate, lhs = num_negate (lhs, precision); | 
|  | if (!num_positive (rhs, precision)) | 
|  | negate = !negate, rhs = num_negate (rhs, precision); | 
|  | } | 
|  |  | 
|  | overflow = lhs.high && rhs.high; | 
|  | result = num_part_mul (lhs.low, rhs.low); | 
|  |  | 
|  | temp = num_part_mul (lhs.high, rhs.low); | 
|  | result.high += temp.low; | 
|  | if (temp.high) | 
|  | overflow = true; | 
|  |  | 
|  | temp = num_part_mul (lhs.low, rhs.high); | 
|  | result.high += temp.low; | 
|  | if (temp.high) | 
|  | overflow = true; | 
|  |  | 
|  | temp.low = result.low, temp.high = result.high; | 
|  | result = num_trim (result, precision); | 
|  | if (!num_eq (result, temp)) | 
|  | overflow = true; | 
|  |  | 
|  | if (negate) | 
|  | result = num_negate (result, precision); | 
|  |  | 
|  | if (unsignedp) | 
|  | result.overflow = false; | 
|  | else | 
|  | result.overflow = overflow || (num_positive (result, precision) ^ !negate | 
|  | && !num_zerop (result)); | 
|  | result.unsignedp = unsignedp; | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Divide two preprocessing numbers, LHS and RHS, returning the answer | 
|  | or the remainder depending upon OP. LOCATION is the source location | 
|  | of this operator (for diagnostics).  */ | 
|  |  | 
|  | static cpp_num | 
|  | num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op, | 
|  | location_t location) | 
|  | { | 
|  | cpp_num result, sub; | 
|  | cpp_num_part mask; | 
|  | bool unsignedp = lhs.unsignedp || rhs.unsignedp; | 
|  | bool negate = false, lhs_neg = false; | 
|  | size_t i, precision = CPP_OPTION (pfile, precision); | 
|  |  | 
|  | /* Prepare for unsigned division.  */ | 
|  | if (!unsignedp) | 
|  | { | 
|  | if (!num_positive (lhs, precision)) | 
|  | negate = !negate, lhs_neg = true, lhs = num_negate (lhs, precision); | 
|  | if (!num_positive (rhs, precision)) | 
|  | negate = !negate, rhs = num_negate (rhs, precision); | 
|  | } | 
|  |  | 
|  | /* Find the high bit.  */ | 
|  | if (rhs.high) | 
|  | { | 
|  | i = precision - 1; | 
|  | mask = (cpp_num_part) 1 << (i - PART_PRECISION); | 
|  | for (; ; i--, mask >>= 1) | 
|  | if (rhs.high & mask) | 
|  | break; | 
|  | } | 
|  | else if (rhs.low) | 
|  | { | 
|  | if (precision > PART_PRECISION) | 
|  | i = precision - PART_PRECISION - 1; | 
|  | else | 
|  | i = precision - 1; | 
|  | mask = (cpp_num_part) 1 << i; | 
|  | for (; ; i--, mask >>= 1) | 
|  | if (rhs.low & mask) | 
|  | break; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (!pfile->state.skip_eval) | 
|  | cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, | 
|  | "division by zero in #if"); | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* First nonzero bit of RHS is bit I.  Do naive division by | 
|  | shifting the RHS fully left, and subtracting from LHS if LHS is | 
|  | at least as big, and then repeating but with one less shift. | 
|  | This is not very efficient, but is easy to understand.  */ | 
|  |  | 
|  | rhs.unsignedp = true; | 
|  | lhs.unsignedp = true; | 
|  | i = precision - i - 1; | 
|  | sub = num_lshift (rhs, precision, i); | 
|  |  | 
|  | result.high = result.low = 0; | 
|  | for (;;) | 
|  | { | 
|  | if (num_greater_eq (lhs, sub, precision)) | 
|  | { | 
|  | lhs = num_binary_op (pfile, lhs, sub, CPP_MINUS); | 
|  | if (i >= PART_PRECISION) | 
|  | result.high |= (cpp_num_part) 1 << (i - PART_PRECISION); | 
|  | else | 
|  | result.low |= (cpp_num_part) 1 << i; | 
|  | } | 
|  | if (i-- == 0) | 
|  | break; | 
|  | sub.low = (sub.low >> 1) | (sub.high << (PART_PRECISION - 1)); | 
|  | sub.high >>= 1; | 
|  | } | 
|  |  | 
|  | /* We divide so that the remainder has the sign of the LHS.  */ | 
|  | if (op == CPP_DIV) | 
|  | { | 
|  | result.unsignedp = unsignedp; | 
|  | result.overflow = false; | 
|  | if (!unsignedp) | 
|  | { | 
|  | if (negate) | 
|  | result = num_negate (result, precision); | 
|  | result.overflow = (num_positive (result, precision) ^ !negate | 
|  | && !num_zerop (result)); | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* CPP_MOD.  */ | 
|  | lhs.unsignedp = unsignedp; | 
|  | lhs.overflow = false; | 
|  | if (lhs_neg) | 
|  | lhs = num_negate (lhs, precision); | 
|  |  | 
|  | return lhs; | 
|  | } | 
|  |  |