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

Reply via email to