cppexp.c (CPP_UMINUS, CPP_UPLUS): New.
authorNeil Booth <neil@daikokuya.demon.co.uk>
Fri, 26 Apr 2002 06:32:50 +0000 (06:32 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Fri, 26 Apr 2002 06:32:50 +0000 (06:32 +0000)
* 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

gcc/ChangeLog
gcc/cppexp.c
gcc/cpplib.h

index 87eb96191bdb345b999408f390979df4bc898868..93dd23b892613c2ca75f3a5fbb6f6b84dbd7e049 100644 (file)
@@ -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
index b62741b30daf7a1a3910dcd64c1fc8a5e107af62..e3756d7f23e700bfbe6b52d1e1d87f543022eba6 100644 (file)
@@ -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);
index 765d65a3869485788bb36e452aa052e6f6892f18..164c4c8b5b5d3b49b12e45b81583cad6f040bb4a 100644 (file)
@@ -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,