OSDN Git Service

* config/mips/mips.md (*zero_extend<GPR:mode>_trunc<SHORT:mode>,
[pf3gnuchains/gcc-fork.git] / libcpp / expr.c
index dbbb05a..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"
@@ -84,10 +83,10 @@ static unsigned int
 interpret_float_suffix (const uchar *s, size_t len)
 {
   size_t flags;
-  size_t f, l, w, q, i;
+  size_t f, d, l, w, q, i;
 
   flags = 0;
-  f = l = w = q = i = 0;
+  f = d = l = w = q = i = 0;
 
   /* Process decimal float suffixes, which are two letters starting
      with d or D.  Order and case are significant.  */
@@ -103,7 +102,9 @@ interpret_float_suffix (const uchar *s, size_t len)
       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;
       }
     }
 
@@ -162,6 +163,7 @@ interpret_float_suffix (const uchar *s, size_t 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;
@@ -171,14 +173,15 @@ interpret_float_suffix (const uchar *s, size_t len)
        return 0;
       }
 
-  if (f + l + w + q > 1 || i > 1)
+  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));
+            q ? CPP_N_MD_Q : CPP_N_DEFAULT));
 }
 
 /* Subroutine of cpp_classify_number.  S points to an integer suffix
@@ -365,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)
         {
@@ -409,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;
     }
@@ -526,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;
        }
@@ -620,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\"");
@@ -740,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
        {
@@ -755,7 +786,7 @@ 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;