P1236R1 - Signed integers are two's complement
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
This commit is contained in:
parent
12763abc53
commit
8ee099430b
16 changed files with 123 additions and 22 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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".
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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)
|
||||
|
|
25
gcc/testsuite/g++.dg/cpp2a/constexpr-shift1.C
Normal file
25
gcc/testsuite/g++.dg/cpp2a/constexpr-shift1.C
Normal file
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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'" } */
|
||||
|
|
11
gcc/testsuite/g++.dg/ubsan/cxx2a-shift-1.C
Normal file
11
gcc/testsuite/g++.dg/ubsan/cxx2a-shift-1.C
Normal file
|
@ -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);
|
||||
}
|
15
gcc/testsuite/g++.dg/ubsan/cxx2a-shift-2.C
Normal file
15
gcc/testsuite/g++.dg/ubsan/cxx2a-shift-2.C
Normal file
|
@ -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);
|
||||
}
|
|
@ -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 } } }
|
||||
|
|
Loading…
Add table
Reference in a new issue