diff libcpp/expr.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents a06113de4d67
children b7f97abdc517
line wrap: on
line diff
--- a/libcpp/expr.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/libcpp/expr.c	Fri Feb 12 23:39:51 2010 +0900
@@ -52,7 +52,8 @@
 static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num,
 				enum cpp_ttype);
 static cpp_num num_mul (cpp_reader *, cpp_num, cpp_num);
-static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
+static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype,
+			   source_location);
 static cpp_num num_lshift (cpp_num, size_t, size_t);
 static cpp_num num_rshift (cpp_num, size_t, size_t);
 
@@ -82,89 +83,106 @@
 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;
+
+  flags = 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.  */
+  if (len == 2 && (*s == 'd' || *s == 'D'))
+    {
+      bool uppercase = (*s == 'D');
+      switch (s[1])
+      {
+      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:
+	/* Additional two-character suffixes beginning with D are not
+	   for decimal float constants.  */
+	break;
+      }
+    }
+
+  /* Recognize a fixed-point suffix.  */
+  switch (s[len-1])
+    {
+    case 'k': case 'K': flags = CPP_N_ACCUM; break;
+    case 'r': case 'R': flags = CPP_N_FRACT; break;
+    default: break;
+    }
 
-  f = l = w = q = i = d = 0;
-  r = k = u = h = 0;
+  /* Continue processing a fixed-point suffix.  The suffix is case
+     insensitive except for ll or LL.  Order is significant.  */
+  if (flags)
+    {
+      if (len == 1)
+	return flags;
+      len--;
+
+      if (*s == 'u' || *s == 'U')
+	{
+	  flags |= CPP_N_UNSIGNED;
+	  if (len == 1)
+	    return flags;
+	  len--;
+	  s++;
+        }
 
+      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;
+    }
+
+  /* In any remaining valid suffix, the case and order don't matter.  */
   while (len--)
     switch (s[len])
       {
-      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 '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;
-      case 'd': case 'D': d++; break;
       default:
 	return 0;
       }
 
-  if (r + k > 1 || h > 1 || l > 2 || u > 1)
-    return 0;
-
-  if (r == 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));
-    }
-
-  if (k == 1)
-    {
-      if (f || i || d || w || q)
-	return 0;
-
-      return (CPP_N_ACCUM
-	      | (u ? CPP_N_UNSIGNED : 0)
-	      | (h ? CPP_N_SMALL :
-		 l == 2 ? CPP_N_LARGE :
-		 l == 1 ? CPP_N_MEDIUM :  0));
-    }
-
-  if (f + l + w + q > 1 || i > 1 || h + u > 0)
-    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 +369,13 @@
 		   "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 +420,12 @@
 	}
 
       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 +539,27 @@
 		    && 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 +652,7 @@
 
   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 +772,14 @@
       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,7 +787,7 @@
 	  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;
 
@@ -1078,7 +1124,7 @@
 	case CPP_DIV:
 	case CPP_MOD:
 	  top[-1].value = num_div_op (pfile, top[-1].value,
-				      top->value, top->op);
+				      top->value, top->op, top->loc);
 	  top[-1].loc = top->loc;
 	  break;
 
@@ -1623,10 +1669,13 @@
   return result;
 }
 
-/* Divide two preprocessing numbers, returning the answer or the
-   remainder depending upon OP.  */
+/* Divide two preprocessing numbers, LHS and RHS, returning the answer
+   or the remainder depending upon OP. LOCATION is the source location
+   of this operator (for diagnostics).  */
+
 static cpp_num
-num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
+num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
+	    source_location location)
 {
   cpp_num result, sub;
   cpp_num_part mask;
@@ -1666,7 +1715,8 @@
   else
     {
       if (!pfile->state.skip_eval)
-	cpp_error (pfile, CPP_DL_ERROR, "division by zero in #if");
+	cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
+			     "division by zero in #if");
       return lhs;
     }