digitalmars.D - phobos's circle CI runs a busted version of DMD
- deadalnix (11/11) Jan 10 2023 Sample code:
- Max Haughton (3/14) Jan 10 2023 https://godbolt.org/z/M3fGE9bqY
- Dom DiSc (3/11) Jan 11 2023 Ok, so Godbolt also runs a busted version of DMD?
- deadalnix (3/8) Jan 11 2023 Congratulation for understanding exactly backward. 64516 is not a
- max haughton (4/19) Jan 11 2023 Success here merely means that it compiled.
- Dukc (8/19) Jan 11 2023 [The spec
- jmh530 (20/42) Jan 11 2023 Not really. If you just do `>>` (i.e. not `>>=`), then you get
- jmh530 (18/62) Jan 11 2023 Upon further investigation, the problem goes away when you cast
- Paul Backus (13/24) Jan 11 2023 The relevant section of the spec here is the one about
- jmh530 (2/7) Jan 11 2023 So someone file a bug report...
- max haughton (2/11) Jan 11 2023 I filed one last night
- Walter Bright (2/3) Jan 11 2023 Thank you. Link?
- max haughton (3/6) Jan 11 2023 https://issues.dlang.org/show_bug.cgi?id=23618
- Walter Bright (2/12) Jan 11 2023 That's right. It also happens for ubyte operations.
- Salih Dincer (22/34) Jan 11 2023 ```d
- =?UTF-8?Q?Ali_=c3=87ehreli?= (16/21) Jan 11 2023 Yes but it shouldn't because one of the operands is uint and the 'int'
- Salih Dincer (29/34) Jan 12 2023 Deadalnix is RIGHT!
- deadalnix (3/11) Jan 11 2023 Signed right shift is the same as logical right shift for
- =?UTF-8?Q?Ali_=c3=87ehreli?= (7/14) Jan 11 2023 On 1/10/23 17:03, deadalnix wrote:
- Walter Bright (1/1) Jan 14 2023 https://github.com/dlang/dmd/pull/14814
Sample code: ```d ushort ee = 1028; ee <<= 5U; ee >>= 5U; writeln(ee); ``` Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.
Jan 10 2023
On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:Sample code: ```d ushort ee = 1028; ee <<= 5U; ee >>= 5U; writeln(ee); ``` Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.https://godbolt.org/z/M3fGE9bqY "All versions: Success with output: 64516" from run.dlang.io
Jan 10 2023
On Wednesday, 11 January 2023 at 02:50:52 UTC, Max Haughton wrote:On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:Ok, so Godbolt also runs a busted version of DMD? And why counts 64516 as a success here?!?!Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.https://godbolt.org/z/M3fGE9bqY "All versions: Success with output: 64516" from run.dlang.io
Jan 11 2023
On Wednesday, 11 January 2023 at 11:04:50 UTC, Dom DiSc wrote:Congratulation for understanding exactly backward. 64516 is not a success, it is a failure.https://godbolt.org/z/M3fGE9bqY "All versions: Success with output: 64516" from run.dlang.ioOk, so Godbolt also runs a busted version of DMD? And why counts 64516 as a success here?!?!
Jan 11 2023
On Wednesday, 11 January 2023 at 11:04:50 UTC, Dom DiSc wrote:On Wednesday, 11 January 2023 at 02:50:52 UTC, Max Haughton wrote:Success here merely means that it compiled. The "run with all dmd versions" mode is aimed for finding regressions and so on.On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:Ok, so Godbolt also runs a busted version of DMD? And why counts 64516 as a success here?!?!Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.https://godbolt.org/z/M3fGE9bqY "All versions: Success with output: 64516" from run.dlang.io
Jan 11 2023
On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:Sample code: ```d ushort ee = 1028; ee <<= 5U; ee >>= 5U; writeln(ee); ``` Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.[The spec says](https://dlang.org/spec/expression.html#shift_expressions) that `>>` means *signed* shift right. `>>>` is for unsigned shifts. So pedantically speaking, 64516 is the correct result. It's another issue whether that's good design though. For one, it breaks the rule "do what C does, or don't compile". It'd be more reasonable if `>>` was type-dependant shift right (as in C) IMO.
Jan 11 2023
On Wednesday, 11 January 2023 at 13:26:57 UTC, Dukc wrote:On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:Not really. If you just do `>>` (i.e. not `>>=`), then you get 1028. ```d import core.stdc.stdio: printf; void main() { ushort ee = 32896; //starting from the second shift ushort ee_result = ee >> 5u; printf("the value of ee_result is %d\n", ee_result); //the value of ee_result is 1028 } ``` The problem is the combination with assignment, which is what makes it seem like a bug. According to [1], "the right operand is implicitly converted to the type of the left operand, and assigned to it." So what should happen is that `5U` is implicitly converted to `5` and a signed conversion should happen. The result should be 1028. 64516 seems like a weird result. [1] https://dlang.org/spec/expression.html#simple_assignment_expressionsSample code: ```d ushort ee = 1028; ee <<= 5U; ee >>= 5U; writeln(ee); ``` Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.[The spec says](https://dlang.org/spec/expression.html#shift_expressions) that `>>` means *signed* shift right. `>>>` is for unsigned shifts. So pedantically speaking, 64516 is the correct result. It's another issue whether that's good design though. For one, it breaks the rule "do what C does, or don't compile". It'd be more reasonable if `>>` was type-dependant shift right (as in C) IMO.
Jan 11 2023
On Wednesday, 11 January 2023 at 13:51:43 UTC, jmh530 wrote:On Wednesday, 11 January 2023 at 13:26:57 UTC, Dukc wrote:Upon further investigation, the problem goes away when you cast `5u` to ushort (since `5u` is a uint and not a ushort). ```d import core.stdc.stdio: printf; void main() { ushort ee = 32896; //starting from the second shift ee >>= (cast(ushort) 5u); printf("the value of ee is %d\n", ee); //the value of ee is 1028 } ``` Not quite sure why the problem is there for the uint and not the ushort, but it could be related to the sequence of integer promotion and the casting. What happens seems inconsistent with the spec. One weird thing is that if you change the cast from ushort to ulong, then we don't have the problem. It is only uint where we get the weird result.On Wednesday, 11 January 2023 at 01:03:33 UTC, deadalnix wrote:Not really. If you just do `>>` (i.e. not `>>=`), then you get 1028. ```d import core.stdc.stdio: printf; void main() { ushort ee = 32896; //starting from the second shift ushort ee_result = ee >> 5u; printf("the value of ee_result is %d\n", ee_result); //the value of ee_result is 1028 } ``` The problem is the combination with assignment, which is what makes it seem like a bug. According to [1], "the right operand is implicitly converted to the type of the left operand, and assigned to it." So what should happen is that `5U` is implicitly converted to `5` and a signed conversion should happen. The result should be 1028. 64516 seems like a weird result. [1] https://dlang.org/spec/expression.html#simple_assignment_expressionsSample code: ```d ushort ee = 1028; ee <<= 5U; ee >>= 5U; writeln(ee); ``` Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.[The spec says](https://dlang.org/spec/expression.html#shift_expressions) that `>>` means *signed* shift right. `>>>` is for unsigned shifts. So pedantically speaking, 64516 is the correct result. It's another issue whether that's good design though. For one, it breaks the rule "do what C does, or don't compile". It'd be more reasonable if `>>` was type-dependant shift right (as in C) IMO.
Jan 11 2023
On Wednesday, 11 January 2023 at 13:51:43 UTC, jmh530 wrote:The problem is the combination with assignment, which is what makes it seem like a bug. According to [1], "the right operand is implicitly converted to the type of the left operand, and assigned to it." [1] https://dlang.org/spec/expression.html#simple_assignment_expressionsThe relevant section of the spec here is the one about "Assignment Operator Expressions" [2], which states thatFor arguments of built-in types, assignment operator expressions such as a op= b are semantically equivalent to: a = cast(typeof(a))(a op b)If we rewrite deadalnix's example using this equivalence, we get the following code: ushort ee = 1028; ee = cast(ushort)(ee << 5U); ee = cast(ushort)(ee >> 5U); writeln(ee); ...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec. [2] https://dlang.org/spec/expression.html#assignment_operator_expressions
Jan 11 2023
On Wednesday, 11 January 2023 at 20:55:33 UTC, Paul Backus wrote:[snip] ...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec. [2] https://dlang.org/spec/expression.html#assignment_operator_expressionsSo someone file a bug report...
Jan 11 2023
On Wednesday, 11 January 2023 at 20:57:00 UTC, jmh530 wrote:On Wednesday, 11 January 2023 at 20:55:33 UTC, Paul Backus wrote:I filed one last night[snip] ...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec. [2] https://dlang.org/spec/expression.html#assignment_operator_expressionsSo someone file a bug report...
Jan 11 2023
On 1/11/2023 2:31 PM, max haughton wrote:I filed one last nightThank you. Link?
Jan 11 2023
On Wednesday, 11 January 2023 at 23:22:45 UTC, Walter Bright wrote:On 1/11/2023 2:31 PM, max haughton wrote:https://issues.dlang.org/show_bug.cgi?id=23618I filed one last nightThank you. Link?
Jan 11 2023
On Thursday, 12 January 2023 at 02:05:14 UTC, max haughton wrote:On Wednesday, 11 January 2023 at 23:22:45 UTC, Walter Bright wrote:It must be noted that the problem seems to be fixed in recent compiler, but CircleCI uses a compiler that is busted. The reason I did not go the bug repport road is because I expect this bug to be marked as fixed because it is indeed fixed, but that wouldn't address the CircleCI issue.On 1/11/2023 2:31 PM, max haughton wrote:https://issues.dlang.org/show_bug.cgi?id=23618I filed one last nightThank you. Link?
Jan 12 2023
On Thursday, 12 January 2023 at 08:55:50 UTC, deadalnix wrote:[...] I expect this bug to be marked as fixed because it is indeed fixed, [...]``` $ dmd --version DMD64 D Compiler v2.101.1 Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved written by Walter Bright $ cat bug23618.d unittest { ubyte ub; ub = 0x80; ub >>= 1u; assert (ub == 0x40); ushort us; us = 0x8000; us >>= 1u; assert (us == 0x4000); } $ dmd -O -checkaction=context -unittest -main -run bug23618.d 1 modules passed unittests $ dmd -checkaction=context -unittest -main -run bug23618.d bug23618.d(5): [unittest] 192 != 64 1/1 modules FAILED unittests ```
Jan 12 2023
On 1/11/2023 12:55 PM, Paul Backus wrote:If we rewrite deadalnix's example using this equivalence, we get the following code: ushort ee = 1028; ee = cast(ushort)(ee << 5U); ee = cast(ushort)(ee >> 5U); writeln(ee); ...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec.That's right. It also happens for ubyte operations.
Jan 11 2023
On Wednesday, 11 January 2023 at 23:22:04 UTC, Walter Bright wrote:On 1/11/2023 12:55 PM, Paul Backus wrote:```d ubyte u = 128; u.writef!"%08b: "; writeln(u); typeof(u >> 1U).stringof.writeln; u >>= 1U; u.writef!"%08b: "; writeln(u); byte b = -128; b.writef!"%08b: "; writeln(b); typeof(b >> 1U).stringof.writeln; b >>= 1U; b.writef!"%08b: "; writeln(b); ``` The problem is that it shift via int first. Then the type is converted to whatever it is, right? I think there is no error because >>> should be used instead of >> ```d u >>>= 1U; assert( u == 64 ); ``` SDB 79If we rewrite deadalnix's example using this equivalence, we get the following code: ushort ee = 1028; ee = cast(ushort)(ee << 5U); ee = cast(ushort)(ee >> 5U); writeln(ee); ...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec.That's right. It also happens for ubyte operations.
Jan 11 2023
On 1/11/23 15:54, Salih Dincer wrote:The problem is that it shift via int first.Yes but it shouldn't because one of the operands is uint and the 'int' operand should be converted to uint and the operation should have uint semantics.I think there is no errorThis is a bug because the >> operator should not perform sign extension for unsigned types.because >>> should be used instead of >>import std; void main() { int i = 0x8000_0000; assert(i >> 31 == 0xffff_ffff); // sign extended assert(i >>> 31 == 0x0000_0001); // different for int uint u = 0x8000_0000; assert(u >> 31 == 0x0000_0001); // no extension assert(u >>> 31 == 0x0000_0001); // no difference for uint } Alicould be used but it is the same as >> operator for unsigned types.
Jan 11 2023
On Thursday, 12 January 2023 at 04:01:13 UTC, Ali Çehreli wrote:On 1/11/23 15:54, Salih Dincer wrote:Deadalnix is RIGHT! Interestingly, triple shifting (>>>) does not work correctly on any type, except long! ```d 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 79The problem is that it shift via int first.Yes but it shouldn't because one of the operands is uint and the 'int' operand should be converted to uint and the operation should have uint semantics.
Jan 12 2023
On Wednesday, 11 January 2023 at 13:26:57 UTC, Dukc wrote:[The spec says](https://dlang.org/spec/expression.html#shift_expressions) that `>>` means *signed* shift right. `>>>` is for unsigned shifts. So pedantically speaking, 64516 is the correct result. It's another issue whether that's good design though. For one, it breaks the rule "do what C does, or don't compile". It'd be more reasonable if `>>` was type-dependant shift right (as in C) IMO.Signed right shift is the same as logical right shift for unsigned integrals.
Jan 11 2023
On 1/10/23 17:03, deadalnix wrote: I am following the code with "Integer Promotions" open: https://dlang.org/spec/type.html#integer-promotionsushort ee = 1028; ee <<= 5U; ee >>= 5U;ee is promoted to 'int' for both operations. 5U is uint. According to documentation above, 'int' should be converted to 'uint'.Regular compiler: https://godbolt.org/z/TcbjP76fW (prints 1028) Circle CI: 64516 . Someone, the compiler manages to do a signed arithmetic shift on an unsigned.I agree, this is a bug. Ali
Jan 11 2023
https://github.com/dlang/dmd/pull/14814
Jan 14 2023