Marcin Grzegorczyk said:
Keith Thompson wrote:
[snip]
Yes, in (1 << n), the type of the result is int, and it exhibits
UB if n >= the width of int.
As a matter of nitpick, it actually exhibits UB if n >= the *precision*
of int.
Hmm. I think you're right (specifically when the left operand is 1).
For concreteness, let's assume 16-bit int with a range of
-32768..+32767 (and no padding bits, though I don't think that
matters here). So the precision of int is 15, and the width is 16.
C99 6.5.7p3:
The integer promotions are performed on each of the operands. The
type of the result is that of the promoted left operand. If the
value of the right operand is negative or is greater than or
equal to the width of the promoted left operand, the behavior
is undefined.
p4:
[...] If E1 has a signed type and nonnegative value, and
E1 * 2^E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.
Neither (1 << 15) nor (1 << 16) violates p3, since both 15 and 16 are
less than or equal to the width. But they both violate p4, since the
mathematical results are 32768 and 65536, respectively, neither of which
is representable in int.
(1 << 15) --> 32768, violates p4, UB
(1 << 16) --> 65536, violates p4, UB
(1 << 17) --> 131072, violates both p3 and p4, UB
(0 << 15) --> 0, ok
(0 << 16) --> 0, ok
(0 << 17) --> 0, but violates p3, UB
(1u << 15) --> 32768, ok
(1u << 16) --> 65536, reduced to 0, ok
(1u << 17) --> 131072, but violates p3, UB
(I've lost count of the number of off-by-one errors I've committed
while revising this post.)