P1236R1 - Signed integers are two's complement
authorJakub Jelinek <jakub@redhat.com>
Wed, 14 Nov 2018 16:46:06 +0000 (17:46 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 14 Nov 2018 16:46:06 +0000 (17:46 +0100)
P1236R1 - Signed integers are two's complement
gcc/cp/
* constexpr.c (cxx_eval_check_shift_p): Disable the signed LSHIFT_EXPR
checks for c++2a.
gcc/c-family/
* c-warn.c (maybe_warn_shift_overflow): Don't warn for c++2a.
* c-ubsan.c (ubsan_instrument_shift): Make signed shifts
with in-range second operand well defined for -std=c++2a.
gcc/
* doc/invoke.texi (Wshift-overflow): Adjust documentation for
c++2a.
gcc/testsuite/
* g++.dg/cpp2a/constexpr-shift1.C: New test.
* g++.dg/warn/permissive-1.C (enum A, enum D): Don't expect
diagnostics here for c++2a.
* g++.dg/cpp0x/constexpr-shift1.C (fn3, i3, fn4, i4): Don't expect
diagnostics here for c++2a.
* g++.dg/cpp0x/constexpr-60049.C (f3, x3, y3): Likewise.
* g++.dg/ubsan/cxx11-shift-1.C (main): Add some further tests.
* g++.dg/ubsan/cxx11-shift-2.C (main): Likewise.
* g++.dg/ubsan/cxx2a-shift-1.C: New test.
* g++.dg/ubsan/cxx2a-shift-2.C: New test.

From-SVN: r266153

16 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-ubsan.c
gcc/c-family/c-warn.c
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-60049.C
gcc/testsuite/g++.dg/cpp0x/constexpr-shift1.C
gcc/testsuite/g++.dg/cpp2a/constexpr-shift1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/cxx11-shift-1.C
gcc/testsuite/g++.dg/ubsan/cxx11-shift-2.C
gcc/testsuite/g++.dg/ubsan/cxx2a-shift-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/cxx2a-shift-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/permissive-1.C

index ae27a137d15aa2fd08e9f6a927e923beeee48137..fb28a7d585a76855a7158d835459e5581f813f46 100644 (file)
@@ -1,5 +1,9 @@
 2018-11-14  Jakub Jelinek  <jakub@redhat.com>
 
+       P1236R1 - Signed integers are two's complement
+       * doc/invoke.texi (Wshift-overflow): Adjust documentation for
+       c++2a.
+
        PR bootstrap/86739
        * hash-map.h (hash_map::iterator::reference_pair): New class.
        (hash_map::iterator::operator*): Return it rather than std::pair.
index 94b823fe39898ac04b7c2d8bff8d9601bbff225a..eadad49615673c4bb3d6cce2d968a1d4fe95b710 100644 (file)
@@ -1,5 +1,10 @@
 2018-11-14  Jakub Jelinek  <jakub@redhat.com>
 
+       P1236R1 - Signed integers are two's complement
+       * c-warn.c (maybe_warn_shift_overflow): Don't warn for c++2a.
+       * c-ubsan.c (ubsan_instrument_shift): Make signed shifts
+       with in-range second operand well defined for -std=c++2a.
+
        PR other/88007
        * c-common.c (parse_optimize_options): Allocate option string from
        opts_obstack rather than as GC memory.  Move the allocation after
index ae6e25043bf868681d087bd2b11dbbb62d4582e0..4ef2bd80cfedc952382186f3e4b699b3a4ffeb13 100644 (file)
@@ -134,7 +134,10 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
   if (TYPE_OVERFLOW_WRAPS (type0)
       || maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (type0)),
                   TYPE_PRECISION (type0))
-      || !sanitize_flags_p (SANITIZE_SHIFT_BASE))
+      || !sanitize_flags_p (SANITIZE_SHIFT_BASE)
+      /* In C++2a and later, shifts are well defined except when
+        the second operand is not within bounds.  */
+      || cxx_dialect >= cxx2a)
     ;
 
   /* For signed x << y, in C99/C11, the following:
index a1a7f9359644c6d635854e2bc2e03d92e122762d..93c343a438428075b336435ba43f4b7517c9ca37 100644 (file)
@@ -2286,6 +2286,8 @@ diagnose_mismatched_attributes (tree olddecl, tree newdecl)
 /* Warn if signed left shift overflows.  We don't warn
    about left-shifting 1 into the sign bit in C++14; cf.
    <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3367.html#1457>
+   and don't warn for C++2a at all, as signed left shifts never
+   overflow.
    LOC is a location of the shift; OP0 and OP1 are the operands.
    Return true if an overflow is detected, false otherwise.  */
 
@@ -2300,7 +2302,7 @@ maybe_warn_shift_overflow (location_t loc, tree op0, tree op1)
   unsigned int prec0 = TYPE_PRECISION (type0);
 
   /* Left-hand operand must be signed.  */
-  if (TYPE_UNSIGNED (type0))
+  if (TYPE_UNSIGNED (type0) || cxx_dialect >= cxx2a)
     return false;
 
   unsigned int min_prec = (wi::min_precision (wi::to_wide (op0), SIGNED)
@@ -2309,7 +2311,7 @@ maybe_warn_shift_overflow (location_t loc, tree op0, tree op1)
    * However, shifting 1 _out_ of the sign bit, as in
    * INT_MIN << 1, is considered an overflow.
    */
-  if (!tree_int_cst_sign_bit(op0) && min_prec == prec0 + 1)
+  if (!tree_int_cst_sign_bit (op0) && min_prec == prec0 + 1)
     {
       /* Never warn for C++14 onwards.  */
       if (cxx_dialect >= cxx14)
index 1587b49e7dd341baf9ffffd8cac9a73f20cc37df..ee5c2ce844622a2a432b28d5da14c383780179f5 100644 (file)
@@ -1,3 +1,9 @@
+2018-11-14  Jakub Jelinek  <jakub@redhat.com>
+
+       P1236R1 - Signed integers are two's complement
+       * constexpr.c (cxx_eval_check_shift_p): Disable the signed LSHIFT_EXPR
+       checks for c++2a.
+
 2018-11-13  David Malcolm  <dmalcolm@redhat.com>
 
        * call.c: Replace "source_location" with "location_t".
index 7b696da5834bb3dfddb0f94791371d380b75cf1d..a50e186148d93edcb20740aa0a3472a6e5d2fa99 100644 (file)
@@ -1920,9 +1920,14 @@ cxx_eval_check_shift_p (location_t loc, const constexpr_ctx *ctx,
      if E1 has a signed type and non-negative value, and E1x2^E2 is
      representable in the corresponding unsigned type of the result type,
      then that value, converted to the result type, is the resulting value;
-     otherwise, the behavior is undefined.  */
-  if (code == LSHIFT_EXPR && !TYPE_UNSIGNED (lhstype)
-      && (cxx_dialect >= cxx11))
+     otherwise, the behavior is undefined.
+     For C++2a:
+     The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo
+     2^N, where N is the range exponent of the type of the result.  */
+  if (code == LSHIFT_EXPR
+      && !TYPE_UNSIGNED (lhstype)
+      && cxx_dialect >= cxx11
+      && cxx_dialect < cxx2a)
     {
       if (tree_int_cst_sgn (lhs) == -1)
        {
index 283d20fa29620c703991e344d80eefb5af5a9acd..ea730b61c05dbff67972e0baef574713c32dcbfd 100644 (file)
@@ -5074,11 +5074,12 @@ This is the warning level of @option{-Wshift-overflow} and is enabled
 by default in C99 and C++11 modes (and newer).  This warning level does
 not warn about left-shifting 1 into the sign bit.  (However, in C, such
 an overflow is still rejected in contexts where an integer constant expression
-is required.)
+is required.)  No warning is emitted in C++2A mode (and newer), as signed left
+shifts always wrap.
 
 @item -Wshift-overflow=2
 This warning level also warns about left-shifting 1 into the sign bit,
-unless C++14 mode is active.
+unless C++14 mode (or newer) is active.
 @end table
 
 @item -Wswitch
index cee33796cc57658d2e0ed15748a26f64c840af27..a94cb786840c0e0eca821a37602ae050c8a6dace 100644 (file)
@@ -1,3 +1,17 @@
+2018-11-14  Jakub Jelinek  <jakub@redhat.com>
+
+       P1236R1 - Signed integers are two's complement
+       * g++.dg/cpp2a/constexpr-shift1.C: New test.
+       * g++.dg/warn/permissive-1.C (enum A, enum D): Don't expect
+       diagnostics here for c++2a.
+       * g++.dg/cpp0x/constexpr-shift1.C (fn3, i3, fn4, i4): Don't expect
+       diagnostics here for c++2a.
+       * g++.dg/cpp0x/constexpr-60049.C (f3, x3, y3): Likewise.
+       * g++.dg/ubsan/cxx11-shift-1.C (main): Add some further tests.
+       * g++.dg/ubsan/cxx11-shift-2.C (main): Likewise.
+       * g++.dg/ubsan/cxx2a-shift-1.C: New test.
+       * g++.dg/ubsan/cxx2a-shift-2.C: New test.
+
 2018-11-14  Jeff Law  <law@redhat.com>
 
        * gcc.c-torture/compile/20181114.c: New test.
index 172963f1fc4ab12f8e3a4fbe8e41b3f7be42d0d5..8400910f0512830487fa286cf69a4b3910406a9a 100644 (file)
@@ -5,7 +5,7 @@
 
 constexpr int f1 (int n) { return 1 << n; }   // { dg-error "shift expression" }
 constexpr int f2 (int n) { return 1 << n; }   // { dg-error "shift expression" }
-constexpr int f3 (int n) { return n << 1; }   // { dg-error "shift expression" }
+constexpr int f3 (int n) { return n << 1; }   // { dg-error "shift expression" "" { target c++17_down } }
 constexpr int f4 (int n) { return 1 >> n; }   // { dg-error "shift expression" }
 constexpr int f5 (int n) { return 1 >> n; }   // { dg-error "shift expression" }
 
@@ -13,12 +13,12 @@ constexpr int X = __CHAR_BIT__ * sizeof (int) + 1;
 
 constexpr int x1 = f1 (X);    // { dg-message "in .constexpr. expansion of" }
 constexpr int x2 = f2 (-1);   // { dg-message "in .constexpr. expansion of" }
-constexpr int x3 = f3 (-1);   // { dg-message "in .constexpr. expansion of" }
+constexpr int x3 = f3 (-1);   // { dg-message "in .constexpr. expansion of" "" { target c++17_down } }
 constexpr int x4 = f4 (X);    // { dg-message "in .constexpr. expansion of" }
 constexpr int x5 = f5 (-1);   // { dg-message "in .constexpr. expansion of" }
 
 constexpr int y1 =  1 << X;   // { dg-error "shift expression" }
 constexpr int y2 =  1 << -1;  // { dg-error "shift expression" }
-constexpr int y3 = -1 << 1;   // { dg-error "shift expression" }
+constexpr int y3 = -1 << 1;   // { dg-error "shift expression" "" { target c++17_down } }
 constexpr int y4 =  1 >> X;   // { dg-error "shift expression" }
 constexpr int y5 =  1 >> -1;  // { dg-error "shift expression" }
index 4abd9e0cfb6bf6e15a49971f6959e906bcab3828..c1cfb1eebdb4a3f521fc335ecb3edd6c70a282e7 100644 (file)
@@ -19,18 +19,18 @@ constexpr int i2 = fn2 (1, 200); // { dg-message "in .constexpr. expansion of "
 constexpr int
 fn3 (int i, int j)
 {
-  return i << j; // { dg-error "is negative" }
+  return i << j; // { dg-error "is negative" "" { target c++17_down } }
 }
 
-constexpr int i3 = fn3 (-1, 2); // { dg-message "in .constexpr. expansion of " }
+constexpr int i3 = fn3 (-1, 2); // { dg-message "in .constexpr. expansion of " "" { target c++17_down } }
 
 constexpr int
 fn4 (int i, int j)
 {
-  return i << j; // { dg-error "overflows" }
+  return i << j; // { dg-error "overflows" "" { target c++17_down } }
 }
 
-constexpr int i4 = fn4 (__INT_MAX__, 2); // { dg-message "in .constexpr. expansion of " }
+constexpr int i4 = fn4 (__INT_MAX__, 2); // { dg-message "in .constexpr. expansion of " "" { target c++17_down } }
 
 constexpr int
 fn5 (int i, int j)
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-shift1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-shift1.C
new file mode 100644 (file)
index 0000000..abe15e7
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++11 } }
+
+constexpr int a = -42 << 0;    // { dg-error "left operand of shift expression '\\(-42 << 0\\)' is negative" "" { target c++17_down } }
+constexpr int b = -42 << 1;    // { dg-error "left operand of shift expression '\\(-42 << 1\\)' is negative" "" { target c++17_down } }
+constexpr int c = -42 << (__SIZEOF_INT__ * __CHAR_BIT__ - 1);  // { dg-error "left operand of shift expression '\\(-42 << \[0-9]*\\)' is negative" "" { target c++17_down } }
+                               // { dg-warning "result of '\\(-42 << \[0-9]*\\)' requires \[0-9]* bits to represent, but 'int' only has \[0-9]* bits" "" { target c++17_down } .-1 }
+constexpr int d = 42 << (__SIZEOF_INT__ * __CHAR_BIT__ - 1);   // { dg-error "shift expression '\\(42 << \[0-9]*\\)' overflows" "" { target c++17_down } }
+                               // { dg-warning "result of '\\(42 << \[0-9]*\\)' requires \[0-9]* bits to represent, but 'int' only has \[0-9]* bits" "" { target c++17_down } .-1 }
+constexpr int e = 32 << (__SIZEOF_INT__ * __CHAR_BIT__ - 5);   // { dg-error "shift expression '\\(32 << \[0-9]*\\)' overflows" "" { target c++17_down } }
+                               // { dg-warning "result of '\\(32 << \[0-9]*\\)' requires \[0-9]* bits to represent, but 'int' only has \[0-9]* bits" "" { target c++17_down } .-1 }
+constexpr int f = 32 << (__SIZEOF_INT__ * __CHAR_BIT__ - 6);
+constexpr int g = -42U << 0;
+constexpr int h = -42U << 1;
+constexpr int i = -42U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1);
+constexpr int j = 42U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1);
+constexpr int k = 32U << (__SIZEOF_INT__ * __CHAR_BIT__ - 5);
+constexpr int l = 32U << (__SIZEOF_INT__ * __CHAR_BIT__ - 6);
+#if __cplusplus > 201703L
+static_assert (a == g);
+static_assert (b == h);
+static_assert (c == i);
+static_assert (d == j);
+static_assert (e == k);
+static_assert (f == l);
+#endif
index 431eab12d3e414e55df3225f7925b72b92b6486c..7e998885c9f63daea665ae8705ae4b710fa79b23 100644 (file)
@@ -2,9 +2,10 @@
 /* { dg-options "-fsanitize=shift -w -fno-sanitize-recover=shift -std=c++11" } */
 
 int
-main (void)
+main ()
 {
   int a = 1;
-  a <<= 31;
-  return 0;
+  a <<= (__SIZEOF_INT__ * __CHAR_BIT__ - 1);
+  a = 16;
+  a <<= (__SIZEOF_INT__ * __CHAR_BIT__ - 5);
 }
index fbc16dfd3d8d1f27c5a128e1c4db6c7fe281d035..d104ead41758ccd2d66d437cdab357811fcc5851 100644 (file)
@@ -2,9 +2,18 @@
 /* { dg-options "-fsanitize=shift -w -std=c++11" } */
 
 int
-main (void)
+main ()
 {
   int a = -42;
   a <<= 1;
+  a = -43;
+  a <<= 0;
+  a = -44;
+  a <<= (__SIZEOF_INT__ * __CHAR_BIT__ - 1);
+  a = 32;
+  a <<= (__SIZEOF_INT__ * __CHAR_BIT__ - 3);
 }
-/* { dg-output "left shift of negative value -42" } */
+/* { dg-output "left shift of negative value -42.*" } */
+/* { dg-output "left shift of negative value -43.*" } */
+/* { dg-output "left shift of negative value -44.*" } */
+/* { dg-output "left shift of 32 by \[0-9]* places cannot be represented in type 'int'" } */
diff --git a/gcc/testsuite/g++.dg/ubsan/cxx2a-shift-1.C b/gcc/testsuite/g++.dg/ubsan/cxx2a-shift-1.C
new file mode 100644 (file)
index 0000000..2094cb1
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover=shift -std=c++2a" } */
+
+int
+main ()
+{
+  int a = 1;
+  a <<= 31;
+  a = 16;
+  a <<= (__SIZEOF_INT__ * __CHAR_BIT__ - 5);
+}
diff --git a/gcc/testsuite/g++.dg/ubsan/cxx2a-shift-2.C b/gcc/testsuite/g++.dg/ubsan/cxx2a-shift-2.C
new file mode 100644 (file)
index 0000000..5a56410
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -w -fno-sanitize-recover=shift -std=c++2a" } */
+
+int
+main ()
+{
+  int a = -42;
+  a <<= 1;
+  a = -43;
+  a <<= 0;
+  a = -44;
+  a <<= (__SIZEOF_INT__ * __CHAR_BIT__ - 1);
+  a = 32;
+  a <<= (__SIZEOF_INT__ * __CHAR_BIT__ - 3);
+}
index bfaca7637824560c4511308e047a14ccc60b829e..387af606b26a9c5dc5d94a5f85f500355258b7c7 100644 (file)
@@ -2,7 +2,7 @@
 // { dg-do compile { target int32 } }
 // { dg-options "-fpermissive -Wno-shift-overflow -Wno-shift-count-overflow -Wno-shift-count-negative" }
 
-enum A { AA = -1 << 4 }; // { dg-warning "operand of shift expression" "" { target c++11 } }
+enum A { AA = -1 << 4 }; // { dg-warning "operand of shift expression" "" { target { c++11 && c++17_down } } }
 enum B { BB = 1 << -4 }; // { dg-warning "operand of shift expression" }
 enum C { CC = 1 << __SIZEOF_INT__ * 4 * __CHAR_BIT__ - 4 }; // { dg-warning "operand of shift expression" }
-enum D { DD = 10 << __SIZEOF_INT__ * __CHAR_BIT__ - 2 }; // { dg-warning "shift expression" "" { target c++11 } }
+enum D { DD = 10 << __SIZEOF_INT__ * __CHAR_BIT__ - 2 }; // { dg-warning "shift expression" "" { target { c++11 && c++17_down } } }