aboutsummaryrefslogtreecommitdiff
path: root/contrib/gcclibs/libcpp/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcclibs/libcpp/expr.c')
-rw-r--r--contrib/gcclibs/libcpp/expr.c65
1 files changed, 59 insertions, 6 deletions
diff --git a/contrib/gcclibs/libcpp/expr.c b/contrib/gcclibs/libcpp/expr.c
index 574b85ff656d..24fcb1b863e9 100644
--- a/contrib/gcclibs/libcpp/expr.c
+++ b/contrib/gcclibs/libcpp/expr.c
@@ -82,7 +82,7 @@ static void check_promotion (cpp_reader *, const struct op *);
static unsigned int
interpret_float_suffix (const uchar *s, size_t len)
{
- size_t f = 0, l = 0, i = 0, d = 0;
+ size_t f = 0, l = 0, i = 0, d = 0, d0 = 0;
while (len--)
switch (s[len])
@@ -101,7 +101,12 @@ interpret_float_suffix (const uchar *s, size_t len)
return 0;
}
- if (f + l > 1 || i > 1)
+ if (d == 1 && !f && !l) {
+ d = 0;
+ d0 = 1;
+ }
+
+ if (f + d0 + l > 1 || i > 1)
return 0;
/* Allow dd, df, dl suffixes for decimal float constants. */
@@ -110,7 +115,8 @@ interpret_float_suffix (const uchar *s, size_t len)
return ((i ? CPP_N_IMAGINARY : 0)
| (f ? CPP_N_SMALL :
- l ? CPP_N_LARGE : CPP_N_MEDIUM)
+ d0 ? CPP_N_MEDIUM :
+ l ? CPP_N_LARGE : CPP_N_DEFAULT)
| (d ? CPP_N_DFLOAT : 0));
}
@@ -182,6 +188,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
radix = 16;
str++;
}
+ else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1'))
+ {
+ radix = 2;
+ str++;
+ }
}
/* Now scan for a well-formed integer or float. */
@@ -220,10 +231,22 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
radix = 10;
if (max_digit >= radix)
- SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+ {
+ if (radix == 2)
+ SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit);
+ else
+ 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;
+ }
+
if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
cpp_error (pfile, CPP_DL_PEDWARN,
"use of C99 hexadecimal floating constant");
@@ -261,6 +284,13 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
"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)
{
@@ -308,11 +338,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
cpp_error (pfile, CPP_DL_PEDWARN,
"imaginary constants are a GCC extension");
+ if (radix == 2 && CPP_PEDANTIC (pfile))
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "binary constants are a GCC extension");
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;
@@ -363,6 +398,11 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
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. */
@@ -418,12 +458,25 @@ static cpp_num
append_digit (cpp_num num, int digit, int base, size_t precision)
{
cpp_num result;
- unsigned int shift = 3 + (base == 16);
+ unsigned int shift;
bool overflow;
cpp_num_part add_high, add_low;
- /* Multiply by 8 or 16. Catching this overflow here means we don't
+ /* 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;