This patch fixes PR 55715, bogus cpplib diagnostics for subtraction
involving the most negative integer arising from the implementation of
subtraction as negation followed by falling through into the addition
case.  The fix is simply to separate the subtraction implementation
from that of addition so the overflow check can be done using the
signs of the original operands.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline.

libcpp:
2013-12-09  Joseph Myers  <jos...@codesourcery.com>

        PR preprocessor/55715
        * expr.c (num_binary_op): Implement subtraction directly rather
        than with negation and falling through into addition case.

gcc/testsuite:
2013-12-09  Joseph Myers  <jos...@codesourcery.com>

        PR preprocessor/55715
        * gcc.dg/cpp/expr-overflow-1.c: New test.

Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c       (revision 205803)
+++ libcpp/expr.c       (working copy)
@@ -1836,7 +1836,22 @@ num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp
 
       /* Arithmetic.  */
     case CPP_MINUS:
-      rhs = num_negate (rhs, precision);
+      result.low = lhs.low - rhs.low;
+      result.high = lhs.high - rhs.high;
+      if (result.low > lhs.low)
+       result.high--;
+      result.unsignedp = lhs.unsignedp || rhs.unsignedp;
+      result.overflow = false;
+
+      result = num_trim (result, precision);
+      if (!result.unsignedp)
+       {
+         bool lhsp = num_positive (lhs, precision);
+         result.overflow = (lhsp != num_positive (rhs, precision)
+                            && lhsp != num_positive (result, precision));
+       }
+      return result;
+
     case CPP_PLUS:
       result.low = lhs.low + rhs.low;
       result.high = lhs.high + rhs.high;
Index: gcc/testsuite/gcc.dg/cpp/expr-overflow-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/expr-overflow-1.c  (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/expr-overflow-1.c  (revision 0)
@@ -0,0 +1,44 @@
+/* Test overflow in preprocessor arithmetic.  PR 55715.  */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c99" } */
+
+#include <stdint.h>
+
+#if -1 - INTMAX_MIN
+#endif
+
+#if 0 - INTMAX_MIN /* { dg-warning "overflow" } */
+#endif
+
+#if 1 * INTMAX_MIN
+#endif
+
+#if -1 * INTMAX_MIN /* { dg-warning "overflow" } */
+#endif
+
+#if 0 * INTMAX_MIN
+#endif
+
+#if -INTMAX_MIN /* { dg-warning "overflow" } */
+#endif
+
+#if +INTMAX_MIN
+#endif
+
+#if INTMAX_MIN / 1
+#endif
+
+#if INTMAX_MIN / -1 /* { dg-warning "overflow" } */
+#endif
+
+#if UINTMAX_MAX * UINTMAX_MAX
+#endif
+
+#if UINTMAX_MAX / -1
+#endif
+
+#if UINTMAX_MAX + INTMAX_MAX
+#endif
+
+#if UINTMAX_MAX - INTMAX_MIN
+#endif

-- 
Joseph S. Myers
jos...@codesourcery.com

Reply via email to