aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNeil Booth <neil@daikokuya.demon.co.uk>2002-04-26 06:32:50 +0000
committerNeil Booth <neil@gcc.gnu.org>2002-04-26 06:32:50 +0000
commitf8b954fcdc0446691171bd20e6cb218799d4d1a9 (patch)
tree41b138ea9b50f42af72e2ae19543c9e1a16ce126 /gcc
parent6052bef039abf0676722cd1df243c1cf5ab99431 (diff)
downloadgcc-f8b954fcdc0446691171bd20e6cb218799d4d1a9.zip
gcc-f8b954fcdc0446691171bd20e6cb218799d4d1a9.tar.gz
gcc-f8b954fcdc0446691171bd20e6cb218799d4d1a9.tar.bz2
cppexp.c (CPP_UMINUS, CPP_UPLUS): New.
* cppexp.c (CPP_UMINUS, CPP_UPLUS): New. (HAVE_NO_R_OPERAND): Remove. (HAVE_VALUE): Remove. (op_to_prio): Update. (UNARY): Don't alter flags. (_cpp_parse_expr): want_value used to indicate whether a number or unary operator is expected next. Distinguish unary and binary +/-. (op_as_text): Update for unary operators. From-SVN: r52780
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/cppexp.c153
-rw-r--r--gcc/cpplib.h13
3 files changed, 95 insertions, 83 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 87eb961..93dd23b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2002-04-26 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (CPP_UMINUS, CPP_UPLUS): New.
+ (HAVE_NO_R_OPERAND): Remove.
+ (HAVE_VALUE): Remove.
+ (op_to_prio): Update.
+ (UNARY): Don't alter flags.
+ (_cpp_parse_expr): want_value used to indicate whether
+ a number or unary operator is expected next. Distinguish
+ unary and binary +/-.
+ (op_as_text): Update for unary operators.
+
2002-04-25 Richard Henderson <rth@redhat.com>
PR c/2161
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
index b62741b..e3756d7 100644
--- a/gcc/cppexp.c
+++ b/gcc/cppexp.c
@@ -48,9 +48,12 @@ struct op
HOST_WIDEST_INT value; /* The value logically "right" of op. */
};
-/* There is no "error" token, but we can't get comments in #if, so we can
- abuse that token type. */
+/* Token type abuse. There is no "error" token, but we can't get
+ comments in #if, so we can abuse that token type. Similarly,
+ create unary plus and minus operators. */
#define CPP_ERROR CPP_COMMENT
+#define CPP_UPLUS (CPP_LAST_CPP_OP + 1)
+#define CPP_UMINUS (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. */
@@ -454,10 +457,9 @@ same way as the ultra-low priority end-of-expression dummy operator.
The exit code checks to see if the operator that caused it is ')', and
if so outputs an appropriate error message.
-The parser assumes all shifted operators require a right operand
-unless the flag NO_R_OPERAND is set, and similarly for NO_L_OPERAND.
-These semantics are automatically checked, any extra semantics need to
-be handled with operator-specific code. */
+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. */
#define FLAG_BITS 8
#define FLAG_MASK ((1 << FLAG_BITS) - 1)
@@ -466,10 +468,8 @@ be handled with operator-specific code. */
#define EXTRACT_FLAGS(CNST) ((CNST) & FLAG_MASK)
/* Flags. */
-#define HAVE_VALUE (1 << 0)
-#define NO_L_OPERAND (1 << 1)
-#define NO_R_OPERAND (1 << 2)
-#define SHORT_CIRCUIT (1 << 3)
+#define NO_L_OPERAND (1 << 0)
+#define SHORT_CIRCUIT (1 << 1)
/* Priority and flag combinations. */
#define RIGHT_ASSOC (1 << FLAG_BITS)
@@ -501,8 +501,8 @@ op_to_prio[] =
/* NOT */ UNARY_PRIO,
/* GREATER */ LESS_PRIO,
/* LESS */ LESS_PRIO,
- /* PLUS */ UNARY_PRIO, /* note these two can be unary */
- /* MINUS */ UNARY_PRIO, /* or binary */
+ /* PLUS */ PLUS_PRIO,
+ /* MINUS */ PLUS_PRIO,
/* MULT */ MUL_PRIO,
/* DIV */ MUL_PRIO,
/* MOD */ MUL_PRIO,
@@ -525,7 +525,10 @@ op_to_prio[] =
/* EQ_EQ */ EQUAL_PRIO,
/* NOT_EQ */ EQUAL_PRIO,
/* GREATER_EQ */ LESS_PRIO,
- /* LESS_EQ */ LESS_PRIO
+ /* LESS_EQ */ LESS_PRIO,
+ /* EOF */ FORCE_REDUCE_PRIO,
+ /* UPLUS */ UNARY_PRIO,
+ /* UMINUS */ UNARY_PRIO
};
#define COMPARE(OP) \
@@ -544,8 +547,7 @@ op_to_prio[] =
top->unsignedp = unsigned1 | unsigned2;
#define UNARY(OP) \
top->value = OP v2; \
- top->unsignedp = unsigned2; \
- top->flags |= HAVE_VALUE;
+ top->unsignedp = unsigned2;
#define SHIFT(PSH, MSH) \
if (skip_evaluation) \
break; \
@@ -568,8 +570,7 @@ _cpp_parse_expr (pfile)
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.
- In that case the 'flags' field has the HAVE_VALUE flag set. */
+ element of the operator that precedes it. */
#define INIT_STACK_SIZE 20
struct op init_stack[INIT_STACK_SIZE];
@@ -579,6 +580,7 @@ _cpp_parse_expr (pfile)
int skip_evaluation = 0;
int result;
unsigned int lex_count, saw_leading_not;
+ bool want_value = true;
/* Set up detection of #if ! defined(). */
pfile->mi_ind_cmacro = 0;
@@ -589,8 +591,6 @@ _cpp_parse_expr (pfile)
top->op = CPP_EOF;
/* Nifty way to catch missing '('. */
top->prio = EXTRACT_PRIO(CLOSE_PAREN_PRIO);
- /* Avoid missing right operand checks. */
- top->flags = NO_R_OPERAND;
for (;;)
{
@@ -603,38 +603,41 @@ _cpp_parse_expr (pfile)
lex_count++;
/* If the token is an operand, push its value and get next
- token. If it is an operator, get its priority and flags, and
- try to reduce the expression on the stack. */
+ token. If it is an operator, handle some special cases, get
+ its priority and flags, and try to reduce the expression on
+ the stack. */
switch (op.op)
{
case CPP_ERROR:
goto syntax_error;
- push_immediate:
case CPP_NUMBER:
/* Push a value onto the stack. */
- if (top->flags & HAVE_VALUE)
+ if (!want_value)
SYNTAX_ERROR ("missing binary operator");
+ push_immediate:
+ want_value = false;
top->value = op.value;
top->unsignedp = op.unsignedp;
- top->flags |= HAVE_VALUE;
continue;
- case CPP_EOF: prio = FORCE_REDUCE_PRIO; break;
-
case CPP_NOT:
saw_leading_not = lex_count == 1;
- prio = op_to_prio[op.op];
break;
case CPP_PLUS:
- case CPP_MINUS: prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break;
- /* else unary; fall through */
- default: prio = op_to_prio[op.op]; break;
+ if (want_value)
+ op.op = CPP_UPLUS;
+ break;
+ case CPP_MINUS:
+ if (want_value)
+ op.op = CPP_UMINUS;
+ break;
+ default:
+ break;
}
- /* Separate the operator's code into priority and flags. */
- flags = EXTRACT_FLAGS(prio);
- prio = EXTRACT_PRIO(prio);
- if (prio == EXTRACT_PRIO(OPEN_PAREN_PRIO))
+ flags = EXTRACT_FLAGS (op_to_prio[op.op]);
+ prio = EXTRACT_PRIO (op_to_prio[op.op]);
+ if (prio == EXTRACT_PRIO (OPEN_PAREN_PRIO))
goto skip_reduction;
/* Check for reductions. Then push the operator. */
@@ -645,13 +648,15 @@ _cpp_parse_expr (pfile)
/* Most operators that can appear on the stack require a
right operand. Check this before trying to reduce. */
- if ((top->flags & (HAVE_VALUE | NO_R_OPERAND)) == 0)
+ if (want_value)
{
if (top->op == CPP_OPEN_PAREN)
SYNTAX_ERROR ("void expression between '(' and ')'");
- else
+ else if (top->op != CPP_EOF)
SYNTAX_ERROR2 ("operator '%s' has no right operand",
op_as_text (pfile, top->op));
+ else if (op.op != CPP_CLOSE_PAREN)
+ SYNTAX_ERROR ("#if with no expression");
}
unsigned2 = top->unsignedp, v2 = top->value;
@@ -682,44 +687,35 @@ _cpp_parse_expr (pfile)
case CPP_MIN: MINMAX(<); break;
case CPP_MAX: MINMAX(>); break;
+ case CPP_UPLUS:
+ /* Can't use UNARY(+) because K+R C did not have unary
+ plus. Can't use UNARY() because some compilers object
+ to the empty argument. */
+ top->value = v2;
+ top->unsignedp = unsigned2;
+ if (CPP_WTRADITIONAL (pfile))
+ cpp_error (pfile, DL_WARNING,
+ "traditional C rejects the unary plus operator");
+ break;
+ case CPP_UMINUS:
+ UNARY(-);
+ if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
+ integer_overflow (pfile);
+ break;
+
case CPP_PLUS:
- if (!(top->flags & HAVE_VALUE))
- {
- /* Can't use UNARY(+) because K+R C did not have unary
- plus. Can't use UNARY() because some compilers object
- to the empty argument. */
- top->value = v2;
- top->unsignedp = unsigned2;
- top->flags |= HAVE_VALUE;
-
- if (CPP_WTRADITIONAL (pfile))
- cpp_error (pfile, DL_WARNING,
- "traditional C rejects the unary plus operator");
- }
- else
- {
- top->value = v1 + v2;
- top->unsignedp = unsigned1 | unsigned2;
- if (! top->unsignedp && ! skip_evaluation
- && ! possible_sum_sign (v1, v2, top->value))
- integer_overflow (pfile);
- }
+ top->value = v1 + v2;
+ top->unsignedp = unsigned1 | unsigned2;
+ if (! top->unsignedp && ! skip_evaluation
+ && ! possible_sum_sign (v1, v2, top->value))
+ integer_overflow (pfile);
break;
case CPP_MINUS:
- if (!(top->flags & HAVE_VALUE))
- {
- UNARY(-);
- if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
- integer_overflow (pfile);
- }
- else
- { /* Binary '-' */
- top->value = v1 - v2;
- top->unsignedp = unsigned1 | unsigned2;
- if (! top->unsignedp && ! skip_evaluation
- && ! possible_sum_sign (top->value, v2, v1))
- integer_overflow (pfile);
- }
+ top->value = v1 - v2;
+ top->unsignedp = unsigned1 | unsigned2;
+ if (! top->unsignedp && ! skip_evaluation
+ && ! possible_sum_sign (top->value, v2, v1))
+ integer_overflow (pfile);
break;
case CPP_MULT:
top->unsignedp = unsigned1 | unsigned2;
@@ -821,16 +817,17 @@ _cpp_parse_expr (pfile)
/* Check we have a left operand iff we need one. */
if (flags & NO_L_OPERAND)
{
- if (top->flags & HAVE_VALUE)
+ if (!want_value)
SYNTAX_ERROR2 ("missing binary operator before '%s'",
op_as_text (pfile, op.op));
}
else
{
- if (!(top->flags & HAVE_VALUE))
+ if (want_value)
SYNTAX_ERROR2 ("operator '%s' has no left operand",
op_as_text (pfile, op.op));
}
+ want_value = true;
/* Check for and handle stack overflow. */
top++;
@@ -868,11 +865,6 @@ _cpp_parse_expr (pfile)
if (top != stack)
{
cpp_error (pfile, DL_ICE, "unbalanced stack in #if");
- goto syntax_error;
- }
- else if (!(top[1].flags & HAVE_VALUE))
- {
- SYNTAX_ERROR ("#if with no expression");
syntax_error:
result = 0; /* Return 0 on syntax error. */
}
@@ -891,6 +883,11 @@ op_as_text (pfile, op)
{
cpp_token token;
+ if (op == CPP_UPLUS)
+ op = CPP_PLUS;
+ else if (op == CPP_UMINUS)
+ op = CPP_MINUS;
+
token.type = op;
token.flags = 0;
return cpp_token_as_text (pfile, &token);
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index 765d65a..164c4c8 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -46,9 +46,9 @@ typedef struct cpp_callbacks cpp_callbacks;
struct answer;
struct file_name_map_list;
-/* The first two groups, apart from '=', can appear in preprocessor
- expressions. This allows a lookup table to be implemented in
- _cpp_parse_expr.
+/* The first three groups, apart from '=', can appear in preprocessor
+ expressions (+= and -= are used to indicate unary + and - resp.).
+ This allows a lookup table to be implemented in _cpp_parse_expr.
The first group, to CPP_LAST_EQ, can be immediately followed by an
'='. The lexer needs operators ending in '=', like ">>=", to be in
@@ -58,6 +58,7 @@ struct file_name_map_list;
#define CPP_LAST_EQ CPP_MAX
#define CPP_FIRST_DIGRAPH CPP_HASH
#define CPP_LAST_PUNCTUATOR CPP_DOT_STAR
+#define CPP_LAST_CPP_OP CPP_EOF
#define TTYPE_TABLE \
OP(CPP_EQ = 0, "=") \
@@ -90,8 +91,11 @@ struct file_name_map_list;
OP(CPP_GREATER_EQ, ">=") \
OP(CPP_LESS_EQ, "<=") \
\
+ /* These 3 are special in preprocessor expressions. */ \
+ TK(CPP_EOF, SPELL_NONE) \
OP(CPP_PLUS_EQ, "+=") /* math */ \
OP(CPP_MINUS_EQ, "-=") \
+\
OP(CPP_MULT_EQ, "*=") \
OP(CPP_DIV_EQ, "/=") \
OP(CPP_MOD_EQ, "%=") \
@@ -135,8 +139,7 @@ struct file_name_map_list;
TK(CPP_COMMENT, SPELL_NUMBER) /* Only if output comments. */ \
/* SPELL_NUMBER happens to DTRT. */ \
TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \
- TK(CPP_PADDING, SPELL_NONE) /* Whitespace for cpp0. */ \
- TK(CPP_EOF, SPELL_NONE) /* End of line or file. */
+ TK(CPP_PADDING, SPELL_NONE) /* Whitespace for cpp0. */
#define OP(e, s) e,
#define TK(e, s) e,