Hi! I'd like to ping the https://gcc.gnu.org/pipermail/gcc-patches/2025-March/678863.html patch.
Thanks. On Sat, Mar 22, 2025 at 01:33:51AM +0100, Jakub Jelinek wrote: > The libcpp left shift handling implements (partially) the C99-C23 > wording where shifts are UB if shift count is negative, or too large, > or shifting left a negative value or shifting left non-negative value > results in something not representable in the result type (in the > preprocessor case that is intmax_t). > libcpp actually implements left shift by negative count as right shifts > by negation of the count and similarly right shifts by negative count > as left shifts by negation (not ok), sets overflow for too large shift > count (ok), doesn't check for negative values on left shift (not ok) > and checks correctly for the non-representable ones otherwise (ok). > > Now, C++11 to C++17 has different behavior, whereas in C99-C23 1 << 63 > in preprocessor is invalid, in C++11-17 it is valid, but 3 << 63 is > not. The wording is that left shift of negative value is UB (like in C) > and signed non-negative left shift is UB if the result isn't representable > in corresponding unsigned type (so uintmax_t for libcpp). > > And then C++20 and newer says all left shifts are well defined with the > exception of bad shift counts. > > In -fsanitize=undefined we handle these by > /* For signed x << y, in C99 and later, the following: > (unsigned) x >> (uprecm1 - y) > if non-zero, is undefined. */ > and > /* For signed x << y, in C++11 to C++17, the following: > x < 0 || ((unsigned) x >> (uprecm1 - y)) > if > 1, is undefined. */ > > Now, we are late in GCC 15 development, so I think making the preprocessor > more strict than it is now is undesirable, so will defer setting overflow > flag for the shifts by negative count, or shifts by negative value left. > > The following patch just makes some previously incorrectly rejected or > warned cases valid for C++11-17 and even more for C++20 and later. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2025-03-22 Jakub Jelinek <ja...@redhat.com> > > PR preprocessor/119391 > * expr.cc (num_lshift): Add pfile argument. Don't set num.overflow > for !num.unsignedp in C++20 or later unless n >= precision. For > C++11 to C++17 set it if orig >> (precision - 1 - n) as logical > shift results in value > 1. > (num_binary_op): Pass pfile to num_lshift. > (num_div_op): Likewise. > > * g++.dg/cpp/pr119391.C: New test. Jakub