* cppexp.c (lex): Move some code to _cpp_parse_expr, but
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 28 Apr 2002 23:14:56 +0000 (23:14 +0000)
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 28 Apr 2002 23:14:56 +0000 (23:14 +0000)
keep most cases as function eval_token.
(eval_token): New function.
(_cpp_parse_expr): Read token here for improved diagnostics.
Don't use op_as_text.  Detect bad ':' here.
(reduce): Don't detect bad ':' here.
(op_as_text): Remove.
* cpphash.h (_cpp_test_assertion): Change prototype.
* cpplib.c (_cpp_test_assertion): Change prototype.
testsuite:
* gcc.dg/cpp/if-cexp.c: Add a test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52866 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cppexp.c
gcc/cpphash.h
gcc/cpplib.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/if-cexp.c

index b8a0f7c..f4fcc8d 100644 (file)
@@ -1,3 +1,15 @@
+2002-04-29  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * cppexp.c (lex): Move some code to _cpp_parse_expr, but
+       keep most cases as function eval_token.
+       (eval_token): New function.
+       (_cpp_parse_expr): Read token here for improved diagnostics.
+       Don't use op_as_text.  Detect bad ':' here.
+       (reduce): Don't detect bad ':' here.
+       (op_as_text): Remove.
+       * cpphash.h (_cpp_test_assertion): Change prototype.
+       * cpplib.c (_cpp_test_assertion): Change prototype.
+
 2002-04-28  Richard Henderson  <rth@redhat.com>
 
        PR c/5154
index 29a2611..914a207 100644 (file)
@@ -36,8 +36,7 @@ static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
                                            unsigned HOST_WIDEST_INT));
 static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
 static struct op parse_defined PARAMS ((cpp_reader *));
-static struct op lex PARAMS ((cpp_reader *));
-static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
+static struct op eval_token PARAMS ((cpp_reader *, const cpp_token *));
 static struct op *reduce PARAMS ((cpp_reader *, struct op *, enum cpp_ttype));
 
 struct op
@@ -275,45 +274,30 @@ parse_defined (pfile)
   return op;
 }
 
-/* Read a token.  The returned type is CPP_NUMBER for a valid number
-   (an interpreted preprocessing number or character constant, or the
-   result of the "defined" or "#" operators), CPP_ERROR on error,
-   CPP_EOF, or the type of an operator token.  */
+/* Convert a token into a CPP_NUMBER (an interpreted preprocessing
+   number or character constant, or the result of the "defined" or "#"
+   operators), or CPP_ERROR on error.  */
 static struct op
-lex (pfile)
+eval_token (pfile, token)
      cpp_reader *pfile;
+     const cpp_token *token;
 {
+  unsigned int temp;
   struct op op;
-  const cpp_token *token = cpp_get_token (pfile);
+
+  op.op = CPP_NUMBER;
+  op.unsignedp = 0;
 
   switch (token->type)
     {
     case CPP_NUMBER:
       return parse_number (pfile, token);
 
-    case CPP_CHAR:
     case CPP_WCHAR:
-      {
-       unsigned int chars_seen;
-
-       if (token->type == CPP_CHAR)
-         op.unsignedp = 0;
-       else
-         op.unsignedp = WCHAR_UNSIGNED;
-       op.op = CPP_NUMBER;
-       op.value = cpp_interpret_charconst (pfile, token, 1, &chars_seen);
-       return op;
-      }
-
-    case CPP_STRING:
-    case CPP_WSTRING:
-      SYNTAX_ERROR ("string constants are not valid in #if");
-
-    case CPP_OTHER:
-      if (ISGRAPH (token->val.c))
-       SYNTAX_ERROR2 ("invalid character '%c' in #if", token->val.c);
-      else
-       SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", token->val.c);
+      op.unsignedp = WCHAR_UNSIGNED;
+    case CPP_CHAR:             /* Always unsigned.  */
+      op.value = cpp_interpret_charconst (pfile, token, 1, &temp);
+      break;
 
     case CPP_NAME:
       if (token->val.node == pfile->spec_nodes.n_defined)
@@ -322,8 +306,6 @@ lex (pfile)
               && (token->val.node == pfile->spec_nodes.n_true
                   || token->val.node == pfile->spec_nodes.n_false))
        {
-         op.op = CPP_NUMBER;
-         op.unsignedp = 0;
          op.value = (token->val.node == pfile->spec_nodes.n_true);
 
          /* Warn about use of true or false in #if when pedantic
@@ -333,46 +315,22 @@ lex (pfile)
            cpp_error (pfile, DL_PEDWARN,
                       "ISO C++ does not permit \"%s\" in #if",
                       NODE_NAME (token->val.node));
-         return op;
        }
       else
        {
-         op.op = CPP_NUMBER;
-         op.unsignedp = 0;
          op.value = 0;
-
          if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
            cpp_error (pfile, DL_WARNING, "\"%s\" is not defined",
                       NODE_NAME (token->val.node));
-         return op;
-       }
-
-    case CPP_HASH:
-      {
-       int temp;
-
-       op.op = CPP_NUMBER;
-       if (_cpp_test_assertion (pfile, &temp))
-         op.op = CPP_ERROR;
-       op.unsignedp = 0;
-       op.value = temp;
-       return op;
-      }
-
-    default:
-      if (((int) token->type > (int) CPP_EQ
-          && (int) token->type < (int) CPP_PLUS_EQ))
-       {
-         op.op = token->type;
-         return op;
        }
+      break;
 
-      SYNTAX_ERROR2 ("\"%s\" is not valid in #if expressions",
-                    cpp_token_as_text (pfile, token));
+    default: /* CPP_HASH */
+      if (_cpp_test_assertion (pfile, &temp))
+       op.op = CPP_ERROR;
+      op.value = temp;
     }
 
- syntax_error:
-  op.op = CPP_ERROR;
   return op;
 }
 
@@ -459,7 +417,7 @@ extra semantics need to be handled with operator-specific code.  */
    N entries of enum cpp_ttype.  */
 static const struct operator
 {
-  uchar prio;                  /* Priorities are even.  */
+  uchar prio;
   uchar flags;
 } optab[] =
 {
@@ -539,6 +497,7 @@ _cpp_parse_expr (pfile)
      cpp_reader *pfile;
 {
   struct op *top = pfile->op_stack;
+  const cpp_token *token = NULL, *prev_token;
   unsigned int lex_count;
   bool saw_leading_not, want_value = true;
 
@@ -556,19 +515,26 @@ _cpp_parse_expr (pfile)
     {
       struct op op;
 
-      /* Read a token */
-      op = lex (pfile);
+      prev_token = token;
+      token = cpp_get_token (pfile);
       lex_count++;
+      op.op = token->type;
 
       switch (op.op)
        {
-       case CPP_ERROR:
-         goto syntax_error;
+         /* These tokens convert into values.  */
        case CPP_NUMBER:
-         /* Push a value onto the stack.  */
+       case CPP_CHAR:
+       case CPP_WCHAR:
+       case CPP_NAME:
+       case CPP_HASH:
          if (!want_value)
-           SYNTAX_ERROR ("missing binary operator");
+           SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
+                          cpp_token_as_text (pfile, token));
          want_value = false;
+         op = eval_token (pfile, token);
+         if (op.op == CPP_ERROR)
+           goto syntax_error;
          top->value = op.value;
          top->unsignedp = op.unsignedp;
          continue;
@@ -584,7 +550,16 @@ _cpp_parse_expr (pfile)
          if (want_value)
            op.op = CPP_UMINUS;
          break;
+       case CPP_OTHER:
+         if (ISGRAPH (token->val.c))
+           SYNTAX_ERROR2 ("invalid character '%c' in #if", token->val.c);
+         else
+           SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", token->val.c);
+
        default:
+         if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
+           SYNTAX_ERROR2 ("token \"%s\" is not valid in #if expressions",
+                          cpp_token_as_text (pfile, token));
          break;
        }
 
@@ -592,11 +567,13 @@ _cpp_parse_expr (pfile)
       if (optab[op.op].flags & NO_L_OPERAND)
        {
          if (!want_value)
-           SYNTAX_ERROR2 ("missing binary operator before '%s'",
-                          op_as_text (pfile, op.op));
+           SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
+                          cpp_token_as_text (pfile, token));
        }
       else if (want_value)
        {
+         /* Ordering here is subtle and intended to favour the
+            missing parenthesis diagnostics over alternatives.  */
          if (op.op == CPP_CLOSE_PAREN)
            {
              if (top->op == CPP_OPEN_PAREN)
@@ -606,19 +583,20 @@ _cpp_parse_expr (pfile)
            SYNTAX_ERROR ("#if with no expression");
          if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
            SYNTAX_ERROR2 ("operator '%s' has no right operand",
-                          op_as_text (pfile, top->op));
+                          cpp_token_as_text (pfile, prev_token));
        }
 
       top = reduce (pfile, top, op.op);
       if (!top)
        goto syntax_error;
 
+      if (op.op == CPP_EOF)
+       break;
+
       switch (op.op)
        {
        case CPP_CLOSE_PAREN:
          continue;
-       case CPP_EOF:
-         goto done;
        case CPP_OR_OR:
          if (top->value)
            pfile->state.skip_eval++;
@@ -629,6 +607,8 @@ _cpp_parse_expr (pfile)
            pfile->state.skip_eval++;
          break;
        case CPP_COLON:
+         if (top->op != CPP_QUERY)
+           SYNTAX_ERROR (" ':' without preceding '?'");
          if (top[-1].value) /* Was '?' condition true?  */
            pfile->state.skip_eval++;
          else
@@ -646,7 +626,6 @@ _cpp_parse_expr (pfile)
       top->op = op.op;
     }
 
-done:
   /* The controlling macro expression is only valid if we called lex 3
      times: <!> <defined expression> and <EOF>.  push_conditional ()
      checks that we are at top-of-file.  */
@@ -693,8 +672,7 @@ reduce (pfile, top, op)
       switch (top[1].op)
        {
        default:
-         cpp_error (pfile, DL_ICE, "impossible operator '%s'",
-                    op_as_text (pfile, top[1].op));
+         cpp_error (pfile, DL_ICE, "impossible operator '%u'", top[1].op);
          return 0;
 
        case CPP_NOT:    UNARY(!);      break;
@@ -806,11 +784,6 @@ reduce (pfile, top, op)
          cpp_error (pfile, DL_ERROR, "'?' without following ':'");
          return 0;
        case CPP_COLON:
-         if (top->op != CPP_QUERY)
-           {
-             cpp_error (pfile, DL_ERROR, " ':' without preceding '?'");
-             return 0;
-           }
          top--;
          if (top->value) pfile->state.skip_eval--;
          top->value = top->value ? v1 : v2;
@@ -849,21 +822,3 @@ _cpp_expand_op_stack (pfile)
 
   return pfile->op_stack + n;
 }
-
-/* Output OP as text for diagnostics.  */
-static const unsigned char *
-op_as_text (pfile, op)
-     cpp_reader *pfile;
-     enum cpp_ttype 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 743feea..5ad0c6e 100644 (file)
@@ -413,7 +413,7 @@ extern void _cpp_init_tokenrun              PARAMS ((tokenrun *, unsigned int));
 extern void _cpp_maybe_push_include_file PARAMS ((cpp_reader *));
 
 /* In cpplib.c */
-extern int _cpp_test_assertion PARAMS ((cpp_reader *, int *));
+extern int _cpp_test_assertion PARAMS ((cpp_reader *, unsigned int *));
 extern int _cpp_handle_directive PARAMS ((cpp_reader *, int));
 extern void _cpp_define_builtin        PARAMS ((cpp_reader *, const char *));
 extern void _cpp_do__Pragma    PARAMS ((cpp_reader *));
index a579873..b210209 100644 (file)
@@ -1652,7 +1652,7 @@ find_answer (node, candidate)
 int
 _cpp_test_assertion (pfile, value)
      cpp_reader *pfile;
-     int *value;
+     unsigned int *value;
 {
   struct answer *answer;
   cpp_hashnode *node;
index 173ab5c..f806315 100644 (file)
@@ -1,3 +1,7 @@
+2002-04-29  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * gcc.dg/cpp/if-cexp.c: Add a test.
+
 2002-04-28  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/20020426-2.c: New test.
index e2af375..1ebd119 100644 (file)
@@ -10,4 +10,5 @@
 #error OK      /* { dg-error "OK" "nested ? : with parens" } */
 #endif
 
-
+#if 2:         /* { dg-error "':' without" "immediate :" } */
+#endif