Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Unified Diff: gcc/libcpp/expr.c

Issue 3050029: [gcc] GCC 4.5.0=>4.5.1 (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/nacl-toolchain.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gcc/libcpp/charset.c ('k') | gcc/libcpp/files.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gcc/libcpp/expr.c
diff --git a/gcc/libcpp/expr.c b/gcc/libcpp/expr.c
index edefd389cc75e3c63c2d689664eb9ddceac3e307..60cb2816a7ab9d3fed07c567362e62dea5ef24c0 100644
--- a/gcc/libcpp/expr.c
+++ b/gcc/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
@@ -52,7 +52,8 @@ static cpp_num num_inequality_op (cpp_reader *, cpp_num, cpp_num,
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);
+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;
+ if (len == 1)
+ return flags;
+ len--;
+
+ if (*s == 'u' || *s == 'U')
+ {
+ flags |= CPP_N_UNSIGNED;
+ if (len == 1)
+ return flags;
+ len--;
+ s++;
+ }
- return (CPP_N_ACCUM
- | (u ? CPP_N_UNSIGNED : 0)
- | (h ? CPP_N_SMALL :
- l == 2 ? CPP_N_LARGE :
- l == 1 ? CPP_N_MEDIUM : 0));
+ switch (*s)
+ {
+ case 'h': case 'H':
+ if (len == 1)
+ return flags |= CPP_N_SMALL;
+ break;
+ case 'l':
+ if (len == 1)
+ return flags |= CPP_N_MEDIUM;
+ if (len == 2 && s[1] == 'l')
+ return flags |= CPP_N_LARGE;
+ break;
+ case 'L':
+ if (len == 1)
+ return flags |= CPP_N_MEDIUM;
+ if (len == 2 && s[1] == 'L')
+ return flags |= CPP_N_LARGE;
+ break;
+ default:
+ break;
+ }
+ /* Anything left at this point is invalid. */
+ return 0;
}
- 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 :
+ d ? CPP_N_MEDIUM :
l ? CPP_N_LARGE :
w ? CPP_N_MD_W :
- q ? CPP_N_MD_Q : CPP_N_MEDIUM)
- | (d ? CPP_N_DFLOAT : 0));
+ q ? CPP_N_MD_Q : CPP_N_DEFAULT));
}
/* Subroutine of cpp_classify_number. S points to an integer suffix
@@ -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')
@@ -249,6 +269,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
{
+ seen_digit = true;
c = hex_value (c);
if (c > max_digit)
max_digit = c;
@@ -314,6 +335,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
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");
@@ -351,6 +375,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)
{
@@ -395,10 +426,12 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
}
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_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;
}
@@ -512,8 +545,27 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
&& 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_DL_WARNING,
+ 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;
}
@@ -606,7 +658,7 @@ 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\"");
@@ -726,14 +778,14 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
break;
case CPP_NAME:
- if (token->val.node == pfile->spec_nodes.n_defined)
+ 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))
+ && (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 == pfile->spec_nodes.n_true);
+ result.low = (token->val.node.node == pfile->spec_nodes.n_true);
}
else
{
@@ -741,7 +793,7 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
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_NAME (token->val.node.node));
}
break;
@@ -1078,7 +1130,7 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
case CPP_DIV:
case CPP_MOD:
top[-1].value = num_div_op (pfile, top[-1].value,
- top->value, top->op);
+ top->value, top->op, top->loc);
top[-1].loc = top->loc;
break;
@@ -1623,10 +1675,13 @@ num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
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;
@@ -1666,7 +1721,8 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
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;
}
« no previous file with comments | « gcc/libcpp/charset.c ('k') | gcc/libcpp/files.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698