OSDN Git Service

PR driver/40144
[pf3gnuchains/gcc-fork.git] / libcpp / expr.c
index af0e259..6887b16 100644 (file)
@@ -1,11 +1,11 @@
 /* Parse C expressions for cpplib.
    Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
-   2002, 2004, 2008 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
-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,
@@ -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
-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"
@@ -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.  */
+  source_location loc;          /* The location of this value.         */
   enum cpp_ttype op;
 };
 
@@ -82,89 +82,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
@@ -351,6 +368,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 +419,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 +538,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 +651,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 +771,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,14 +786,29 @@ 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;
 
-    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;
+      break;
+
+    default:
+      abort ();
     }
 
   result.unsignedp = !!unsignedp;
@@ -837,7 +897,7 @@ static const struct cpp_operator
    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;
@@ -860,6 +920,7 @@ _cpp_parse_expr (cpp_reader *pfile)
       lex_count++;
       op.token = cpp_get_token (pfile);
       op.op = op.token->type;
+      op.loc = op.token->src_loc;
 
       switch (op.op)
        {
@@ -912,7 +973,7 @@ _cpp_parse_expr (cpp_reader *pfile)
            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",
@@ -963,6 +1024,7 @@ _cpp_parse_expr (cpp_reader *pfile)
 
       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
@@ -973,7 +1035,8 @@ _cpp_parse_expr (cpp_reader *pfile)
 
   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.  */
     }
@@ -1015,6 +1078,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);
+         top[-1].loc = top->loc;
          break;
 
        case CPP_PLUS:
@@ -1024,6 +1088,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);
+         top[-1].loc = top->loc;
          break;
 
        case CPP_GREATER:
@@ -1032,12 +1097,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);
+         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);
+         top[-1].loc = top->loc;
          break;
 
        case CPP_AND:
@@ -1045,16 +1112,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);
+         top[-1].loc = top->loc;
          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);
+         top[-1].loc = top->loc;
          break;
 
        case CPP_OR_OR:
@@ -1066,6 +1136,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->loc = top[1].loc;
          continue;
 
        case CPP_AND_AND:
@@ -1077,16 +1148,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->loc = top[1].loc;
          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;
+         top->loc = top[1].loc;
          return top;
 
        case CPP_COLON:
@@ -1095,9 +1170,13 @@ reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
            {
              pfile->state.skip_eval--;
              top->value = top[1].value;
+             top->loc = top[1].loc;
            }
          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;
@@ -1152,12 +1231,12 @@ check_promotion (cpp_reader *pfile, const struct op *op)
   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)))
-    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));
 }