https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119391
--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Looking more, seems like there are many bugs on the preprocessor side related
to shifts.

My reading of C89 and C++98 is that it doesn't really tell what happens for
left shift if E1 has signed type, just says that shift by negative count or
larger or equal to precision is UB and then has:
"The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted E2 bit
positions; vacated bits are zero-filled. If E1 has an unsigned type, the value
of the result is E1 multiplied by the quantity 2 raised to the power E2,
reduced modulo ULONG_MAX+1 if E1 has type unsigned long, UINT_MAX+1 otherwise."
C99 through C23 say the same for count and it is also UB to shift left any
negative values and UB if E1 << E2 is not representable in the result type.
C++11 through C++17 have the same for count and UB to shift left any negative
values and UB if E1 << E2 is not representable in unsigned type corresponding
to the result type (then the result is converted to that).
And finally C++20 and later has only UB on bad counts.

Now, what libcpp implements is, negative shift counts are silently treated as
shifts in the other direction by the negation of the value.
There is no check for left shift of negative values (invalid for at least
C99-C2Y and C++11-C++17).
Otherwise, the implementation matches the C99-23-ish requirement that E1x2^E2
needs to be representable in the result type.

IMHO it is too late for changing this to be more strict in GCC 15 but perhaps
we should change it so that it doesn't reject what shouldn't be rejected in
C++11..C++26.

#if __cplusplus  >= 201103L
#define C constexpr
#else
#define C const
#endif
C long long a = -1LL << 0;
C long long b = -1LL << 2;
C long long c = -1LL << 62;
C long long d = -1LL << 63;
C long long e = -1LL << 64;
C long long f = 3LL << 61;
C long long g = 3LL << 62;
C long long h = 3LL << 63;
C long long i = 4LL << -1;
#if (-1 << 0) != -1
#endif
#if (-1 << 2) != -1
#endif
#if (-1 << 62) != -4611686018427387904
#endif
#if (-1 << 63) != -9223372036854775807 - 1
#endif
#if (-1 << 64) != 0
#endif
#if (3 << 61) != 6917529027641081856
#endif
#if (3 << 62) != -4611686018427387904
#endif
#if (3 << 63) != -9223372036854775807 - 1
#endif
#if (4 << -1) != 2
#endif

Reply via email to