Bug 23618 – Right Shift equals expressions on unsigned shorts should be unsigned right shift

Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2023-01-11T03:15:08Z
Last change time
2023-01-14T14:39:45Z
Keywords
backend, pull
Assigned to
No Owner
Creator
mhh

Comments

Comment #0 by maxhaton — 2023-01-11T03:15:08Z
unittest { const ushort tru = 1028; ushort ee = tru; ee <<= 5U; ee >>= 5U; assert(((tru << 5U) >> 5U) == ee); } Seems similar to regression 3583 from 2009
Comment #1 by ibuclaw — 2023-01-14T00:07:10Z
Only affects dmd.
Comment #2 by bugzilla — 2023-01-14T06:50:59Z
The issue comes up because (ee >>= 5) is done as a signed right shift, even though ee is an unsigned type. Step by step: https://dlang.org/spec/expression.html#assignment_operator_expressions says: a op= b are semantically equivalent to: a = cast(typeof(a))(a op b) so, (ee >>= 5) is rewritten to: ee = cast(ushort)(ee >> b); https://dlang.org/spec/expression.html#shift_expressions says: the operands undergo integral promotions ee = cast(ushort)(cast(int)ee >> b) or: ee = cast(ushort)((ee & 0x0000_FFFF) >> b) then: >> is a signed right shift but the sign bit is 0, so it is, in effect, an unsigned right shift. The compiler generates a signed right shift, though.
Comment #3 by salihdb — 2023-01-14T07:12:26Z
The problem is also seen when the sign extension is not done. Here is the test code: struct TestType(T) { import std.traits : Unsigned; alias U = Unsigned!T; T t = T.min; // sample: -128 for byte U u = U.max/2 + 1; // sample: 128 for ubyte } void main() { alias T = long; // int, short, byte TestType!T v1, v2; enum bits = T.sizeof * 8 - 1; v1.t >>= bits; assert(v1.t == -1); // okay, because signed type v1.u >>= bits; assert(v1.u == 1); // okay, because unsigned type v2.t >>>= bits; assert(v2.t == 1); /* okay, no sign extension but -1 for byte, short, int */ v2.u >>>= bits; assert(v2.u == 1); // okay, no sign extension } SDB@79
Comment #4 by dlang-bot — 2023-01-14T07:28:36Z
@WalterBright created dlang/dmd pull request #14814 "fix Issue 23618 - Right Shift equals expressions on unsigned shorts s…" fixing this issue: - fix Issue 23618 - Right Shift equals expressions on unsigned shorts should be unsigned right shift https://github.com/dlang/dmd/pull/14814
Comment #5 by dlang-bot — 2023-01-14T12:18:43Z
dlang/dmd pull request #14814 "fix Issue 23618 - Right Shift equals expressions on unsigned shorts s…" was merged into stable: - 1a7eebc1a52954a56173f098ee5128bfbfe6b746 by Walter Bright: fix Issue 23618 - Right Shift equals expressions on unsigned shorts should be unsigned right shift https://github.com/dlang/dmd/pull/14814
Comment #6 by dlang-bot — 2023-01-14T14:39:45Z
dlang/dmd pull request #14815 "Merge stable" was merged into master: - 579c97ab66ddc2c6a8f3db177937bb4c94353120 by Walter Bright: fix Issue 23618 - Right Shift equals expressions on unsigned shorts should be unsigned right shift (#14814) https://github.com/dlang/dmd/pull/14815