]> git.gag.com Git - fw/sdcc/blobdiff - support/cpp/libcpp/expr.c
* support/cpp/output.h, support/cpp/opts-common.c,
[fw/sdcc] / support / cpp / libcpp / expr.c
index 8ac901086e97325e66c380c492d16074fcff33ed..539663c198658f4701ca65bc6ca112be8b9120ac 100644 (file)
@@ -1,11 +1,11 @@
 /* Parse C expressions for cpplib.
    Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
 /* Parse C expressions for cpplib.
    Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
-   2002, 2004 Free Software Foundation.
+   2002, 2004, 2008, 2009 Free Software Foundation.
    Contributed by Per Bothner, 1994.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
    Contributed by Per Bothner, 1994.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
 
 This program is distributed in the hope that it will be useful,
 later version.
 
 This program is distributed in the hope that it will be useful,
@@ -14,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with this program; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -32,6 +31,7 @@ struct op
 {
   const cpp_token *token;       /* The token forming op (for diagnostics).  */
   cpp_num value;                /* The value logically "right" of op.  */
 {
   const cpp_token *token;       /* The token forming op (for diagnostics).  */
   cpp_num value;                /* The value logically "right" of op.  */
+  source_location loc;          /* The location of this value.         */
   enum cpp_ttype op;
 };
 
   enum cpp_ttype op;
 };
 
@@ -637,6 +637,20 @@ parse_defined (cpp_reader *pfile)
                    "this use of \"defined\" may not be portable");
 
       _cpp_mark_macro_used (node);
                    "this use of \"defined\" may not be portable");
 
       _cpp_mark_macro_used (node);
+      if (!(node->flags & NODE_USED))
+        {
+          node->flags |= NODE_USED;
+          if (node->type == NT_MACRO)
+            {
+              if (pfile->cb.used_define)
+                pfile->cb.used_define (pfile, pfile->directive_line, node);
+            }
+          else
+            {
+              if (pfile->cb.used_undef)
+                pfile->cb.used_undef (pfile, pfile->directive_line, node);
+            }
+        }
 
       /* A possible controlling macro of the form #if !defined ().
          _cpp_parse_expr checks there was no other junk on the line.  */
 
       /* A possible controlling macro of the form #if !defined ().
          _cpp_parse_expr checks there was no other junk on the line.  */
@@ -691,6 +705,8 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
 
     case CPP_WCHAR:
     case CPP_CHAR:
 
     case CPP_WCHAR:
     case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
       {
         cppchar_t cc = cpp_interpret_charconst (pfile, token,
                                                 &temp, &unsignedp);
       {
         cppchar_t cc = cpp_interpret_charconst (pfile, token,
                                                 &temp, &unsignedp);
@@ -729,10 +745,25 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
         }
       break;
 
         }
       break;
 
-    default: /* CPP_HASH */
+    case CPP_HASH:
+      if (!pfile->state.skipping)
+        {
+          /* A pedantic warning takes precedence over a deprecated
+             warning here.  */
+          if (CPP_PEDANTIC (pfile))
+            cpp_error (pfile, CPP_DL_PEDWARN,
+                       "assertions are a GCC extension");
+          else if (CPP_OPTION (pfile, warn_deprecated))
+            cpp_error (pfile, CPP_DL_WARNING,
+                       "assertions are a deprecated extension");
+        }
       _cpp_test_assertion (pfile, &temp);
       result.high = 0;
       result.low = temp;
       _cpp_test_assertion (pfile, &temp);
       result.high = 0;
       result.low = temp;
+      break;
+
+    default:
+      abort ();
     }
 
   result.unsignedp = !!unsignedp;
     }
 
   result.unsignedp = !!unsignedp;
@@ -793,9 +824,11 @@ static const struct cpp_operator
   /* COMPL */           {16, NO_L_OPERAND},
   /* AND_AND */         {6, LEFT_ASSOC},
   /* OR_OR */           {5, LEFT_ASSOC},
   /* COMPL */           {16, NO_L_OPERAND},
   /* AND_AND */         {6, LEFT_ASSOC},
   /* OR_OR */           {5, LEFT_ASSOC},
-  /* QUERY */           {3, 0},
+  /* Note that QUERY, COLON, and COMMA must have the same precedence.
+     However, there are some special cases for these in reduce().  */
+  /* QUERY */           {4, 0},
   /* COLON */           {4, LEFT_ASSOC | CHECK_PROMOTION},
   /* COLON */           {4, LEFT_ASSOC | CHECK_PROMOTION},
-  /* COMMA */           {2, LEFT_ASSOC},
+  /* COMMA */           {4, LEFT_ASSOC},
   /* OPEN_PAREN */      {1, NO_L_OPERAND},
   /* CLOSE_PAREN */     {0, 0},
   /* EOF */             {0, 0},
   /* OPEN_PAREN */      {1, NO_L_OPERAND},
   /* CLOSE_PAREN */     {0, 0},
   /* EOF */             {0, 0},
@@ -819,7 +852,7 @@ static const struct cpp_operator
    stored in the 'value' field of the stack element of the operator
    that precedes it.  */
 bool
    stored in the 'value' field of the stack element of the operator
    that precedes it.  */
 bool
-_cpp_parse_expr (cpp_reader *pfile)
+_cpp_parse_expr (cpp_reader *pfile, bool is_if)
 {
   struct op *top = pfile->op_stack;
   unsigned int lex_count;
 {
   struct op *top = pfile->op_stack;
   unsigned int lex_count;
@@ -842,6 +875,7 @@ _cpp_parse_expr (cpp_reader *pfile)
       lex_count++;
       op.token = cpp_get_token (pfile);
       op.op = op.token->type;
       lex_count++;
       op.token = cpp_get_token (pfile);
       op.op = op.token->type;
+      op.loc = op.token->src_loc;
 
       switch (op.op)
         {
 
       switch (op.op)
         {
@@ -849,6 +883,8 @@ _cpp_parse_expr (cpp_reader *pfile)
         case CPP_NUMBER:
         case CPP_CHAR:
         case CPP_WCHAR:
         case CPP_NUMBER:
         case CPP_CHAR:
         case CPP_WCHAR:
+        case CPP_CHAR16:
+        case CPP_CHAR32:
         case CPP_NAME:
         case CPP_HASH:
           if (!want_value)
         case CPP_NAME:
         case CPP_HASH:
           if (!want_value)
@@ -892,7 +928,7 @@ _cpp_parse_expr (cpp_reader *pfile)
             SYNTAX_ERROR ("missing expression between '(' and ')'");
 
           if (op.op == CPP_EOF && top->op == CPP_EOF)
             SYNTAX_ERROR ("missing expression between '(' and ')'");
 
           if (op.op == CPP_EOF && top->op == CPP_EOF)
-            SYNTAX_ERROR ("#if with no expression");
+            SYNTAX_ERROR2 ("%s with no expression", is_if ? "#if" : "#elif");
 
           if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
             SYNTAX_ERROR2 ("operator '%s' has no right operand",
 
           if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
             SYNTAX_ERROR2 ("operator '%s' has no right operand",
@@ -943,6 +979,7 @@ _cpp_parse_expr (cpp_reader *pfile)
 
       top->op = op.op;
       top->token = op.token;
 
       top->op = op.op;
       top->token = op.token;
+      top->loc = op.token->src_loc;
     }
 
   /* The controlling macro expression is only valid if we called lex 3
     }
 
   /* The controlling macro expression is only valid if we called lex 3
@@ -953,7 +990,8 @@ _cpp_parse_expr (cpp_reader *pfile)
 
   if (top != pfile->op_stack)
     {
 
   if (top != pfile->op_stack)
     {
-      cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in #if");
+      cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in %s",
+                 is_if ? "#if" : "#elif");
     syntax_error:
       return false;  /* Return false on syntax error.  */
     }
     syntax_error:
       return false;  /* Return false on syntax error.  */
     }
@@ -995,6 +1033,7 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
         case CPP_NOT:
         case CPP_COMPL:
           top[-1].value = num_unary_op (pfile, top->value, top->op);
         case CPP_NOT:
         case CPP_COMPL:
           top[-1].value = num_unary_op (pfile, top->value, top->op);
+          top[-1].loc = top->loc;
           break;
 
         case CPP_PLUS:
           break;
 
         case CPP_PLUS:
@@ -1004,6 +1043,7 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
         case CPP_COMMA:
           top[-1].value = num_binary_op (pfile, top[-1].value,
                                          top->value, top->op);
         case CPP_COMMA:
           top[-1].value = num_binary_op (pfile, top[-1].value,
                                          top->value, top->op);
+          top[-1].loc = top->loc;
           break;
 
         case CPP_GREATER:
           break;
 
         case CPP_GREATER:
@@ -1012,12 +1052,14 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
         case CPP_LESS_EQ:
           top[-1].value
             = num_inequality_op (pfile, top[-1].value, top->value, top->op);
         case CPP_LESS_EQ:
           top[-1].value
             = num_inequality_op (pfile, top[-1].value, top->value, top->op);
+          top[-1].loc = top->loc;
           break;
 
         case CPP_EQ_EQ:
         case CPP_NOT_EQ:
           top[-1].value
             = num_equality_op (pfile, top[-1].value, top->value, top->op);
           break;
 
         case CPP_EQ_EQ:
         case CPP_NOT_EQ:
           top[-1].value
             = num_equality_op (pfile, top[-1].value, top->value, top->op);
+          top[-1].loc = top->loc;
           break;
 
         case CPP_AND:
           break;
 
         case CPP_AND:
@@ -1025,16 +1067,19 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
         case CPP_XOR:
           top[-1].value
             = num_bitwise_op (pfile, top[-1].value, top->value, top->op);
         case CPP_XOR:
           top[-1].value
             = num_bitwise_op (pfile, top[-1].value, top->value, top->op);
+          top[-1].loc = top->loc;
           break;
 
         case CPP_MULT:
           top[-1].value = num_mul (pfile, top[-1].value, top->value);
           break;
 
         case CPP_MULT:
           top[-1].value = num_mul (pfile, top[-1].value, top->value);
+          top[-1].loc = top->loc;
           break;
 
         case CPP_DIV:
         case CPP_MOD:
           top[-1].value = num_div_op (pfile, top[-1].value,
                                       top->value, top->op);
           break;
 
         case CPP_DIV:
         case CPP_MOD:
           top[-1].value = num_div_op (pfile, top[-1].value,
                                       top->value, top->op);
+          top[-1].loc = top->loc;
           break;
 
         case CPP_OR_OR:
           break;
 
         case CPP_OR_OR:
@@ -1046,6 +1091,7 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
           top->value.high = 0;
           top->value.unsignedp = false;
           top->value.overflow = false;
           top->value.high = 0;
           top->value.unsignedp = false;
           top->value.overflow = false;
+          top->loc = top[1].loc;
           continue;
 
         case CPP_AND_AND:
           continue;
 
         case CPP_AND_AND:
@@ -1057,16 +1103,20 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
           top->value.high = 0;
           top->value.unsignedp = false;
           top->value.overflow = false;
           top->value.high = 0;
           top->value.unsignedp = false;
           top->value.overflow = false;
+          top->loc = top[1].loc;
           continue;
 
         case CPP_OPEN_PAREN:
           if (op != CPP_CLOSE_PAREN)
             {
           continue;
 
         case CPP_OPEN_PAREN:
           if (op != CPP_CLOSE_PAREN)
             {
-              cpp_error (pfile, CPP_DL_ERROR, "missing ')' in expression");
+              cpp_error_with_line (pfile, CPP_DL_ERROR,
+                                   top->token->src_loc,
+                                   0, "missing ')' in expression");
               return 0;
             }
           top--;
           top->value = top[1].value;
               return 0;
             }
           top--;
           top->value = top[1].value;
+          top->loc = top[1].loc;
           return top;
 
         case CPP_COLON:
           return top;
 
         case CPP_COLON:
@@ -1075,14 +1125,21 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
             {
               pfile->state.skip_eval--;
               top->value = top[1].value;
             {
               pfile->state.skip_eval--;
               top->value = top[1].value;
+              top->loc = top[1].loc;
             }
           else
             }
           else
-            top->value = top[2].value;
+            {
+              top->value = top[2].value;
+              top->loc = top[2].loc;
+            }
           top->value.unsignedp = (top[1].value.unsignedp
                                   || top[2].value.unsignedp);
           continue;
 
         case CPP_QUERY:
           top->value.unsignedp = (top[1].value.unsignedp
                                   || top[2].value.unsignedp);
           continue;
 
         case CPP_QUERY:
+          /* COMMA and COLON should not reduce a QUERY operator.  */
+          if (op == CPP_COMMA || op == CPP_COLON)
+            return top;
           cpp_error (pfile, CPP_DL_ERROR, "'?' without following ':'");
           return 0;
 
           cpp_error (pfile, CPP_DL_ERROR, "'?' without following ':'");
           return 0;
 
@@ -1129,12 +1186,12 @@ check_promotion (cpp_reader *pfile, const struct op *op)
   if (op->value.unsignedp)
     {
       if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision)))
   if (op->value.unsignedp)
     {
       if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision)))
-        cpp_error (pfile, CPP_DL_WARNING,
-                   "the left operand of \"%s\" changes sign when promoted",
-                   cpp_token_as_text (pfile, op->token));
+        cpp_error_with_line (pfile, CPP_DL_WARNING, op[-1].loc, 0,
+                             "the left operand of \"%s\" changes sign when promoted",
+                             cpp_token_as_text (pfile, op->token));
     }
   else if (!num_positive (op->value, CPP_OPTION (pfile, precision)))
     }
   else if (!num_positive (op->value, CPP_OPTION (pfile, precision)))
-    cpp_error (pfile, CPP_DL_WARNING,
+    cpp_error_with_line (pfile, CPP_DL_WARNING, op->loc, 0,
                "the right operand of \"%s\" changes sign when promoted",
                cpp_token_as_text (pfile, op->token));
 }
                "the right operand of \"%s\" changes sign when promoted",
                cpp_token_as_text (pfile, op->token));
 }