summaryrefslogtreecommitdiff
path: root/support/cpp/libcpp/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/cpp/libcpp/expr.c')
-rw-r--r--support/cpp/libcpp/expr.c1366
1 files changed, 711 insertions, 655 deletions
diff --git a/support/cpp/libcpp/expr.c b/support/cpp/libcpp/expr.c
index 539663c19..60cb2816a 100644
--- a/support/cpp/libcpp/expr.c
+++ b/support/cpp/libcpp/expr.c
@@ -1,6 +1,6 @@
/* Parse C expressions for cpplib.
Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
- 2002, 2004, 2008, 2009 Free Software Foundation.
+ 2002, 2004, 2008, 2009, 2010 Free Software Foundation.
Contributed by Per Bothner, 1994.
This program is free software; you can redistribute it and/or modify it
@@ -29,8 +29,8 @@ along with this program; see the file COPYING3. If not see
struct op
{
- const cpp_token *token; /* The token forming op (for diagnostics). */
- cpp_num value; /* The value logically "right" of op. */
+ const cpp_token *token; /* The token forming op (for diagnostics). */
+ cpp_num value; /* The value logically "right" of op. */
source_location loc; /* The location of this value. */
enum cpp_ttype op;
};
@@ -48,11 +48,12 @@ 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);
+ enum cpp_ttype);
static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num,
- enum cpp_ttype);
+ 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);
+static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype,
+ source_location);
static cpp_num num_lshift (cpp_num, size_t, size_t);
static cpp_num num_rshift (cpp_num, size_t, size_t);
@@ -82,89 +83,106 @@ static void check_promotion (cpp_reader *, const struct op *);
static unsigned int
interpret_float_suffix (const uchar *s, size_t len)
{
- size_t f, l, w, q, i, d;
- size_t r, k, u, h;
+ size_t flags;
+ size_t f, d, l, w, q, i;
- f = l = w = q = i = d = 0;
- r = k = u = h = 0;
+ flags = 0;
+ f = d = l = w = q = i = 0;
- while (len--)
- switch (s[len])
+ /* 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 'r': case 'R': r++; break;
- case 'k': case 'K': k++; break;
- case 'u': case 'U': u++; break;
- case 'h': case 'H': h++; break;
- case 'f': case 'F':
- if (d > 0)
- return 0;
- f++;
- break;
- case 'l': case 'L':
- if (d > 0)
- return 0;
- 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;
- case 'w': case 'W':
- if (d > 0)
- return 0;
- w++;
- break;
- case 'q': case 'Q':
- if (d > 0)
- return 0;
- q++;
- break;
- case 'i': case 'I':
- case 'j': case 'J': i++; break;
- case 'd': case 'D': d++; break;
+ 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:
- return 0;
+ /* Additional two-character suffixes beginning with D are not
+ for decimal float constants. */
+ break;
}
+ }
- if (r + k > 1 || h > 1 || l > 2 || u > 1)
- return 0;
-
- if (r == 1)
+ /* Recognize a fixed-point suffix. */
+ switch (s[len-1])
{
- if (f || i || d || w || q)
- return 0;
-
- return (CPP_N_FRACT
- | (u ? CPP_N_UNSIGNED : 0)
- | (h ? CPP_N_SMALL :
- l == 2 ? CPP_N_LARGE :
- l == 1 ? CPP_N_MEDIUM : 0));
+ case 'k': case 'K': flags = CPP_N_ACCUM; break;
+ case 'r': case 'R': flags = CPP_N_FRACT; break;
+ default: break;
}
- if (k == 1)
+ /* Continue processing a fixed-point suffix. The suffix is case
+ insensitive except for ll or LL. Order is significant. */
+ if (flags)
{
- if (f || i || d || w || q)
- return 0;
-
- return (CPP_N_ACCUM
- | (u ? CPP_N_UNSIGNED : 0)
- | (h ? CPP_N_SMALL :
- l == 2 ? CPP_N_LARGE :
- l == 1 ? CPP_N_MEDIUM : 0));
+ 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;
}
- if (f + l + w + q > 1 || i > 1 || h + u > 0)
- 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;
+ }
- /* Allow dd, df, dl suffixes for decimal float constants. */
- if (d && ((d + f + l != 2) || i))
+ if (f + d + l + w + q > 1 || i > 1)
return 0;
return ((i ? CPP_N_IMAGINARY : 0)
- | (f ? CPP_N_SMALL :
- l ? CPP_N_LARGE :
- w ? CPP_N_MD_W :
- q ? CPP_N_MD_Q : CPP_N_MEDIUM)
- | (d ? CPP_N_DFLOAT : 0));
+ | (f ? CPP_N_SMALL :
+ d ? CPP_N_MEDIUM :
+ l ? CPP_N_LARGE :
+ w ? CPP_N_MD_W :
+ q ? CPP_N_MD_Q : CPP_N_DEFAULT));
}
/* Subroutine of cpp_classify_number. S points to an integer suffix
@@ -180,25 +198,25 @@ interpret_int_suffix (const uchar *s, size_t len)
while (len--)
switch (s[len])
{
- case 'u': case 'U': u++; break;
+ 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;
+ 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;
+ return 0;
}
if (l > 2 || u > 1 || i > 1)
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));
+ | (u ? CPP_N_UNSIGNED : 0)
+ | ((l == 0) ? CPP_N_SMALL
+ : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
}
/* Categorize numeric constants according to their field (integer,
@@ -211,6 +229,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
const uchar *limit;
unsigned int max_digit, result, radix;
enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
+ bool seen_digit;
/* If the lexer has done its job, length one can only be a single
digit. Fast-path this very common case. */
@@ -221,6 +240,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
float_flag = NOT_FLOAT;
max_digit = 0;
radix = 10;
+ seen_digit = false;
/* First, interpret the radix. */
if (*str == '0')
@@ -230,16 +250,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
/* Require at least one hex digit to classify it as hex. */
if ((*str == 'x' || *str == 'X')
- && (str[1] == '.' || ISXDIGIT (str[1])))
- {
- radix = 16;
- str++;
- }
+ && (str[1] == '.' || ISXDIGIT (str[1])))
+ {
+ radix = 16;
+ str++;
+ }
else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1'))
- {
- radix = 2;
- str++;
- }
+ {
+ radix = 2;
+ str++;
+ }
}
/* Now scan for a well-formed integer or float. */
@@ -248,30 +268,31 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
unsigned int c = *str++;
if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
- {
- c = hex_value (c);
- if (c > max_digit)
- max_digit = c;
- }
+ {
+ seen_digit = true;
+ c = hex_value (c);
+ if (c > max_digit)
+ max_digit = c;
+ }
else if (c == '.')
- {
- if (float_flag == NOT_FLOAT)
- float_flag = AFTER_POINT;
- else
- SYNTAX_ERROR ("too many decimal points in number");
- }
+ {
+ if (float_flag == NOT_FLOAT)
+ float_flag = AFTER_POINT;
+ else
+ SYNTAX_ERROR ("too many decimal points in number");
+ }
else if ((radix <= 10 && (c == 'e' || c == 'E'))
- || (radix == 16 && (c == 'p' || c == 'P')))
- {
- float_flag = AFTER_EXPON;
- break;
- }
+ || (radix == 16 && (c == 'p' || c == 'P')))
+ {
+ float_flag = AFTER_EXPON;
+ break;
+ }
else
- {
- /* Start of suffix. */
- str--;
- break;
- }
+ {
+ /* Start of suffix. */
+ str--;
+ break;
+ }
}
/* The suffix may be for decimal fixed-point constants without exponent. */
@@ -279,19 +300,19 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
{
result = interpret_float_suffix (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 (pfile, CPP_DL_PEDWARN,
- "fixed-point constants are a GCC extension");
- goto syntax_ok;
- }
+ {
+ 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 (pfile, CPP_DL_PEDWARN,
+ "fixed-point constants are a GCC extension");
+ goto syntax_ok;
+ }
else
- result = 0;
+ result = 0;
}
if (float_flag != NOT_FLOAT && radix == 8)
@@ -300,56 +321,66 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
if (max_digit >= radix)
{
if (radix == 2)
- SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
+ SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
else
- SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+ SYNTAX_ERROR2 ("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");
- return CPP_N_INVALID;
- }
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "invalid prefix \"0b\" for floating constant");
+ return CPP_N_INVALID;
+ }
+
+ if (radix == 16 && !seen_digit)
+ SYNTAX_ERROR ("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");
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "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))
- SYNTAX_ERROR ("exponent has no digits");
-
- do
- str++;
- while (ISDIGIT (*str));
- }
+ {
+ if (*str == '+' || *str == '-')
+ str++;
+
+ /* Exponent is decimal, even if string is a hex float. */
+ if (!ISDIGIT (*str))
+ SYNTAX_ERROR ("exponent has no digits");
+
+ do
+ str++;
+ while (ISDIGIT (*str));
+ }
else if (radix == 16)
- SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
+ SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
result = interpret_float_suffix (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;
- }
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "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_error (pfile, CPP_DL_WARNING,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
+ && CPP_WTRADITIONAL (pfile)
+ && ! cpp_sys_macro_p (pfile))
+ cpp_error (pfile, CPP_DL_WARNING,
+ "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");
/* Radix must be 10 for decimal floats. */
if ((result & CPP_N_DFLOAT) && radix != 10)
@@ -361,12 +392,12 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
}
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 (pfile, CPP_DL_PEDWARN,
+ "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 (pfile, CPP_DL_PEDWARN,
+ "decimal float constants are a GCC extension");
result |= CPP_N_FLOATING;
}
@@ -374,31 +405,33 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
{
result = interpret_int_suffix (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;
- }
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "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;
+ {
+ int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
+ int large = (result & CPP_N_WIDTH) == CPP_N_LARGE;
- if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
- cpp_error (pfile, CPP_DL_WARNING,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
- }
+ if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
+ cpp_error (pfile, CPP_DL_WARNING,
+ "traditional C rejects the \"%.*s\" suffix",
+ (int) (limit - str), str);
+ }
if ((result & CPP_N_WIDTH) == CPP_N_LARGE
- && ! CPP_OPTION (pfile, c99)
- && CPP_OPTION (pfile, warn_long_long))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "use of C99 long long integer constant");
+ && CPP_OPTION (pfile, warn_long_long))
+ cpp_error (pfile,
+ CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN,
+ CPP_OPTION (pfile, cplusplus)
+ ? "use of C++0x long long integer constant"
+ : "use of C99 long long integer constant");
result |= CPP_N_INTEGER;
}
@@ -406,10 +439,10 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
syntax_ok:
if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
cpp_error (pfile, CPP_DL_PEDWARN,
- "imaginary constants are a GCC extension");
+ "imaginary constants are a GCC extension");
if (radix == 2 && CPP_PEDANTIC (pfile))
cpp_error (pfile, CPP_DL_PEDWARN,
- "binary constants are a GCC extension");
+ "binary constants are a GCC extension");
if (radix == 10)
result |= CPP_N_DECIMAL;
@@ -434,7 +467,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
drag in GCC's floating point emulator. */
cpp_num
cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
- unsigned int type)
+ unsigned int type)
{
const uchar *p, *end;
cpp_num result;
@@ -458,65 +491,84 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
bool overflow = false;
if ((type & CPP_N_RADIX) == CPP_N_OCTAL)
- {
- base = 8;
- p++;
- }
+ {
+ base = 8;
+ p++;
+ }
else if ((type & CPP_N_RADIX) == CPP_N_HEX)
- {
- base = 16;
- p += 2;
- }
+ {
+ base = 16;
+ p += 2;
+ }
else if ((type & CPP_N_RADIX) == CPP_N_BINARY)
- {
- base = 2;
- p += 2;
- }
+ {
+ base = 2;
+ p += 2;
+ }
/* We can add a digit to numbers strictly less than this without
- needing the precision and slowness of double integers. */
+ needing the precision and slowness of double integers. */
max = ~(cpp_num_part) 0;
if (precision < PART_PRECISION)
- max >>= PART_PRECISION - 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
- 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;
- }
- }
+ {
+ c = *p;
+
+ if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
+ c = hex_value (c);
+ 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)
- cpp_error (pfile, CPP_DL_PEDWARN,
- "integer constant is too large for its type");
+ 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. */
+ 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))
- {
- if (base == 10)
- cpp_error (pfile, CPP_DL_WARNING,
- "integer constant is so large that it is unsigned");
- result.unsignedp = true;
- }
+ && !(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;
@@ -606,54 +658,54 @@ parse_defined (cpp_reader *pfile)
if (token->type == CPP_NAME)
{
- node = token->val.node;
+ 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;
- }
+ {
+ cpp_error (pfile, CPP_DL_ERROR, "missing ')' after \"defined\"");
+ node = 0;
+ }
}
else
{
cpp_error (pfile, CPP_DL_ERROR,
- "operator \"defined\" requires an identifier");
+ "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));
- }
+ {
+ 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));
+ }
}
if (node)
{
if (pfile->context != initial_context && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
- "this use of \"defined\" may not be portable");
+ cpp_error (pfile, CPP_DL_WARNING,
+ "this use of \"defined\" may not be portable");
_cpp_mark_macro_used (node);
if (!(node->flags & NODE_USED))
- {
- node->flags |= NODE_USED;
- if (node->type == NT_MACRO)
- {
- if (pfile->cb.used_define)
- pfile->cb.used_define (pfile, pfile->directive_line, node);
- }
- else
- {
- if (pfile->cb.used_undef)
- pfile->cb.used_undef (pfile, pfile->directive_line, node);
- }
- }
+ {
+ node->flags |= NODE_USED;
+ if (node->type == NT_MACRO)
+ {
+ if (pfile->cb.used_define)
+ pfile->cb.used_define (pfile, pfile->directive_line, node);
+ }
+ else
+ {
+ if (pfile->cb.used_undef)
+ pfile->cb.used_undef (pfile, pfile->directive_line, node);
+ }
+ }
/* A possible controlling macro of the form #if !defined ().
- _cpp_parse_expr checks there was no other junk on the line. */
+ _cpp_parse_expr checks there was no other junk on the line. */
pfile->mi_ind_cmacro = node;
}
@@ -684,22 +736,22 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
case CPP_NUMBER:
temp = cpp_classify_number (pfile, token);
switch (temp & CPP_N_CATEGORY)
- {
- case CPP_N_FLOATING:
- cpp_error (pfile, CPP_DL_ERROR,
- "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");
- break;
-
- case CPP_N_INVALID:
- /* Error already issued. */
- break;
- }
+ {
+ case CPP_N_FLOATING:
+ cpp_error (pfile, CPP_DL_ERROR,
+ "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");
+ break;
+
+ case CPP_N_INVALID:
+ /* Error already issued. */
+ break;
+ }
result.high = result.low = 0;
break;
@@ -708,55 +760,55 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
case CPP_CHAR16:
case CPP_CHAR32:
{
- 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));
- }
+ 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 == pfile->spec_nodes.n_defined)
- return parse_defined (pfile);
+ if (token->val.node.node == pfile->spec_nodes.n_defined)
+ return parse_defined (pfile);
else if (CPP_OPTION (pfile, cplusplus)
- && (token->val.node == pfile->spec_nodes.n_true
- || token->val.node == pfile->spec_nodes.n_false))
- {
- result.high = 0;
- result.low = (token->val.node == pfile->spec_nodes.n_true);
- }
+ && (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_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined",
- NODE_NAME (token->val.node));
- }
+ {
+ result.high = 0;
+ result.low = 0;
+ if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
+ cpp_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined",
+ 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 (pfile, CPP_DL_PEDWARN,
- "assertions are a GCC extension");
- else if (CPP_OPTION (pfile, warn_deprecated))
- cpp_error (pfile, CPP_DL_WARNING,
- "assertions are a deprecated extension");
- }
+ {
+ /* 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");
+ else if (CPP_OPTION (pfile, warn_deprecated))
+ cpp_error (pfile, CPP_DL_WARNING,
+ "assertions are a deprecated extension");
+ }
_cpp_test_assertion (pfile, &temp);
result.high = 0;
result.low = temp;
@@ -794,9 +846,9 @@ 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)
+#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. */
@@ -806,38 +858,38 @@ static const struct cpp_operator
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},
+ /* 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}
+ /* 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.
@@ -878,104 +930,104 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
op.loc = op.token->src_loc;
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_NAME:
- case CPP_HASH:
- if (!want_value)
- SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
- want_value = false;
- top->value = eval_token (pfile, op.token);
- 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 ("token \"%s\" is not valid in preprocessor expressions",
- cpp_token_as_text (pfile, op.token));
- break;
- }
+ {
+ /* These tokens convert into values. */
+ case CPP_NUMBER:
+ case CPP_CHAR:
+ case CPP_WCHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
+ case CPP_NAME:
+ case CPP_HASH:
+ if (!want_value)
+ SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
+ cpp_token_as_text (pfile, op.token));
+ want_value = false;
+ top->value = eval_token (pfile, op.token);
+ 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 ("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 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
- }
+ {
+ if (!want_value)
+ SYNTAX_ERROR2 ("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 ')'");
-
- if (op.op == CPP_EOF && top->op == CPP_EOF)
- SYNTAX_ERROR2 ("%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));
- 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));
- }
+ {
+ /* 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 ')'");
+
+ if (op.op == CPP_EOF && top->op == CPP_EOF)
+ SYNTAX_ERROR2 ("%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));
+ 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));
+ }
top = reduce (pfile, top, op.op);
if (!top)
- goto syntax_error;
+ goto syntax_error;
if (op.op == CPP_EOF)
- break;
+ 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 (" ':' without preceding '?'");
- if (!num_zerop (top[-1].value)) /* Was '?' condition true? */
- pfile->state.skip_eval++;
- else
- pfile->state.skip_eval--;
- default:
- break;
- }
+ {
+ 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 (" ':' 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 = _cpp_expand_op_stack (pfile);
top->op = op.op;
top->token = op.token;
@@ -991,7 +1043,7 @@ _cpp_parse_expr (cpp_reader *pfile, bool is_if)
if (top != pfile->op_stack)
{
cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in %s",
- is_if ? "#if" : "#elif");
+ is_if ? "#if" : "#elif");
syntax_error:
return false; /* Return false on syntax error. */
}
@@ -1023,134 +1075,134 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
while (prio < optab[top->op].prio)
{
if (CPP_OPTION (pfile, warn_num_sign_change)
- && optab[top->op].flags & CHECK_PROMOTION)
- check_promotion (pfile, top);
+ && 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[-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;
- }
+ {
+ 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");
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "integer overflow in preprocessor expression");
}
if (op == CPP_CLOSE_PAREN)
@@ -1186,14 +1238,14 @@ check_promotion (cpp_reader *pfile, const struct op *op)
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));
+ 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));
+ "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. */
@@ -1204,12 +1256,12 @@ num_trim (cpp_num num, size_t precision)
{
precision -= PART_PRECISION;
if (precision < PART_PRECISION)
- num.high &= ((cpp_num_part) 1 << precision) - 1;
+ num.high &= ((cpp_num_part) 1 << precision) - 1;
}
else
{
if (precision < PART_PRECISION)
- num.low &= ((cpp_num_part) 1 << precision) - 1;
+ num.low &= ((cpp_num_part) 1 << precision) - 1;
num.high = 0;
}
@@ -1237,18 +1289,18 @@ 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));
- }
+ {
+ 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;
- }
+ {
+ if (precision < PART_PRECISION)
+ num.low |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
+ num.high = ~(cpp_num_part) 0;
+ }
}
return num;
@@ -1286,7 +1338,7 @@ num_greater_eq (cpp_num pa, cpp_num pb, size_t precision)
unsignedp = num_positive (pa, precision);
if (unsignedp != num_positive (pb, precision))
- return unsignedp;
+ return unsignedp;
/* Otherwise we can do an unsigned comparison. */
}
@@ -1297,7 +1349,7 @@ num_greater_eq (cpp_num pa, cpp_num pb, size_t precision)
/* 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)
+ cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
{
lhs.overflow = false;
lhs.unsignedp = lhs.unsignedp || rhs.unsignedp;
@@ -1326,7 +1378,7 @@ num_bitwise_op (cpp_reader *pfile ATTRIBUTE_UNUSED,
/* 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)
+ enum cpp_ttype op)
{
bool gte = num_greater_eq (lhs, rhs, CPP_OPTION (pfile, precision));
@@ -1348,7 +1400,7 @@ num_inequality_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs,
/* 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)
+ 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);
@@ -1379,22 +1431,22 @@ num_rshift (cpp_num num, size_t precision, size_t n)
{
/* Sign-extend. */
if (precision < PART_PRECISION)
- num.high = sign_mask, num.low |= sign_mask << precision;
+ num.high = sign_mask, num.low |= sign_mask << precision;
else if (precision < 2 * PART_PRECISION)
- num.high |= sign_mask << (precision - PART_PRECISION);
+ num.high |= sign_mask << (precision - PART_PRECISION);
if (n >= PART_PRECISION)
- {
- n -= PART_PRECISION;
- num.low = num.high;
- num.high = sign_mask;
- }
+ {
+ 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.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
+ num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
+ }
}
num = num_trim (num, precision);
@@ -1418,25 +1470,25 @@ num_lshift (cpp_num num, size_t precision, size_t n)
orig = num;
if (m >= PART_PRECISION)
- {
- m -= PART_PRECISION;
- num.high = num.low;
- num.low = 0;
- }
+ {
+ 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.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
+ num.low <<= m;
+ }
num = num_trim (num, precision);
if (num.unsignedp)
- num.overflow = false;
+ num.overflow = false;
else
- {
- maybe_orig = num_rshift (num, precision, n);
- num.overflow = !num_eq (orig, maybe_orig);
- }
+ {
+ maybe_orig = num_rshift (num, precision, n);
+ num.overflow = !num_eq (orig, maybe_orig);
+ }
}
return num;
@@ -1450,8 +1502,8 @@ num_unary_op (cpp_reader *pfile, cpp_num num, enum cpp_ttype op)
{
case CPP_UPLUS:
if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_WARNING,
- "traditional C rejects the unary plus operator");
+ cpp_error (pfile, CPP_DL_WARNING,
+ "traditional C rejects the unary plus operator");
num.overflow = false;
break;
@@ -1491,22 +1543,22 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
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);
- }
+ {
+ /* 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. */
+ n = ~0; /* Maximal. */
else
- n = rhs.low;
+ n = rhs.low;
if (op == CPP_LSHIFT)
- lhs = num_lshift (lhs, precision, n);
+ lhs = num_lshift (lhs, precision, n);
else
- lhs = num_rshift (lhs, precision, n);
+ lhs = num_rshift (lhs, precision, n);
break;
/* Arithmetic. */
@@ -1516,25 +1568,25 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
result.low = lhs.low + rhs.low;
result.high = lhs.high + rhs.high;
if (result.low < lhs.low)
- result.high++;
+ 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));
- }
+ {
+ 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_error (pfile, CPP_DL_PEDWARN,
- "comma operator in operand of #if");
+ || !pfile->state.skip_eval))
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "comma operator in operand of #if");
lhs = rhs;
break;
}
@@ -1587,9 +1639,9 @@ num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
if (!unsignedp)
{
if (!num_positive (lhs, precision))
- negate = !negate, lhs = num_negate (lhs, precision);
+ negate = !negate, lhs = num_negate (lhs, precision);
if (!num_positive (rhs, precision))
- negate = !negate, rhs = num_negate (rhs, precision);
+ negate = !negate, rhs = num_negate (rhs, precision);
}
overflow = lhs.high && rhs.high;
@@ -1617,16 +1669,19 @@ num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
result.overflow = false;
else
result.overflow = overflow || (num_positive (result, precision) ^ !negate
- && !num_zerop (result));
+ && !num_zerop (result));
result.unsignedp = unsignedp;
return result;
}
-/* Divide two preprocessing numbers, returning the answer or the
- remainder depending upon OP. */
+/* 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)
+num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
+ source_location location)
{
cpp_num result, sub;
cpp_num_part mask;
@@ -1638,9 +1693,9 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
if (!unsignedp)
{
if (!num_positive (lhs, precision))
- negate = !negate, lhs_neg = true, lhs = num_negate (lhs, precision);
+ negate = !negate, lhs_neg = true, lhs = num_negate (lhs, precision);
if (!num_positive (rhs, precision))
- negate = !negate, rhs = num_negate (rhs, precision);
+ negate = !negate, rhs = num_negate (rhs, precision);
}
/* Find the high bit. */
@@ -1649,24 +1704,25 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
i = precision - 1;
mask = (cpp_num_part) 1 << (i - PART_PRECISION);
for (; ; i--, mask >>= 1)
- if (rhs.high & mask)
- break;
+ if (rhs.high & mask)
+ break;
}
else if (rhs.low)
{
if (precision > PART_PRECISION)
- i = precision - PART_PRECISION - 1;
+ i = precision - PART_PRECISION - 1;
else
- i = precision - 1;
+ i = precision - 1;
mask = (cpp_num_part) 1 << i;
for (; ; i--, mask >>= 1)
- if (rhs.low & mask)
- break;
+ if (rhs.low & mask)
+ break;
}
else
{
if (!pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_ERROR, "division by zero in #if");
+ cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
+ "division by zero in #if");
return lhs;
}
@@ -1684,15 +1740,15 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
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;
- }
+ {
+ 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;
+ break;
sub.low = (sub.low >> 1) | (sub.high << (PART_PRECISION - 1));
sub.high >>= 1;
}
@@ -1703,12 +1759,12 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
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));
- }
+ {
+ if (negate)
+ result = num_negate (result, precision);
+ result.overflow = (num_positive (result, precision) ^ !negate
+ && !num_zerop (result));
+ }
return result;
}