There was a recent off-by-one bug in Phobos, where toChars was incorrectly slicing its result:
https://issues.dlang.org/show_bug.cgi?id=16192
It ended up right-shifting by a negative number and I wondered why dmd didn't warn about this. I see now that static analysis or a runtime check is not done with such functions, so the compiler doesn't know and the binary can't tell you what went wrong at runtime.
However, when creating an equivalent test to see what's going on, I seem to have stumbled on another inlining/optimization combo bug in dmd.
Here's the code I wrote to mimic the toChars issue linked above:
int check_shift(int x) { return 16 >>> ((2 - x) * 4);}
unittest
{
assert(check_shift(3) == 16);
//assert(( 16 >>> (2-3) * 4) == 16);
}
If the second assert isn't commented out, dmd always evaluates that expression at compile-time and gives this error:
shift.d(5): Error: shift by -4 is outside the range 0..31
If it's left commented out and the file is compiled with this command,
./2.071.1/linux/bin64/dmd -O -unittest -main shift.d
the resulting binary asserts at runtime on line 4, ie the first assert. If I compile again with inlining,
./2.071.1/linux/bin64/dmd -O -inline -unittest -main shift.d
the test passes, because the entire unittest block is "optimized" out, ie it's simply removed from the resulting assembly:
0000000000422b80 <_D5shift14__unittestL2_1FZv>:
422b80: 50 push %rax
422b81: 58 pop %rax
422b82: c3 retq
422b83: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
This doesn't happen with inlining alone, the binary asserts there. The problem is reproducible with dmd 2.063.2 on linux/x64 also, which is the oldest dmd I had lying around. Fwiw, ldc 1.0.0 for linux/x64 also passes the test if optimization and inlining are enabled.
Comment #1 by robert.schadek — 2024-12-13T18:48:44Z